如何让Django测试框架读取实时数据库?
我知道这里有个类似的问题,但这个问题的处理方式不太一样:我有一个使用 djapian 索引数据的 Django 应用;我想为这个应用的搜索功能写单元测试,显然,我需要 Django 的设置模块和所有与数据库的连接都处于活动状态,所以 Django 提供的测试运行器看起来很合适。但是,Django 的测试框架会创建一个 虚拟 数据库,我可不想把所有数据导出到一个文件里再重新索引(那样测试会花费 很长时间!);
我的数据是安全的,因为测试只会 读取 数据库,那么,我该如何实现呢?-我对单元测试还很陌生,所以在那个类似问题中提到的编写新的 测试运行器 的解决方案对我来说一点都不清楚,至少没有一些具体的细节。
1 个回答
在阅读djapian的测试案例时,我发现了一些很有意思的东西:他们使用了TestCase类中的setUp方法。他们创建了一个对象,然后用更新方法来更新索引,这样他们就有了一个可以搜索的文档,同时也能进行有控制的查询测试!
对于好奇的人来说,这个方法大概是这样的:
def setUp(self):
p = Person.objects.create(name="Alex")
for i in range(self.num_entries):
Entry.objects.create(author=p, title="Entry with number %s" % i, text="foobar " * i)
Entry.indexer.update()
我觉得这样做可以,但我们要记住,我是在测试一个小搜索引擎,所以这个解决方案可能是个简单的办法;不过我想不出有什么反对意见,所以如果你们有更好的答案,能帮助我为这种类型的Python网络应用定义一个测试策略,那就太好了!
-我想我暂时就先这样做(我还想测试一下在一个完全填充的数据库中查询的延迟,但我觉得可以稍后用Funkload的基准测试来实现)。
编辑:好的,为了对任何感兴趣的人保持忠实,我遇到了另一个问题:xapian索引(如评论中所述)。为了解决这个问题,我创建了一个默认的测试运行器,它将生产环境的xapian索引替换为一个测试索引(一个较小的索引,通过管理脚本创建)。这个运行器相对简单:
def custom_run_tests(test_labels, verbosity=1, interactive=True, extra_tests=[]):
"""Set the test indices"""
settings.CATEGORY_CLASSIFIER_DATA = settings.TEST_CLASSIFIER_DATA
return run_tests(test_labels, verbosity, interactive, extra_tests)
而且,要使用它,我只需添加一个设置:
TEST_RUNNER = 'search.tests.custom_run_tests'
我放弃了之前提到的方法(在setUp中创建文档),是出于性能和可读性的考虑:为了测试数据库,我需要一些带有文本(一个或两个段落)的文档,所以我最终创建了一个固定数据(fixture)来解决这个问题(我使用了一个管理命令,在真实数据库中创建文档,将它们序列化-写入文件-然后删除它们)。所以,最后我根本没有从实时数据库读取数据,而是使用了一个有点黑科技的脚本和一个自定义的运行器创建的测试固定数据,这并不难 :)