Django 测试:临时数据库文件中没有数据
我在 settings.py
中设置了一个 sqlite3 数据库,具体如下:
DATABASES = {
'default': {
'ENGINE': 'django.contrib.gis.db.backends.spatialite',
'NAME': 'path/to/config.sqlite',
'TEST_NAME': 'path/to/test-config.sqlite',
# ... USER, PASSWORD and PORT left out for brevity
}
}
在一次测试运行中,我是这样开始的:
python manage.py test myapp.mytest
这会临时创建一个数据库文件 path/to/test-config.sqlite
,我需要在另一个应用程序中使用这个文件,并且加载所需的数据。
不过,这个数据库文件是空的,我在一次测试暂停时确认了这一点:
sqlite> select * from someapp_somemodel;
... no results here :(
其他不需要 sqlite 文件的测试用例,使用内存数据库就足够了,没有出现错误。
我有几个问题:
- 为什么 Django 如果已经创建了数据库文件,却不把数据写入其中?
- 我该如何让 Django 把数据写入这个临时数据库文件,因为我需要这些数据在临时数据库中?
编辑
我使用的是 Django 1.3.1,如果这有帮助的话。
编辑2
我对数据填充(fixtures)很熟悉,并且用它们来填充数据库,但我的问题是,在测试过程中,数据并没有写入数据库文件。抱歉之前没有说清楚这一点。
编辑3
为了更清楚地说明我的问题,请看以下测试设置(这和我实际做的很接近):
class SomeTestCase(django.test.TestCase):
fixtures = ["some_fixture.json", "some_other_fixture.json"]
def testSomething(self):
import pdb; pdb.set_trace()
当 testSomething
方法运行到断点时,我启动 sqlite3
程序,并连接到 Django 创建的临时数据库文件。数据填充被加载(我知道,因为其他测试也能正常工作),但数据并没有写入临时数据库文件。
5 个回答
来自Django文档的内容:
...当使用SQLite数据库时,测试默认会使用一个在内存中的数据库(也就是说,数据库会在内存中创建,完全不使用文件系统!)。如果你想使用不同的数据库名称,可以在
DATABASES
中的字典里指定TEST_NAME
。
此外,如果你了解一下数据加载:
...在每个测试用例开始时,在运行
setUp()
之前,Django会清空数据库,把数据库恢复到调用syncdb后刚开始的状态...
如果你需要一个全新的数据库并加载一些数据,你当然可以通过运行syncdb
来创建一个空数据库,然后使用django-admin.py loaddata
来加载一些数据!
我找到了一种方法,但因为我也玩过hdparm(用过-F或-W 0/1),所以不确定这对你是否有效。我确实重启过并重新尝试过,以确保结果可靠。另外,这个测试没有使用SpatiaLite,不过正如你所说,这可能没什么关系。
总之,我们需要两个屏幕来复现这个问题,screen0用来运行测试,而screen1是一个sh命令行,可以在screen0的进程暂停时使用。
开始测试(screen0):
>>> ./manage.py test testapp
Creating test database for alias 'default'...
Destroying old test database 'default'...
Type 'yes' if you would like to try deleting the test database 'db_test.sqlite', or 'no' to cancel: yes
--Return--
None
> /home/jpic/testproject/testapp/tests.py(16)testSomething()
14
15 def testSomething(self):
---> 16 import ipdb; ipdb.set_trace()
检查创建的测试数据库文件的大小(screen1):
<<< 18:00.39 Mon Feb 20 2012!~/testproject
<<< jpic@germaine!10004 env
>>> ls -l db_test.sqlite
-rw-r--r-- 1 jpic jpic 49152 2012-02-20 18:00 db_test.sqlite
从python中运行PRAGMA SYNCHRONOUS的sql命令(screen0):
ipdb> from django.db import connection; cursor = connection.cursor()
ipdb> cursor.execute("PRAGMA SYNCHRONOUS")
<django.db.backends.sqlite3.base.SQLiteCursorWrapper object at 0x294f348>
ipdb>
检查数据库文件的大小是否增加(screen1):
<<< 18:00.42 Mon Feb 20 2012!~/testproject
<<< jpic@germaine!10005 env
>>> ls -l db_test.sqlite
-rw-r--r-- 1 jpic jpic 272384 2012-02-20 18:00 db_test.sqlite
数据已经写入文件。
这对我来说有点不太合理,因为显然单独使用PRAGMA SYNCHRONOUS
应该只是查询这个值(在我的情况下是:2/FULL)。但实际上,它却写入了磁盘。请注意,如果你没有2(FULL),那么你应该设置为2:PRAGMA SYNCHRONOUS 2
。
现在,我不能确定写了什么(是否完全写入了?),因为我无法访问测试数据库:如果我在screen1中运行sqlite db_test.sqlite
来连接测试数据库,我无法运行任何命令(既不能选择,也不能.dump),因为出现了“SQL错误:数据库被锁定”。不过,我想这现在是你的问题了B)