如何在Django测试中使用managed = False创建表格
我有一个托管= False的模型。如何在Django测试中使用managed = False创建表格
class SampleModel(models.Model):
apple = models.CharField(max_length=30)
orange = models.CharField(max_length=30)
class Meta:
managed = False
我有创造的SampleModel单元测试,但是当我运行测试,我得到:
DatabaseError: no such table: SAMPLE_SAMPLE_MODEL
Django文档 - https://docs.djangoproject.com/en/dev/ref/models/options/#managed介绍以下:
对于测试涉及托管= False的模型,则由您决定 确保将正确的表创建为测试设置的一部分。
如何在测试设置过程中真正“创建”表格?或者,我该如何做到这一点,以便在运行测试时,该模型在测试期间的“managed = True”?
在实际应用中,该模型实际上由数据库中的视图支持。然而,在测试过程中,我想把它作为一个表格,并且能够在其中插入测试数据。
看看这个博客文章:http://www.caktusgroup.com/blog/2010/09/24/simplifying-the-testing-of-unmanaged-database-models-in-django/它详细描述了非托管模型的测试运行器的创建。
执行原始的SQL语句来创建测试设置表:
from django.db import connection
class MyTest(unittest.TestCase):
def setUp(self):
connection.cursor().execute("CREATE TABLE ...")
def tearDown(self):
connection.cursor().execute("DROP TABLE ...")
可以使用dump命令只包括表定义,并在此答案的'setUp()'方法中使用它。例如,在MySQL情况下,该命令可能类似于'mysqldump --no-data databasename'。 –
每个单独测试的'CREATE'和'DROP'表都很慢。模式在测试之间永远不会改变。 –
使用此创建自己的测试运行:
from django.test.simple import DjangoTestSuiteRunner
class NoDbTestRunner(DjangoTestSuiteRunner):
""" A test runner to test without database creation """
def setup_databases(self, **kwargs):
""" Override the database creation defined in parent class """
#set manage=True for that specific database on here
然后在设置这个类添加到TEST_RUNNER。
速战速决,如果你没有太多的非托管表:
首先添加一个新的变量来设置。
# settings.py
import sys
UNDER_TEST = (len(sys.argv) > 1 and sys.argv[1] == 'test')
然后在模型
# models.py
from django.conf import settings
class SampleModel(models.Model):
apple = models.CharField(max_length=30)
orange = models.CharField(max_length=30)
class Meta:
managed = getattr(settings, 'UNDER_TEST', False)
尼斯即插即用解决方案。只需在测试类定义之前粘贴它即可。 (注:使用的Django 1.8)
from django.db.models.loading import get_models
def change_managed_settings_just_for_tests():
"""django model managed bit needs to be switched for tests."""
unmanaged_models = [m for m in get_models() if not m._meta.managed]
for m in unmanaged_models:
m._meta.managed = True
change_managed_settings_just_for_tests()
我想补充:django.db.models.loading.get_models将在Django 1.9(见https://github.com/BertrandBordage/django-cachalot/issues/33)被移除。
下面是一个更新的一个Django的1.10:
class UnManagedModelTestRunner(DiscoverRunner):
'''
Test runner that automatically makes all unmanaged models in your Django
project managed for the duration of the test run.
Many thanks to the Caktus Group
'''
def setup_test_environment(self, *args, **kwargs):
from django.apps import apps
self.unmanaged_models = [m for m in apps.get_models() if not m._meta.managed]
for m in self.unmanaged_models:
m._meta.managed = True
super(UnManagedModelTestRunner, self).setup_test_environment(*args, **kwargs)
def teardown_test_environment(self, *args, **kwargs):
super(UnManagedModelTestRunner, self).teardown_test_environment(*args, **kwargs)
# reset unmanaged models
for m in self.unmanaged_models:
m._meta.managed = False
注意你也需要照顾迁移(见Testing django application with several legacy databases)
MIGRATION_MODULES = {
'news': 'news.test_migrations',
'economist': 'economist.test_migrations'
}
它不适用于Django 1.11(因为它将使用迁移来创建测试数据库,并且在您的模型定义将设置'managed = False')。在https://*.com/a/37060122/462655中提出的解决方案适用于Django 1.11 – msonsona
FWIW这也不适用于Django 1.10.7(也可能是整个1.10.x系列,但我不确定) 。 –
可以在https://dev.to/patrnk/testing-against-unmanaged-models-in-django上获得原始测试跑步者创意的更新 – shadi