使用Sqlite3运行Django Unittest时缺少表 [英] Missing Table When Running Django Unittest with Sqlite3
问题描述
我想使用Django 1.3运行单元测试。通常情况下,我使用MySQL作为数据库后端,但由于这是一个单一的单位测试spinup慢慢,我使用Sqlite3。
I'm trying to run a unittest with Django 1.3. Normally, I use MySQL as my database backend, but since this is painfully slow to spinup for a single unittest, I'm using Sqlite3.
所以切换到Sqlite3只是对我的单元测试,在我的settings.py我有:
So to switch to Sqlite3 just for my unittests, in my settings.py I have:
import sys
if 'test' in sys.argv:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME':'/tmp/database.db',
'USER' : '',
'PASSWORD' : '',
'HOST' : '',
}
}
当我使用 python manage.py test myapp.Test.test_myfunc
,我得到错误:
When I run my unittest with python manage.py test myapp.Test.test_myfunc
, I get the error:
DatabaseError: no such table: django_content_type
Googling显示有少数 可能 原因此错误,这些都不适用于我。我不是运行Apache,所以我不知道如何权限将是一个问题。正在创建文件/tmp/database.db,因此/ tmp是可写的。应用程式django.contrib.contenttypes包含在我的INSTALLED_APPS中。
Googling shows there are a few of possible reasons for this error, none of which seem applicable to me. I'm not running Apache, so I don't see how permissions would be an issue. The file /tmp/database.db is being created, so /tmp is writable. The app django.contrib.contenttypes is included in my INSTALLED_APPS.
我缺少什么?
我在Django 1.5中遇到了这个问题,但是没有一个解决方案可以工作。
I ran into this problem again in Django 1.5, but none of the proposed solutions work.
推荐答案
在Django 1.4,1.5,1.6 ,1.7或1.8,它应该足以使用:
In Django 1.4, 1.5, 1.6, 1.7, or 1.8 it should be sufficient to use:
if 'test' in sys.argv:
DATABASES['default']['ENGINE'] = 'django.db.backends.sqlite3'
不必重写 TEST_NAME
1 ,也不必调用 syncdb
为了运行测试。正如@osa指出的,SQLite引擎的默认是在内存中创建测试数据库( TEST_NAME =':memory:'
)。调用 syncdb
不应该是必要的,因为Django的测试框架将通过调用 syncdb
或<$ c $ <>您可以用 manage.py test -v [2 | 3] $ c>来观察这个问题$ c>。
It should not be necessary to override TEST_NAME
1, nor to call syncdb
in order to run tests. As @osa points out, the default with the SQLite engine is to create the test database in memory (TEST_NAME=':memory:'
). Calling syncdb
should not be necessary because Django's test framework will do this automatically via a call to syncdb
or migrate
depending on the Django version.2 You can observe this with manage.py test -v [2|3]
.
很轻松地说Django设置测试环境:
Very loosely speaking Django sets up the test environment by:
- 从您的
settings.py
- 设置数据库
NAME
为值TEST_NAME
- 对数据库运行测试
NAME
加载常规数据库
NAME
和构造测试类( __ init __()
) - Loading the regular database
NAME
from yoursettings.py
- Discovering and constructing your test classes (
__init__()
is called) - Setting the database
NAME
to the value ofTEST_NAME
- Running the tests against the database
NAME
这里是搓揉:在第2步, NAME
仍指向您的常规(非测试)数据库。如果你的测试包含在 __ init __()
中的类级别的查询或查询,它们将会对常规数据库运行,这可能不是你期望的。这在错误#21143 中标识。
Here's the rub: At step 2, NAME
is still pointing at your regular (non-test) database. If your tests contain class-level queries or queries in __init__()
, they will be run against the regular database which is likely not what you are expecting. This is identified in bug #21143.
不要do:
class BadFooTests(TestCase):
Foo.objects.all().delete() # <-- class level queries, and
def __init__(self):
f = Foo.objects.create() # <-- queries in constructor
f.save() # will run against the production DB
def test_foo(self):
# assert stuff
,因为它们将针对 NAME
中指定的数据库运行。如果在此阶段 NAME
指向有效的数据库(例如您的生产数据库),查询将运行,但可能有意想不到的后果。如果您已重写 ENGINE
和/或 NAME
,使其不指向预先存在的数据库,将被抛出,因为测试数据库尚未创建:
since these will be run against the database specified in NAME
. If NAME
at this stage points to a valid database (e.g. your production database), the query will run, but may have unintended consequences. If you have overridden ENGINE
and/or NAME
such that it does not point to a pre-existing database, an exception will be thrown because the test database has yet to be created:
django.db.utils.DatabaseError: no such table: yourapp_foo # Django 1.4
DatabaseError: no such table: yourapp_foo # Django 1.5
OperationalError: no such table: yourapp_foo # Django 1.6+
而不是:
class GoodFooTests(TestCase):
def setUp(self):
f = Foo.objects.create() # <-- will run against the test DB
f.save() #
def test_foo(self):
# assert stuff
因此,如果您看到错误,以查看您的测试不包括任何可能在测试类方法定义之外访问数据库的查询。
So, if you are seeing errors, check to see that your tests do not include any queries that might hit the database outside of your test class method definitions.
1]在Django> = 1.7, DATABASES [别名] ['TEST_NAME']
是已弃用,赞成 DATABASES [别名] ['TEST'] ['NAME']
[2]查看<$ c $在 db / backends / creation.py
[1] In Django >= 1.7, DATABASES[alias]['TEST_NAME']
is deprecated in favour of DATABASES[alias]['TEST']['NAME']
[2] See the create_test_db()
method in db/backends/creation.py
这篇关于使用Sqlite3运行Django Unittest时缺少表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!