Python的单元测试

时间:2017-01-23 09:56:50

标签: python python-unittest

我试图了解Python unittest模块中的class fixtures。为了加快测试速度,我想创建一个“昂贵”的产品。连接对象在每个类中只有一次。乍一看,我想这样做:

import unittest
import rethinkdb as r

class TestRethink(unittest.TestCase):
    conn = r.connect('localhost', 28016)

    def test_table_list(self):
        r.table_list().run(self.conn)

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

然而,从文档中可以看出,人们应该这样做:

import unittest
import rethinkdb as r

class TestRethink(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        cls.conn = r.connect('localhost', 28016)

    def test_table_list(self):
        r.table_list().run(self.conn)

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

这两种方法有什么区别?在这两种情况下,RethinkDB连接对象都是一个类变量,不是吗?

2 个答案:

答案 0 :(得分:2)

  

这两种方法有什么区别?在这两种情况下,RethinkDB连接对象都是类变量,不是吗?

主要区别在于执行的范围和顺序,类变量将在加载类本身时被定义和执行,而setupClass()方法将在unittest时被TestRethink方法调用。运行测试时,该类将被实例化(它的行为有点像构造函数)。

在你的最小例子中,这应该没什么区别,但是如果你继承了ChartObjects类,那么它就会。因为在第一种情况下,您将为所有子类共享一个数据库连接,而使用setup / teardown,每个子类将有一个连接。

答案 1 :(得分:1)

差异#1

关于第一种方法。 connTestRethink类的成员。

关于第二种方法(unittest方法),TestRethink的每个子类都将使其拥有不同的连接,这意味着每个TestCase类都有自己的连接实例

使用@classmethod时的差异示例:

class A(object):
    @classmethod
    def setup(cls):
        cls.conn = 'my connection for %r' % cls

class B(A):
    pass

class C(A):
    pass


# setup the tests
B.setup()
C.setup()

b = B()
c = C()
print(b.conn)
print(c.conn)

此代码输出:

my connection for <class '__main__.B'>
my connection for <class '__main__.C'>

差异#2

unittest将在设置子类期间处理异常,并将打印更多关于失败的详细信息,这将更容易调试测试失败的原因。

我建议使用unittest方法或尝试使用具有良好API的pytest模块来处理灯具。