我试图了解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连接对象都是一个类变量,不是吗?
答案 0 :(得分:2)
这两种方法有什么区别?在这两种情况下,RethinkDB连接对象都是类变量,不是吗?
主要区别在于执行的范围和顺序,类变量将在加载类本身时被定义和执行,而setupClass()
方法将在unittest
时被TestRethink
方法调用。运行测试时,该类将被实例化(它的行为有点像构造函数)。
在你的最小例子中,这应该没什么区别,但是如果你继承了ChartObjects
类,那么它就会。因为在第一种情况下,您将为所有子类共享一个数据库连接,而使用setup / teardown,每个子类将有一个连接。
答案 1 :(得分:1)
关于第一种方法。 conn
是TestRethink
类的成员。
关于第二种方法(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'>
unittest
将在设置子类期间处理异常,并将打印更多关于失败的详细信息,这将更容易调试测试失败的原因。
我建议使用unittest
方法或尝试使用具有良好API的pytest
模块来处理灯具。