Class Python 单元测试中的固定装置
Class fixtures in Python's unittest
我正在尝试理解 Python 的 unittest
模块中的 class fixtures。为了加快测试速度,我想在每个 class 中只创建一个 'expensive' 连接对象。乍一看,我想到了这样做:
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 连接对象都是一个 class 变量,不是吗?
What is the difference between the two approaches? In both cases the RethinkDB connection object is a class variable, isn't it?
主要区别在于执行范围和顺序,class 变量将在加载 class 本身时定义和执行,而 setupClass()
方法将被调用通过 unittest
在 运行 你的测试时,class 将被实例化(它的行为有点像构造函数)。
在您的最小示例中,这应该没什么区别,但是如果您将 class 替换为您的 TestRethink
class,那么它就会。因为在第一种情况下,您将为所有子 class 共享一个数据库连接,而对于 setup/teardown,每个子class.[=14= 将有一个连接]
差异 #1
关于第一种方法。 conn
是 TestRethink
class 的 class 成员。
在第二种方法(unittest
方法)中,TestRethink
的每个子class 将有其自己的不同连接,这意味着每个 TestCase
class 将有自己的连接实例。
使用 @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
将在设置子 classes 期间处理异常,并将打印有关失败的更多详细信息,这将更容易调试测试失败的原因。
我建议使用 unittest
方法或尝试 pytest
模块,它有很好的 API 来处理固定装置。
我正在尝试理解 Python 的 unittest
模块中的 class fixtures。为了加快测试速度,我想在每个 class 中只创建一个 'expensive' 连接对象。乍一看,我想到了这样做:
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 连接对象都是一个 class 变量,不是吗?
What is the difference between the two approaches? In both cases the RethinkDB connection object is a class variable, isn't it?
主要区别在于执行范围和顺序,class 变量将在加载 class 本身时定义和执行,而 setupClass()
方法将被调用通过 unittest
在 运行 你的测试时,class 将被实例化(它的行为有点像构造函数)。
在您的最小示例中,这应该没什么区别,但是如果您将 class 替换为您的 TestRethink
class,那么它就会。因为在第一种情况下,您将为所有子 class 共享一个数据库连接,而对于 setup/teardown,每个子class.[=14= 将有一个连接]
差异 #1
关于第一种方法。 conn
是 TestRethink
class 的 class 成员。
在第二种方法(unittest
方法)中,TestRethink
的每个子class 将有其自己的不同连接,这意味着每个 TestCase
class 将有自己的连接实例。
使用 @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
将在设置子 classes 期间处理异常,并将打印有关失败的更多详细信息,这将更容易调试测试失败的原因。
我建议使用 unittest
方法或尝试 pytest
模块,它有很好的 API 来处理固定装置。