Тест Django в некоторых случаях использует неправильную базу данных
Я пытаюсь настроить свои тесты Django, и я заметил, что когда я запускаю все тесты, TestRunner использует корректную тестовую базу данных (для всех псевдонимов):
docker-compose exec my_project python manage.py test --keepdb
from django import db
from django.test.runner import DiscoverRunner
from apps.settings.models import Settings
class KeepDBTestRunner(DiscoverRunner):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.verbosity = 2
self.keepdb = True
self.db_base_name = 'test_postgresdevuser'
def run_checks(self):
super().run_checks()
print(db.connections.databases)
----------------------------------------------
result
----------------------------------------------
{'default': {'NAME': 'test_postgresdevuser', 'USER': 'user', 'PASSWORD': '*******', 'HOST': 'postgres', 'PORT': 5432, 'ENGINE': 'apps.core.db_backends.open', 'TEST': {'SERIALIZE': False, 'DEPENDENCIES': [], 'CHARSET': None, 'COLLATION': None, 'NAME': None, 'MIRROR': None}, 'ATOMIC_REQUESTS': False, 'AUTOCOMMIT': True, 'CONN_MAX_AGE': 0, 'OPTIONS': {}, 'TIME_ZONE': None},
'vk_master': {'NAME': 'test_postgresdevuser', 'USER': 'user', 'PASSWORD': '*******', 'HOST': 'postgres', 'PORT': 5432, 'ENGINE': 'apps.core.db_backends.open', 'TEST': {'SERIALIZE': False, 'DEPENDENCIES': [], 'CHARSET': None, 'COLLATION': None, 'NAME': None, 'MIRROR': None}, 'ATOMIC_REQUESTS': False, 'AUTOCOMMIT': True, 'CONN_MAX_AGE': 0, 'OPTIONS': {}, 'TIME_ZONE': None},
Но когда я запускаю тесты для конкретного модуля, он использует исходную базу данных:
docker-compose exec my_project python manage.py test --keepdb apps.my_module
...
print(db.connections.databases)
----------------------------------------------
result
----------------------------------------------
{'default': {'NAME': 'postgresdevuser', 'USER': 'user', 'PASSWORD': '*******', 'HOST': 'postgres', 'PORT': 5432, 'ENGINE': 'apps.core.db_backends.open', 'TEST': {'SERIALIZE': False, 'DEPENDENCIES': [], 'CHARSET': None, 'COLLATION': None, 'NAME': None, 'MIRROR': None}, 'ATOMIC_REQUESTS': False, 'AUTOCOMMIT': True, 'CONN_MAX_AGE': 0, 'OPTIONS': {}, 'TIME_ZONE': None},
'vk_master': {'NAME': 'postgresdevuser', 'USER': 'user', 'PASSWORD': '********', 'HOST': 'postgres', 'PORT': 5432, 'ENGINE': 'apps.core.db_backends.open', 'TEST': {'SERIALIZE': False, 'DEPENDENCIES': [], 'CHARSET': None, 'COLLATION': None, 'NAME': None, 'MIRROR': None}, 'ATOMIC_REQUESTS': False, 'AUTOCOMMIT': True, 'CONN_MAX_AGE': 0, 'OPTIONS': {}, 'TIME_ZONE': None},
В чем причина такого поведения? Использование оригинальной базы данных не допускается, когда я запускаю тесты на предпроизводственной стадии!
Конфигурация проекта:
Django=3.0.7
*.env* file:
DATABASE_URL=postgres://user:********@postgres:5432/postgresdevuser
...
*settings.py* file:
DATABASES = {
'default': env.db('DATABASE_URL', default=''),
'vk_master': env.db('DATABASE_URL', default=''),
...
}
DATABASES['vk_master']['ENGINE'] = 'apps.core.db_backends.open'
DATABASES['default']['ENGINE'] = 'apps.core.db_backends.open'
for db_name in DATABASES:
DATABASES[db_name]['TEST'] = {
'SERIALIZE': False,
'DEPENDENCIES': [],
}
...
Буду благодарен за любой совет!
Я думаю, что это своего рода ошибка в тесте Django. Когда в каком-либо TestCase нет параметра 'databases', он не использует тестовую базу данных, а использует исходную. Чтобы обойти это, я переопределил метод setup_databases в TestRunner следующим образом:
class KeepDBTestRunner(DiscoverRunner):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.keepdb = True
def setup_databases(self, **kwargs):
# define aliases here. In original class aliases will be 'None' (from calling
# self.get_databases(suite)) and it causes a problem.
aliases = {'default', 'replica'}
return super().setup_databases(aliases=aliases)