unittest中setUp与tearDown
在unittest中用例执行的先后顺序是根据数字、字母的先后顺序来判定的,如果要按照预定的顺序执行方法如下:
1.用字母、数字先后顺序排序(缺点:用例名称会不够美观、杂乱无章)
2.用testsuite控制用例加载顺序(缺点:当case较多时,逐个添加非常麻烦)
每次执行用例时,unittest.TestCase的类下每个test开头的方法(就是用例)时,都会执行setUp和tearDown
如下:
import unittest class TestSetupTeardown(unittest.TestCase): def setUp(self): print('连接数据库成功...') def tearDown(self): print('关闭数据库。') def test_a(self): print('test_a') def test_b(self): print('test_b') if __name__ == '__main__': unittest.main()
执行效果如下:
setUp连接数据库,tearDown关闭数据库,这样反复执行,无疑是会增加数据库服务器资源的损耗,且浪费时间
而且下一个用例的执行需要依赖上一个用例的执行结果时,应该怎么办?
1.在需要依赖的case中,将上一个case单独拎出来做一个公用的方法。然后在进入这个case时先调用该方法。例如caseB需要caseA返回的结果,那么我先将caseA封装成一个通用的方法,根据传入的参数不同返回不同的值。然后在caseB中获取返回的值,作为caseB开始前的另一种变相的 ‘setup’。代码如下:
import unittest def set_A(a, b): a = a*2 b = b*2 return (a, b) class Test_setup_and_teardwon(unittest.TestCase): def setUp(self): self.a = 2 self.b = 3 print('set up over :') print('a = %s, b = %s \n'%(self.a, self.b)) def tearDown(self): a = 0 b = 0 print('tear down over :') print('a = %s, b = %s'%(a, b)) print('__________________________________________________________') def test_case_B(self): (a, b) = set_A(self.a, self.b) a = a*2 b = b*2 print('run B over :') print('a= %s, b = %s \n'%(a, b)) def test_case_A(self): a = self.a*2 b = self.b*2 print('run A over :') print('a = %s, a = %s \n'%(a, b)) def test_case_C(self): a = self.a*4 b = self.b*4 print('run C over :') print('a = %s, a = %s \n'%(a, b)) if __name__ == '__main__': suite = unittest.TestSuite() suite.addTest(Test_setup_and_teardwon("test_case_A")) suite.addTest(Test_setup_and_teardwon("test_case_B")) suite.addTest(Test_setup_and_teardwon("test_case_C")) runner = unittest.TextTestRunner() runner.run(suite)
执行结果:
set up over : .a = 2, b = 3 run A over : a = 4, a = 6 tear down over : a = 0, b = 0 __________________________________________________________ set up over : a = 2, b = 3 run B over : a= 8, b = 12 tear down over : .a = 0, b = 0 __________________________________________________________ set up over : a = 2, b = 3 run C over : .a = 8, a = 12 tear down over : a = 0, b = 0 __________________________________________________________ ---------------------------------------------------------------------- Ran 3 tests in 0.000s OK [Finished in 0.1s]
但是在测试用例难以解耦的情况下,每写下一个用例就要封装上一个用例的方法,这会导致代码长度翻倍增长。
因此在此处对于用例之间依赖性较强的模块,控制setUp和tearDown方法只执行一次很有必要
【解决方案】:
将setup() 和teardown() 换成setUpClass()和tearDownClass()
【注意事项】:
setUpClass():必须使用@classmethod 装饰器, 所有case运行之前只运行一次
tearDownClass():必须使用@classmethod装饰器, 所有case运行完之后只运行一次
执行效果如下:
import unittest
class TestSetupTeardown(unittest.TestCase):
@classmethod
def setUpClass(cls):
print('连接数据库成功...')
@classmethod
def tearDownClass(cls):
print('关闭数据库。')
def test_a(self):
print('test_a')
def test_b(self):
print('test_b')
if __name__ == '__main__':
unittest.main()
用例运行级别
-
模块级(setup_module/teardown_module)开始于模块始末,全局的
-
函数级(setup_function/teardown_function)只对函数用例生效(不在类中)
-
类级(setup_class/teardown_class)只在类中前后运行一次(在类中)
-
方法级(setup_method/teardown_method)开始于方法始末(在类中)
-
类里面的(setup/teardown)运行在调用方法的前后
# coding:utf-8 import pytest # 类和方法 def setup_module(): print("setup_module:整个.py模块只执行一次") print("比如:所有用例开始前只打开一次浏览器") def teardown_module(): print("teardown_module:整个.py模块只执行一次") print("比如:所有用例结束只最后关闭浏览器") def setup_function(): print("setup_function:每个用例开始前都会执行") def teardown_function(): print("teardown_function:每个用例结束前都会执行") def test_one(): print("正在执行----test_one") x = "this" assert 'h' in x def test_two(): print("正在执行----test_two") x = "hello" assert 'h' in x class TestCase(): def setup_class(self): print("setup_class:类中所有用例执行之前") def teardown_class(self): print("teardown_class:类中所有用例执行之后") def setup(self): print("setup:类中每个用例执行之前") def teardown(self): print("teardown:类中每个用例执行之后") def setup_method(self): print("setup_method:类中每个用例执行之前") def teardown_method(self): print("teardown_method:类中每个用例执行之后") def test_three(self): print("正在执行----test_three") x = "this" assert 'h' in x def test_four(self): print("正在执行----test_four") x = "hello" assert 'h' in x if __name__ == "__main__": pytest.main(["-s", "Testcase2.py"])
运行结果:
Testcase2.py setup_module:整个.py模块只执行一次 比如:所有用例开始前只打开一次浏览器 setup_function:每个用例开始前都会执行 .正在执行----test_one teardown_function:每个用例结束前都会执行 setup_function:每个用例开始前都会执行 .正在执行----test_two teardown_function:每个用例结束前都会执行 setup_class:类中所有用例执行之前 setup_method:类中每个用例执行之前 setup:类中每个用例执行之前 .正在执行----test_three teardown:类中每个用例执行之后 teardown_method:类中每个用例执行之后 setup_method:类中每个用例执行之前 setup:类中每个用例执行之前 .正在执行----test_four teardown:类中每个用例执行之后 teardown_method:类中每个用例执行之后 teardown_class:类中所有用例执行之后 teardown_module:整个.py模块只执行一次 比如:所有用例结束只最后关闭浏览器
setup_module/teardown_module的优先级是最大的,然后函数里面用到的setup_function/teardown_function与类里面的setup_class/teardown_class互不干涉
类里面的setup_method和teardown_method的功能和setup/teardown功能是一样的,一般二者用其中一个即可
参考原文链接:
https://www.cnblogs.com/UncleYong/p/7076872.html
https://blog.csdn.net/qq_27261401/article/details/78312252
https://blog.csdn.net/yaoliuwei1426/article/details/82146316