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


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

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

我不确定最好的进步方式。一世 认为 我可以使用灯具来提供可行的数据,尽管这是一个很难用到工厂而已。

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


9608
2017-08-20 16:16


起源



答案:


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

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

Django文档

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


5
2017-11-10 14:38



哦,好主意 - 下次我看这些测试时会试一试,然后报告回来! - Phil Gyford
这个答案对我有用。谢谢! - Rachel
我的应用程序需要Postgres,我希望我可以使用SQLite解决方案。 - velotron


答案:


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

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

Django文档

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


5
2017-11-10 14:38



哦,好主意 - 下次我看这些测试时会试一试,然后报告回来! - Phil Gyford
这个答案对我有用。谢谢! - Rachel
我的应用程序需要Postgres,我希望我可以使用SQLite解决方案。 - velotron


我发现了为什么会发生这种情况,以及一些可能的解决方法,包括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提供解决方案。


9
2017-08-01 13:49



多么痛苦。烦人的问题(TestCase的使用)发生得如此无形。谢谢你回来。 - Phil Gyford
很抱歉恢复这个,但我正确地读了这个 TransactionTestCase 是基类 禁用 交易?好像它会反过来? - Korijn
就是这样。 TransactionTestCase 用于测试 使用 交易,因此无法运行 内 一个事务,因为您无法在SQL中嵌套事务,因此它会禁用自己的事务。 - qris