unittest 提供了针对测试方法、测试类、测试模块三种范围的测试固件,每个范围都有初始化和清理两种固件。
测试方法
setUp() 和 tearDown() 两个方法是针对测试用例方法级别的测试固件。
在当前测试类中重写这两个方法,当前测试类中的所有测试方法都会执行这两个测试固件。
在每个测试方法运行之前运行 setUp(), 在每个测试方法运行之后运行 tearDown()。注意是每个测试方法。
这就类似某些框架中提供的钩子hook
函数。
我们把前面的案例改造一下,加上了 setUp() 和 tearDown(),为了方便观察,每个用例执行了一条打印语句:
import unittest
def add(a, b):
return a+b
class TestAdd(unittest.TestCase):
def setUp(self):
print('\n**********执行初始化方法************')
def tearDown(self):
print('\n**********执行清理方法************')
def test_add_int(self):
'''测试int相加'''
result = add(5, 100)
print('用例1结果:', result)
self.assertEqual(result, 105, '整数相加错误')
def test_add_str(self):
'''测试str相加'''
result = add('5', '6')
print('用例2结果:', result)
self.assertEqual(result, '56', '字符串相加错误')
def test_add_list(self):
result = add(['1', '2'], ['a', 'b'])
print('用例3结果:', result)
self.assertEqual(result, ['1','2','a','b'], '列表相加错误')
if __name__ == "__main__":
unittest.main()
运行看看结果:
...
**********执行初始化方法************
用例1结果: 105
**********执行清理方法************
**********执行初始化方法************
用例3结果: ['1', '2', 'a', 'b']
**********执行清理方法************
**********执行初始化方法************
用例2结果: 56
**********执行清理方法************
----------------------------------------------------
Ran 3 tests in 0.001s
OK
可以看到结果中,setUp() 方法执行了 3 次,而 tearDown() 方法也执行了 3 次。
当然,这里为了演示只是写了一条打印语句,具体初始化和清理方法应该写哪些代码,取决于你的测试策略。
测试类
接下来,我们看看基于测试类的固件 setUpClass() 和 tearDownClass() ,这两个方法必须作为类方法来定义。
运行效果为每个测试类中的第一个测试方法开始运行之前与进行 setUpClass() ,在最后一个测试方法运行之后运行 tearDownClass() 。
也就是说,每个测试类,测试固件只会运行一次。
同样,改造一下之前的案例。
import unittest
def add(a, b):
return a+b
class TestAdd(unittest.TestCase):
@classmethod # 类方法需要加上classmethod装饰器
def setUpClass(cls): # => 第一个参数为cls
print('\n*******执行类级别的初始化方法setUpClass*********')
@classmethod
def tearDownClass(cls):
print('\n*******执行类级别的清理方法tearDownClass********')
def test_add_int(self):
'''测试int相加'''
result = add(5, 100)
print('用例1结果:', result)
self.assertEqual(result, 105, '整数相加错误')
def test_add_str(self):
'''测试str相加'''
result = add('5', '6')
print('用例2结果:', result)
self.assertEqual(result, '56', '字符串相加错误')
def test_add_list(self):
result = add(['1', '2'], ['a', 'b'])
print('用例3结果:', result)
self.assertEqual(result, ['1','2','a','b'], '列表相加错误')
if __name__ == "__main__":
unittest.main()
注意在写法上:
@classmethod # 类方法需要加上classmethod装饰器
def setUpClass(cls): # => 第一个参数为cls
print('\n*******执行类级别的初始化方法setUpClass*********')
setUpClass(cls) 必须要写为 类方法,所以必须要加上classmethod装饰器,并且第一个参数使用 cls
运行结果如下:
...
**********执行类级别的初始化方法setUpClass************
用例1结果: 105
用例3结果: ['1', '2', 'a', 'b']
用例2结果: 56
**********执行类级别的清理方法tearDownClass************
----------------------------------------------------------------------
Ran 3 tests in 0.000s
OK
可以从结果中看到类测试固件只会在每个测试类中执行一次。
模块级别
模块级别指的是文件级别。Python 中文件即模块,所以你可以理解为每个文件只运行一次 ,不管你的这个测试文件中有多少的测试类和测试方法。
注意,测试模块(也就是测试文件)一定要包含
test
字样。虽然不是必须,但是会影响一些工具的默认测试模块的查找功能。
实现模块级别的固件,是使用 setUpModule() 和 tearDownModule() 两个函数(注意是函数,不是方法,写在类外面),函数的位置不重要,只要是在当前测试文件中实现这两个方法即可。
为了更好的演示,我把之前的示例拆为了两个类,用例方法不变。
import unittest
def setUpModule(): # => 初始化固件
print('\n********执行模块级别的初始化方法setUpModule**********')
def tearDownModule(): # => 清理固件
print('\n********执行模块级别的初始化方法tearDownModule**********')
def add(a, b):
return a+b
class TestAddOne(unittest.TestCase):
def test_add_int(self):
'''测试int相加'''
result = add(5, 100)
print('用例1结果:', result)
self.assertEqual(result, 105, '整数相加错误')
def test_add_str(self):
'''测试str相加'''
result = add('5', '6')
print('用例2结果:', result)
self.assertEqual(result, '56', '字符串相加错误')
class TestAddTwo(unittest.TestCase):
def test_add_list(self):
result = add(['1', '2'], ['a', 'b'])
print('用例3结果:', result)
self.assertEqual(result, ['1','2','a','b'], '列表相加错误')
if __name__ == "__main__":
unittest.main()
查看运行结果:
...
********执行模块级别的初始化方法setUpModule**********
用例1结果: 105
用例2结果: 56
用例3结果: ['1', '2', 'a', 'b']
********执行模块级别的初始化方法tearDownModule**********
----------------------------------------------------------------------
Ran 3 tests in 0.000s
OK
针对模块的测试固件每个文件只运行一次。
网友评论