11

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

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

我不确定进步的最佳方式。我我可以使用固定装置来提供可以工作的数据,尽管使用工厂来代替这很痛苦。

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

4

2 回答 2

12

我发现了为什么这会发生在我身上,以及一些可能的解决方法,包括上面 Ilya Baryshev 的回答。

如果您的测试源自 Django TestCase,并且您的数据库支持事务,那么每个测试都在其自己的事务中运行,并且外部的任何人(没有其他线程、外部进程或其他测试)都无法看到您的测试在数据库中创建的对象。

LiveServerTestCase使用线程,所以它会遇到这个问题。所以设计者让它继承自TransactionTestCase而不是TestCase,这会禁用这些事务,因此更改是全局可见的。

发生在我身上的是,我在我的测试类中添加了一些 mixin,其中一个加入了TestCase. 这不会导致错误,但它会默默地替换LiveServerTestCasewith的基类TestCase,这会再次启用事务,从而导致您描述的问题。

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

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

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

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

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

于 2014-08-01T13:49:58.290 回答
6

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

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

来自Django 文档

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

于 2012-11-10T14:38:28.610 回答