如何让Django测试用例和Selenium服务器使用相同的数据库?

时间:2012-08-20 16:16:22

标签: django selenium integration-testing

我有一个Django(v1.4,使用Postgresql)项目,我已经写了一堆工作单元测试。这些使用FactoryBoy生成大部分数据。

我现在开始使用LiveServerTestCase和Selenium编写一些集成测试。我刚刚意识到我的测试和实时测试服务器使用不同的数据库。这意味着我的测试中工厂创建的数据对Selenium不可用。

我不确定最好的进步方式。我认为我可以使用灯具来提供可行的数据,尽管使用工厂这一点很痛苦。

有没有办法可以继续使用工厂生成适合我的Selenium测试的数据?我真的喜欢我的测试和LiveServerTestCase使用相同的数据库。

2 个答案:

答案 0 :(得分:12)

我发现为什么会发生这种情况,以及一些可能的解决方法,包括Ilya Baryshev的回答。

如果你的测试来自Django的TestCase,并且你的数据库支持事务,那么每个测试都在自己的事务中运行,并且没有人在外面(没有其他线程,外部进程或其他测试)可以看到对象通过测试在数据库中创建。

LiveServerTestCase使用线程,因此会遇到此问题。因此,设计人员使其继承自TransactionTestCase而不是TestCase,这会禁用这些交易,以便更改全局可见。

我发生的事情是我在测试课程中添加了一些mixins,其中一个是TestCase。这不会导致错误,但它会以LiveServerTestCase静默替换TestCase的基类,这会再次启用事务,从而导致您描述的问题。

Ilya的SQLite内存数据库解决方法可行,因为Django包含检测何时使用实际在线程之间共享相同连接的SQLite :memory:数据库的代码,因此您可以在LiveServerThread中看到测试对象,因为它们是在相同的交易中。然而,这有一些警告:

  

防止两个线程通过此共享连接同时进行数据库查询非常重要,因为这有时会导致测试失败。因此,您需要确保两个线程无法访问数据库同时。特别是,这意味着在某些情况下(例如,在单击链接或提交表单之后),您可能需要检查Selenium是否收到响应并且在继续执行进一步测试之前已加载下一页。例如,通过让Selenium等到响应中找到HTML标记(需要Selenium> 2.13)来执行此操作...

https://docs.djangoproject.com/en/1.4/topics/testing/#live-test-server

就我而言,一旦我们在测试开始时标识autocommit被关闭,并追踪原因(因为我们输入了TestCase代码,我们不应该这样做),我们能够修复继承层次结构以避免引入TestCase,然后从实时服务器线程和测试中可以看到相同的数据库。

这也适用于Postgres数据库,因此它将为velotron提供解决方案。

答案 1 :(得分:5)

您是否尝试过使用sqlite作为测试的数据库后端?

  

使用内存中的SQLite数据库运行测试时,同样如此   数据库连接将由两个并行的线程共享:   运行实时服务器的线程和其中的线程   测试用例运行。

来自Django docs

如果你没有使用常规ORM以外的任何东西,你也可以从测试加速中受益。