为什么我的django测试套件在测试期间改变我的表时无法在测试之间刷新数据库?

时间:2014-10-15 14:46:58

标签: mysql django unit-testing

我已将auth.user模型替换为自定义用户模型,其用户名与公司的用户名是唯一的。为了使这项工作,我手动从用户表中删除唯一约束(通过迁移)。我想编写一个测试来验证它是否按预期工作(在适当时返回错误消息等),但我无法理解为什么测试框架的行为不像我期望的那样。这是我在测试中所做的事情:

class UserTests(TestCase):
    def setUp(self):
        self.client = Client()
        # Setup: Create users, companies, etc. to use in the test

    def test_create_dup_staffuser(self):
        cursor = connection.cursor()
        try:
            cursor.execute("alter table config_user drop index `username`;")
        finally:
            cursor.close()

        # Test code: Create some data, pass it to my 'create user' view,
        # verify the results

    def test_user_something_else(self):
        # Test other things        

测试本身有效。约束被按预期删除,我的测试通过,允许我在公司内创建具有重复用户名的用户。问题是,约束删除阻止我的数据库在下一次测试之前刷新,test_user_something_else从test_create_dup_staffuser仍然剩下的所有数据开始(我通过注释掉alter table来验证这一点,这使得所有内容都能刷新)。

我怀疑从进入TestCase后我的更改在某种程度上阻止了测试结束时的事务回滚,但我不确定它是怎么做或该怎么办。我尝试在测试结束时放回约束,但结果相同。我还尝试添加一个tearDown并手动删除我的数据库中的所有数据,但这也无效。当我在下一次测试时在setUp开始时点击我的断点时,数据又回来了。

有人可以解释这里发生了什么,并建议我如何合理地测试这个功能?我的下一步可能是打开数据库日志以试图弄清楚发生了什么,但除此之外,我没有想法。

我已经考虑过的变通办法:

  • 使用迁移:我们的迁移很复杂并且有一些错误。修复/压缩它们在列表中,但尚未。
  • 重做课程:我可以(现在)想出各种方法来改变我的自定义用户类,使其变得不那么复杂,但是这段代码已经在生产和工作中了,所以我现在不能真正做到这一点,无论是。
  • 升级到django 1.7:它已经在列表中,但不会进入这个开发周期。
  • 暂时跳过该测试:这是我当前的备份计划。

使用django 1.5.8 / python 2.7 / mysql 5.5

1 个答案:

答案 0 :(得分:2)

  

我怀疑从进入TestCase后我的更改在某种程度上阻止了测试结束时的事务回滚,但我不确定它是怎么做或者该做些什么。

我认为就是这样。我建议移到TransactionTestCase,它不使用事务重置数据库。

为什么交易会在您的情况下搞砸?记住这些事情在不断变化,这个answer(由用户joeforker表示)表明你使用的MySQL将把模式改为“导致隐式提交”的指令处理,这肯定会弄乱什么TestCase期待。所以你的alter table命令会从TestCase的脚下“拉出地毯”(可以这么说)。