Python单元测试setUp和tearDown用法详解

到目前为止,针对 unittest 已经介绍了测试用例类(TestCase的子类)、测试包(TestSuite)和测试运行器(TestRunner)。此外,unittest 还有测试固件(Test Fixture)的概念:
  • 测试用例类:测试用例类就是单个的测试单元,其负责检查特定输入和对应的输出是否匹配。unittest 提供了一个 TestCase 基类用于创建测试用例类。
  • 测试包:用于组合多个测试用例,测试包也可以嵌套测试包。
  • 测试运行器:负责组织、运行测试用例,并向用户呈现测试结果。
  • 测试固件:代表执行一个或多个测试用例所需的准备工作,以及相关联的准备操作,准备工作可能包括创建临时数据库、创建目录、开启服务器进程等。

unittest.TestCase 包含了 setUp() tearDown() 两个方法,其中 setUp() 方法用于初始化测试固件;而 tearDown() 方法用于销毁测试固件。程序会在运行每个测试用例(以 test_ 开头的方法)之前自动执行 setUp() 方法来初始化测试固件,井在每个测试用例(以 test_ 开头的方法)运行完成之后自动执行 tearDown() 方法来销毁测试固件。

由此可见,如果希望程序为测试用例初始化、销毁测试固件,那么只要重写 TestCase 的 setUp() 和 tearDown() 方法即可。例如如下测试程序(fixture_test.py):
import unittest

from hello import *

class TestHello(unittest.TestCase):
    # 测试say_hello函数
    def test_say_hello(self):
        self.assertEqual(say_hello() , "Hello World.")
    # 测试add函数
    def test_add(self):
        self.assertEqual(add(3, 4) , 7)
        self.assertEqual(add(0, 4) , 4)
        self.assertEqual(add(-3, 0) , -3)
    def setUp(self):
        print('\n====执行setUp模拟初始化固件====')
    def tearDown(self):
        print('\n====调用tearDown模拟销毁固件====')
使用如下命令来运行该测试程序:

python -m unittest -v fixture_test.py

为该命令添加了 -v 选项,该选项用于告诉 unittest 生成更详细的输出信息。此时可以看到如下输出结果:

test_add (fixture_test1.TestHello) ...
====执行setUp模拟初始化固件====

====调用tearDown模拟销毁固件====
ok
test_say_hello (fixture_test1.TestHello) ...
====执行setUp模拟初始化固件====

====调用tearDown模拟销毁固件====
ok

----------------------------------------------------------------------
Ran 2 tests in 0.002s

OK

从上面的输出结果可以看出,unittest 在运行每个测试用例(以 test_ 开头的方法)之前都执行了 setUp() 方法,在每个测试用例(以 test_ 开头的方法)运行完成之后都执行了 tearDown() 方法。

如果希望程序在该类的所有测试用例执行之前都用一个方法来初始化测试固件,在该类的所有测试用例执行之后都用一个方法来销毁测试固件,则可通过重写 setUpClass() 和 tearDownClass() 类方法来实现。

例如如下测试程序(fixture_test1.py):
import unittest

from hello import *

class TestHello(unittest.TestCase):
    # 测试say_hello函数
    def test_say_hello(self):
        self.assertEqual(say_hello() , "Hello World.")
    # 测试add函数
    def test_add(self):
        self.assertEqual(add(3, 4) , 7)
        self.assertEqual(add(0, 4) , 4)
        self.assertEqual(add(-3, 0) , -3)
    @classmethod
    def setUpClass(cls):
        print('\n====执行setUpClass在类级别模拟初始化固件====')
    @classmethod
    def tearDownClass(cls):
        print('\n====调用tearDownClass在类级别模拟销毁固件====')
上面程序中定义的 setUpClass() 和 tearDownClass() 两个类方法也是用于初始化测试固件和销毁测试固件的方法,但它们会在该类的所有测试用例执行之前和执行之后执行。

使用如下命令来运行该测试程序:

python -m unittest -v fixture_test1.py

可以看到如下输出结果:

====执行setUpClass在类级别模拟初始化固件====
test_add (fixture_test2.TestHello) ... ok
test_say_hello (fixture_test2.TestHello) ... ok

====调用tearDownClass在类级别模拟销毁固件====

----------------------------------------------------------------------
Ran 2 tests in 0.001s

OK