从 1.8 升级到 2.2.4 后,Django 无法为单元测试创建表
Django unable to create tables for unit testing after upgrade from 1.8 to 2.2.4
从 Django 1.8 成功升级到 Django 2.2.4 后,当
我 运行 测试失败了,因为 Django 没有创建数据库表。
我的 test_settings.py 文件在升级前工作正常。
调试 Django db/backends 后,连接似乎已创建,但表并未创建。
我怀疑 test_setting.py 没有配置好,尽管我从 setting.py 文件复制了除了数据库配置(仍然是 SQLite)之外的所有内容。
数据库配置:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': 'test_database'
}
}
INSTALLED_APPS = [
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'rest_framework.authtoken',
'my_app',
'mptt',
'corsheaders',
# audit app
'easyaudit',
'kronos',
'django.contrib.admin',
]
我得到的回溯(例如,这里是 auth_user,但它以相同的方式为所有表重现):
Traceback (most recent call last):
File "C:\Users\owner\Desktop\workspace\my_project\MyProject\services\tests\test_logging.py", line 33, in setUpClass
cls.user = User.objects.get_or_create(username='logging_test_user', password='test_password')
File "C:\Users\owner\Desktop\workspace\my_project\venv36\lib\site-packages\django\db\models\manager.py", line 82, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "C:\Users\owner\Desktop\workspace\my_project\venv36\lib\site-packages\django\db\models\query.py", line 538, in get_or_create
return self.get(**kwargs), False
File "C:\Users\owner\Desktop\workspace\my_project\venv36\lib\site-packages\django\db\models\query.py", line 402, in get
num = len(clone)
File "C:\Users\owner\Desktop\workspace\my_project\venv36\lib\site-packages\django\db\models\query.py", line 256, in __len__
self._fetch_all()
File "C:\Users\owner\Desktop\workspace\my_project\venv36\lib\site-packages\django\db\models\query.py", line 1242, in _fetch_all
self._result_cache = list(self._iterable_class(self))
File "C:\Users\owner\Desktop\workspace\my_project\venv36\lib\site-packages\django\db\models\query.py", line 55, in __iter__
results = compiler.execute_sql(chunked_fetch=self.chunked_fetch, chunk_size=self.chunk_size)
File "C:\Users\owner\Desktop\workspace\my_project\venv36\lib\site-packages\django\db\models\sql\compiler.py", line 1100, in execute_sql
cursor.execute(sql, params)
File "C:\Users\owner\Desktop\workspace\my_project\venv36\lib\site-packages\django\db\backends\utils.py", line 67, in execute
return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
File "C:\Users\owner\Desktop\workspace\my_project\venv36\lib\site-packages\django\db\backends\utils.py", line 76, in _execute_with_wrappers
return executor(sql, params, many, context)
File "C:\Users\owner\Desktop\workspace\my_project\venv36\lib\site-packages\django\db\backends\utils.py", line 84, in _execute
return self.cursor.execute(sql, params)
File "C:\Users\owner\Desktop\workspace\my_project\venv36\lib\site-packages\django\db\utils.py", line 89, in __exit__
raise dj_exc_value.with_traceback(traceback) from exc_value
File "C:\Users\owner\Desktop\workspace\my_project\venv36\lib\site-packages\django\db\backends\utils.py", line 84, in _execute
return self.cursor.execute(sql, params)
File "C:\Users\owner\Desktop\workspace\my_project\venv36\lib\site-packages\django\db\backends\sqlite3\base.py", line 383, in execute
return Database.Cursor.execute(self, query, params)
django.db.utils.OperationalError: no such table: auth_user
使用
的环境变量执行的测试
DJANGO_SETTINGS_MODULE=MyProject.test_settings
沿线的某个地方,测试用例使用的数据库需要附加到它们。在实例化测试数据库之前,Django 会根据对象列出所有需要的数据库。在此之后,它会为它们制作模式。
如果您添加到基础 class 中,您将继承所有测试,或者添加到每个 class 您从 Django class 继承的 classes a像这样的行:
databases = settings.DATABASES
您会发现您的数据库应该实例化。
这个版本的django好像有bug(可能也是2.2以前的,没查过)。
databases = self.get_databases(suite)
old_config = self.setup_databases(aliases=databases)
这里的 databases 变量在任何情况下都不会是 None 因为在 get_databases 函数中它调用 _get_databases() 并且它不会找到任何数据库像上面提到的那样配置,数据库将设置为 set(),并且在 setup_databases 函数中有一个名为
的函数
get_unique_databases_and_mirrors
检查测试中是否没有配置数据库,如果没有,它将使用设置文件中配置的数据库,但因为它设置为空集 (set()) 而不会进入这种情况,因此不会创建数据库。
要消除该错误,您可以创建一个将继承 unittests.Testcase 的 class,并像这样配置数据库:
import django
import unittest
from django.conf import settings
class MyTestCase(unittest.TestCase):
databases = settings.DATABASES
@classmethod
def setUpClass(cls) -> None:
super(MyTestCase, cls).setUpClass()
django.setup()
从 Django 1.8 成功升级到 Django 2.2.4 后,当 我 运行 测试失败了,因为 Django 没有创建数据库表。
我的 test_settings.py 文件在升级前工作正常。
调试 Django db/backends 后,连接似乎已创建,但表并未创建。 我怀疑 test_setting.py 没有配置好,尽管我从 setting.py 文件复制了除了数据库配置(仍然是 SQLite)之外的所有内容。
数据库配置:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': 'test_database'
}
}
INSTALLED_APPS = [
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'rest_framework.authtoken',
'my_app',
'mptt',
'corsheaders',
# audit app
'easyaudit',
'kronos',
'django.contrib.admin',
]
我得到的回溯(例如,这里是 auth_user,但它以相同的方式为所有表重现):
Traceback (most recent call last):
File "C:\Users\owner\Desktop\workspace\my_project\MyProject\services\tests\test_logging.py", line 33, in setUpClass
cls.user = User.objects.get_or_create(username='logging_test_user', password='test_password')
File "C:\Users\owner\Desktop\workspace\my_project\venv36\lib\site-packages\django\db\models\manager.py", line 82, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "C:\Users\owner\Desktop\workspace\my_project\venv36\lib\site-packages\django\db\models\query.py", line 538, in get_or_create
return self.get(**kwargs), False
File "C:\Users\owner\Desktop\workspace\my_project\venv36\lib\site-packages\django\db\models\query.py", line 402, in get
num = len(clone)
File "C:\Users\owner\Desktop\workspace\my_project\venv36\lib\site-packages\django\db\models\query.py", line 256, in __len__
self._fetch_all()
File "C:\Users\owner\Desktop\workspace\my_project\venv36\lib\site-packages\django\db\models\query.py", line 1242, in _fetch_all
self._result_cache = list(self._iterable_class(self))
File "C:\Users\owner\Desktop\workspace\my_project\venv36\lib\site-packages\django\db\models\query.py", line 55, in __iter__
results = compiler.execute_sql(chunked_fetch=self.chunked_fetch, chunk_size=self.chunk_size)
File "C:\Users\owner\Desktop\workspace\my_project\venv36\lib\site-packages\django\db\models\sql\compiler.py", line 1100, in execute_sql
cursor.execute(sql, params)
File "C:\Users\owner\Desktop\workspace\my_project\venv36\lib\site-packages\django\db\backends\utils.py", line 67, in execute
return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
File "C:\Users\owner\Desktop\workspace\my_project\venv36\lib\site-packages\django\db\backends\utils.py", line 76, in _execute_with_wrappers
return executor(sql, params, many, context)
File "C:\Users\owner\Desktop\workspace\my_project\venv36\lib\site-packages\django\db\backends\utils.py", line 84, in _execute
return self.cursor.execute(sql, params)
File "C:\Users\owner\Desktop\workspace\my_project\venv36\lib\site-packages\django\db\utils.py", line 89, in __exit__
raise dj_exc_value.with_traceback(traceback) from exc_value
File "C:\Users\owner\Desktop\workspace\my_project\venv36\lib\site-packages\django\db\backends\utils.py", line 84, in _execute
return self.cursor.execute(sql, params)
File "C:\Users\owner\Desktop\workspace\my_project\venv36\lib\site-packages\django\db\backends\sqlite3\base.py", line 383, in execute
return Database.Cursor.execute(self, query, params)
django.db.utils.OperationalError: no such table: auth_user
使用
的环境变量执行的测试DJANGO_SETTINGS_MODULE=MyProject.test_settings
沿线的某个地方,测试用例使用的数据库需要附加到它们。在实例化测试数据库之前,Django 会根据对象列出所有需要的数据库。在此之后,它会为它们制作模式。
如果您添加到基础 class 中,您将继承所有测试,或者添加到每个 class 您从 Django class 继承的 classes a像这样的行:
databases = settings.DATABASES
您会发现您的数据库应该实例化。
这个版本的django好像有bug(可能也是2.2以前的,没查过)。
databases = self.get_databases(suite)
old_config = self.setup_databases(aliases=databases)
这里的 databases 变量在任何情况下都不会是 None 因为在 get_databases 函数中它调用 _get_databases() 并且它不会找到任何数据库像上面提到的那样配置,数据库将设置为 set(),并且在 setup_databases 函数中有一个名为
的函数get_unique_databases_and_mirrors
检查测试中是否没有配置数据库,如果没有,它将使用设置文件中配置的数据库,但因为它设置为空集 (set()) 而不会进入这种情况,因此不会创建数据库。
要消除该错误,您可以创建一个将继承 unittests.Testcase 的 class,并像这样配置数据库:
import django
import unittest
from django.conf import settings
class MyTestCase(unittest.TestCase):
databases = settings.DATABASES
@classmethod
def setUpClass(cls) -> None:
super(MyTestCase, cls).setUpClass()
django.setup()