본문 바로가기
개발인생/Python

django 데이터베이스 생성 없이 테스트 진행하는 방법

by jeje.91 2023. 3. 13.
반응형

django의 TestCase를 사용해서 DB 테스트를 실행하니 아래와 같은 에러가 발생했다.

 

django.test.testcases.DatabaseOperationForbidden: Database queries to 'other' are not allowed in this test. Add 'other' to services.tests.FirstTest.databases to ensure proper test isolation and silence this failure.

 

TestCase에서 사용할 DB를 databases에 추가해야 한다.

from django.test import TestCase

class FirstTest(TestCase):
    databases = ['default', 'other']
    
    def test_something(self):
        # Your test code here

 

그러고 나면 이제 만나게 되는 문구는 아래와 같다. 

 

Got an error creating the test database: (1007, "Can't create database 'test_other'; database exists")

 

django에서 DB 관련 테스트를 하려면 기본적으로 'test_'라는 prefix가 들어가는 테스트 DB를 생성하게 된다.

이를 생략하고 테스트를 진행하려면 어떻게 해야하는지 정리해보았다.

1. test_runner.py 생성 => 테스트 실행시 database를 설정하지 않고 pass 하도록 한다.

2. settings_test.py 생성 => 앞에 작성한 test_runner.py를 TEST_RUNNER로 설정한다.

3. --settings='config.settings_test' 플래그를 추가해 tests.py 테스트 실행

python manage

 

이와 같이 하면 test DB를 생성하지 않고도 DB 테스트를 진행할 수 있다. 

(관련 코드는 아래에 첨부)


 

# tests.py

from django.db import connections
from django.test import TestCase


# Create your tests here.
class FirstTest(TestCase):
    databases = ['default', 'other']

    def test_raw_query(self):
        # 'other' 데이터베이스에서 raw 쿼리 실행
        with connections['other'].cursor() as cursor:
            cursor.execute('SELECT COUNT(*) FROM users')
            result = cursor.fetchone()

        self.assertEqual(result[0], 2)

 

 

# test_runner.py

from django.test.runner import DiscoverRunner


class TestRunner(DiscoverRunner):

    def setup_databases(self, **kwargs):
        """ Creates the test databases by calling setup_databases(). """
        pass

    def teardown_databases(self, old_config, **kwargs):
        """ Destroys the test databases, restoring pre-test conditions by calling teardown_databases(). """
        pass

 

 

# settings_test.py

from config.settings import *

TEST_RUNNER = 'config.test_runner.TestRunner'

 

 

(추가)

위의 코드를 추가하고 테스트를 진행하면 아래와 같이 경고 문구가 발생할 수 있다.

WARNINGS:
?: (mysql.W002) MySQL Strict Mode is not set for database connection 'other'
        HINT: MySQL's Strict Mode fixes many data integrity problems in MySQL, such as data truncation upon insertion, by escalating warnings into errors. It is strongly recommended you activate it. See: https://docs.djangoproject.com/en/4.1/ref/databases/#mysql-sql-mode

 

테스트하는데 문제는 없지만 필요시 아래와 같이 OPTIONS에 sql_mode를 추가해주면 된다.

 

# settings.py

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR / 'db.sqlite3'
    },
    'other': {
        'ENGINE': os.getenv('DATABASE_OTHER_ENGINE'),
        'NAME': os.getenv('DATABASE_OTHER_NAME'),
        'USER': os.getenv('DATABASE_OTHER_USER'),
        'PASSWORD': os.getenv('DATABASE_OTHER_PASSWORD'),
        'HOST': os.getenv('DATABASE_OTHER_HOST'),
        'PORT': os.getenv('DATABASE_OTHER_PORT'),
        'OPTIONS': {
            'sql_mode': 'STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION',
        },
    },
}
sql_mode 플래그 설명
* STRICT_TRANS_TABLES: 엄격 모드에서 트랜잭션 처리시에만 적용되며, 일반 쿼리에는 적용되지 않습니다. 이 플래그를 설정하면 MySQL이 엄격한 트랜잭션 처리를 수행합니다. 이 플래그를 설정하지 않으면, 일부 데이터베이스 오류가 무시되거나 경고로 처리되어 잘못된 데이터가 삽입될 가능성이 있습니다.
* NO_ZERO_IN_DATE: 날짜 컬럼에 "0000-00-00"과 같은 값을 입력하지 못하도록 제한합니다. 이 플래그를 설정하지 않으면, 이러한 잘못된 날짜 데이터가 삽입될 가능성이 있습니다.
* NO_ZERO_DATE: 날짜 컬럼에 "0000-00-00"과 같은 값이 입력되지 않도록 제한합니다. 이 플래그를 설정하지 않으면, 이러한 잘못된 날짜 데이터가 삽입될 가능성이 있습니다.
* ERROR_FOR_DIVISION_BY_ZERO: 0으로 나누는 경우 오류를 발생시킵니다. 이 플래그를 설정하지 않으면, 나눗셈 결과가 NULL이나 0으로 나올 가능성이 있습니다.
* NO_AUTO_CREATE_USER: 사용자가 존재하지 않는 경우 자동으로 생성하지 않습니다. 이 플래그를 설정하지 않으면, 악성 사용자가 생성되거나 보안 문제가 발생할 가능성이 있습니다.
* NO_ENGINE_SUBSTITUTION: 사용자가 지정한 스토리지 엔진을 사용하지 않으면 오류를 발생시킵니다. 이 플래그를 설정하지 않으면, MySQL이 지정된 스토리지 엔진을 지원하지 않는 경우 다른 엔진을 사용하도록 강제할 가능성이 있습니다.
반응형

댓글