在unittest.TestCase中,self.attr在测试之间会重置。

7

我希望能够使用unittest.TestCase类的self.attr,但是似乎在测试之间它不是持久化的:

import unittest

class TestNightlife(unittest.TestCase):
    _my_param = 0

    def test_a(self):
        print 'test A = %d' % self._my_param
        self._my_param = 1

    def test_b(self):
        print 'test B = %d' % self._my_param
        self._my_param = 2

if __name__ == "__main__":
    unittest.main()

这将产生以下输出:
test A = 0
test B = 0
< p >运行测试时,unittest.TestCase实例是否会改变?为什么?


动机:当然你不能假设测试的顺序,但有时某个测试会改变环境,另一个测试需要知道它是否已经被改变,以便采取或避免某些操作。有时,将这些信息保存在变量中比检查并报告状态的辅助函数更简单和可读。即使你不同意这种观点,了解 self 在测试之间发生了什么仍然是很有趣的问题。 - Jonathan Livni
1个回答

9

这样做的原因是因为unittest.main()为每个测试创建单独的对象(在这种情况下,创建了两个对象)。

关于您的动机:测试不应更改全局状态。您应该在tearDown或测试本身中将全局状态恢复到测试之前的状态。如果测试更改全局状态,那么您将很快面临无法预测的情况。

import unittest

class TestNightlife(unittest.TestCase):
    _my_param = 0

    def test_a(self):
        print 'object id: %d' % id(self)
        print 'test A = %d' % self._my_param
        self._my_param = 1

    def test_b(self):
        print 'object id: %d' % id(self)
        print 'test B = %d' % self._my_param
        self._my_param = 2

if __name__ == "__main__":
    unittest.main()

输出:

object id: 10969360
test A = 0
.object id: 10969424
test B = 0
.
----------------------------------------------------------------------
Ran 2 tests in 0.000s

OK

1
我完全同意关于全局状态的观点,尽管我这样做是为了加快测试速度,实用性胜过纯粹... - Jonathan Livni
顺便问一下,你有证据证明unittest.main()会为每个测试创建单独的对象吗?如果是,请添加它,我会将该问题标记为已解决。 - Jonathan Livni
我没有参考文档的引用,unittest就是那样工作的(请参见示例代码)。 - Tomasz Wysocki

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接