Django - 测试中的代码创建的对象未出现在测试数据库中
别浪费时间看这个问题,下面已经有人回答了。
我的settings.py文件里有:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': 'foo.db',
'TEST_NAME': 'thetest.db'
}
}
在测试代码里有这一行:
allShoes = models.Shoe.objects.filter()
allShoes应该包含一些对象,因为这些数据是由views.py填充的,但在代码里却是空的。我还在测试代码里加了一个set_trace(),这样可以暂停代码执行,然后我用sqlite3程序检查了foo.db,发现里面有对象,而thetest.db里是空的。
我尝试过把我的模型类Shoe从django.test.TestCase和django.test.TransactionTestCase派生出来,但都没有成功。
我使用的是:
>>> django.VERSION
(1, 4, 3, 'final', 0)
还有
(venv)bmac:ol b$ python
Python 2.7.2 (default, Jun 20 2012, 16:23:33)
[GCC 4.2.1 Compatible Apple Clang 4.0 (tags/Apple/clang-418.0.60)] on darwin
你觉得我哪里做错了吗?
补充说明:为了更清楚,foo.db是空的,它是在测试运行之前刚通过syncdb创建的,而thetest.db并不存在。我的测试是一个Selenium测试,它会调用一个视图(正在测试的代码的一部分),然后在页面上点击两次。每次点击都有一个AJAX处理程序,会调用另一个视图;这个视图(更多正在测试的代码)会在数据库里创建一个条目。所以,最后在数据库里应该有两个点击记录,然后测试运行器会销毁这个数据库。
补充说明:我把DATABASES里的TEST_NAME去掉了,以简化问题,虽然我没有看到行为有什么不同。在运行测试时,从我的视图代码里我可以运行:
models.Shoe.objects.using('default').all()
并且能看到对象。然而,从我的测试例程里,执行同样的语句却得到一个空列表。
2 个回答
当Django的测试运行器执行时,它不会去碰生产数据库。在我们的例子中,foo.db
就是你的生产数据库,而Django会确保在你运行单元测试时不会去修改它。相反,它会专门为测试创建一个新的数据库。通常情况下,这个数据库会是一个内存数据库(对于sqlite来说),但是因为你在settings.py
里指定了TEST_NAME
,所以测试数据库会是一个名为thetest.db
的磁盘数据库。
除非你在测试中调用你的视图代码来添加记录,否则thetest.db
里不会有任何内容。
一个测试案例可能看起来像这样。
from django.test import TestCase
class MyTest(TestCase):
def test_something(self):
# Simulate a browser POST which would populate an object in Shoes.
# When the test starts, the db is empty.
response = self.client.post('/shoe/add/', {
# Post data here.
})
self.assertEqual(
1,
models.Shoe.objects.count())
我还没有确认这个解决办法,但我不想让大家浪费时间看这个问题。我觉得问题出在我从测试代码里启动了Django的开发服务器,这样我可以模拟连接不稳定的情况。结果导致使用了生产数据库,这也就解释了为什么测试数据库是空的。真是太糟糕了。