본문 바로가기

web/Django

pytest 시 여러개의 디비 사용하기

참고로 pytest-django 에서 여러개의 디비를 사용하도록 하는 공식적인 버전은 4.3.0 부터 입니다.

해당 버전이 아닐경우 다른 결과가 나올수 있습니다.

 

 

1. 테스트 격리!

일단 나의 진행중인 프로젝트에서는 하나의 django에서 4개의 디비를 바라보고 있다. (........)

사실 한 프로젝트에서 여러개의 디비를 사용하는게 이상한 설계인데, SPOF나기 딱 좋은 지점이기 때문이고, 관리도 어렵다.

특히나 테스트시에는 디비를 않쓰는게 가장 베스트이고 (외부 연결점이 없을수록 격리성이 좋다)

테스트시에 디비를 어쩔수 써야 한다면

1번 디비를 테스트 -> 2번 디비를 테스트 -> .. 하는 식으로 단 하나의 디비만을 테스트 하는것을 추천한다.

각 디비를 초기화 및 셋팅하는데 걸리는 시간과 각각의 트랜잭션에 시간이 들기 때문이다.

그래서 설정을 바꿔가면서 (pytest.ini을 여러개 둬서) pytest를 여러번 돌리는게 더 시간적으로 효율적이다.

 

 

2. conftest.py셋팅

django에서의 셋팅과 다르게 pytest-django에서는 여러개의 디비를 사용하기 위해 별도의 셋팅이 필요하다.

conftest.py는 공통으로 사용되는 Fixture / Plugin / Module을 모아두는 파일로
테스트가 돌아갈 때, 공통적으로 호출되어야 하는 모듈을 정의하는 파일이다.

나의 설정은 다음과 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# -*- coding: utf-8 -*-
import os
 
import dotenv
import pytest
from django.conf import settings
 
dotenv.load_dotenv(os.path.join(os.path.abspath(os.path.dirname(__name__)), '.env'))
 
 
@pytest.fixture(scope='session')
def django_db_setup():
    # settings.py의 설정을 그대로 가져온다.
    settings.DATABASES = {
        'default': {
            'ENGINE''django.db.backends.postgresql',
            'NAME': os.getenv("POSTGRES_DB"),
            'USER': os.getenv("POSTGRES_USER"),
            'PASSWORD': os.getenv("POSTGRES_PASSWORD"),
            'HOST': os.getenv("POSTGRES_HOST")
        },
        'other_db1': {
            'ENGINE''django.db.backends.postgresql',
            'NAME': os.getenv("POSTGRES_other_db1_DB"),            
            'USER': os.getenv("POSTGRES_other_db1_USER"),
            'PASSWORD': os.getenv("POSTGRES_other_db1_PASSWORD"),
            'HOST': os.getenv("POSTGRES_other_db1_HOST")        
       },
        'other_db2': {
            'ENGINE''django.db.backends.postgresql',
            'NAME': os.getenv("POSTGRES_other_db2_DB"),            
            'USER': os.getenv("POSTGRES_other_db2_USER"),
            'PASSWORD': os.getenv("POSTGRES_other_db2_PASSWORD"),
            'HOST': os.getenv("POSTGRES_other_db2_HOST")        
       }
    }
 
 
@pytest.fixture(autouse=True)
def use_dummy_cache_backend(settings):
    settings.CACHES = {
        "default": {
            "BACKEND""django.core.cache.backends.dummy.DummyCache",
        }
    }
 
# 공통으로 사용할 fixture 들 선언
@pytest.fixture
def function_fixture():
    print('Fixture for each test')
    return 1
 
 
@pytest.fixture(scope='module')
def module_fixture():
    print('Fixture for module')
    return 2
 
cs

django_db_setup()의 경우 테스트 데이터베이스를 생성하고설정하는 최상위 함수이다.

setting.py의 데이터베이스 부분을 그대로 가져오면 된다. (왜 다시 설정해야 하는지 의문이다....)

해당 부분을 선언하지 않으면 default로만 접속된다.

 

재밌는것은 문서상에서는 django_db_modify_db_settings()를 먼저 호출한다고 되어 있지만, django_db_modify_db_settings()함수로 선언하면 작동하지 않는다.
https://pytest-django.readthedocs.io/en/latest/database.html

 

 

3. test 코드

테스트코드에서만 별다른거 없이 TestCase.databases = '__all__' 만 선언해 주면 된다.

1
2
class TestCode(TestCase):
    TestCase.databases = '__all__'
cs

 

 

 

끝!

 

 

 

 

번외

1. 여러 문서에서 djang_db를 쓰라고 나와 있지만 작동하지 않았다

@pytest.mark.django_db(databases=['default', 'other_db'])

2. multi_db = True  또한 작동하지 않았다

TransactionTestCase.multi_db = True

 

 

참고 사항

https://github.com/pytest-dev/pytest-django/issues/76

https://github.com/pytest-dev/pytest-django/issues/839

https://americanopeople.tistory.com/311

https://developer.mozilla.org/ko/docs/Learn/Server-side/Django/Testing