Selenium实战(四)——unittest单元测试3(测试用例的执行顺序)
一、测试用例的执行顺序
层级:多个测试目录 > 多个测试文件 > 多个测试类 > 多个测试方法(测试用例)。在这里以一个测试执行顺序的脚本为例test_order.py
1 import unittest 2 3 4 class TestBdd(unittest.TestCase): 5 6 def setUp(self): 7 print("test TestBdd") 8 9 def test_ccc(self): 10 print("test ccc") 11 12 def test_aaa(self): 13 print("test aaa") 14 15 16 class TestAdd(unittest.TestCase): 17 18 def setUp(self): 19 print("test TestAdd") 20 21 def test_bbb(self): 22 print("test bbb") 23 24 25 if __name__ == '__main__': 26 unittest.main()
无论执行多少次,结果都是一样。因为unittest默认分局ASCII码的顺序加载测试用例(数字与字母的顺序为0~9,A~Z,a~z),所以TestAdd类会优先于TestBdd类被执行,test_aaa()方法会优先于test_ccc()方法被执行,也就是说,它并不是按照测试用例的顺序从上到下执行的。
那么要想不被命名限制,自己指定执行顺序,就要用到测试套件TestSuit类,通过addTest()方法按照一定的顺序来加载测试用例。修改以上测试用例如下:
1 if __name__ == '__main__': 2 # 构造测试集 3 suite = unittest.TestSuite() 4 suite.addTest(TestBdd("test_aaa")) 5 6 suite.addTest(TestAdd("test_bbb")) 7 suite.addTest(TestBdd("test_ccc")) 8 9 # 执行测试 10 runner = unittest.TextTestRunner() 11 runner.run(suite)
执行结果如下:
不过当测试用例非常多时,不推荐用这种方法创建测试套件,最好的办法是通过命名控制执行顺序。如果测试用例在设计时不产生相互依赖,那么测试用例的执行顺序就没那么重复了。
Tips: 如果使用discover()方法要执行某测试文件夹下子目录中的测试文件,可在每个子目录下放一个__init__.py文件(作用是将一个目录标记成一个标准的Python模块)
二、跳过测试和预期失败
在运行测试时,有时需要直接跳过某些测试用例,或者当测试用例符合某个条件时跳过测试,又或者直接将测试用例设置为失败。unittest提供了实现这些需求的装饰器。
1 unittest.skip(reason)
无条件地跳过装饰的测试,需要说明跳过测试的原因。
1 unittest.skipIf(condition, reason)
如果条件为真,则跳过装饰的测试
1 unittest.skipUnless(condition,reason)
当条件为真时,执行装饰的测试
1 unittest.exceptedFailure()
不管执行结果是否失败,都将测试标记为失败。下面是测试用例:test_skip.py文件:
1 import unittest 2 3 4 class MyTest(unittest.TestCase): 5 6 @unittest.skip("直接跳过测试") 7 def test_skip(self): 8 print("test aaa") 9 10 @unittest.skipIf(3 > 2, "当条件为真时跳过测试") 11 def test_skip_if(self): 12 print("test bbb") 13 14 @unittest.skipUnless(3 > 2, "当条件为真时执行测试") 15 def test_skip_unless(self): 16 print('test ccc') 17 18 @unittest.expectedFailure 19 def test_expected_failure(self): 20 self.assertEqual(2, 3) 21 22 23 if __name__ == '__main__': 24 unittest.main()
执行结果如下:
当然,这些方法同样适用于测试类,只需将它们针对测试类装饰即可。
1 import unittest 2 3 @unittest.skip("直接跳过,不测试该类") 4 class MyTest(unittest.TestCase): 5 #……
三、Fixture
可以将测试套件比作夹心饼干,setUp/tearDown是两片饼干,测试用例是中间的奶油。test_fixture.py文件:
1 import unittest 2 3 4 def setUpModule(): 5 print("test module start >>>>>>>>>>>>>") 6 7 8 def tearDownModule(): 9 print("test module end >>>>>>>>>>>>>>>") 10 11 class MyTest(unittest.TestCase): 12 13 @classmethod 14 def setUpClass(self): 15 print("test class start ============>") 16 17 @classmethod 18 def tearDownClass(self): 19 print("test class end ==============>") 20 21 def setUp(self): 22 print("test case start ------------->") 23 24 def tearDown(self): 25 print("test case end --------------->") 26 27 def test_case1(self): 28 print("test case1") 29 30 def test_case2(self): 31 print("test case2") 32 33 34 if __name__ == '__main__': 35 unittest.main()
需要注意的是,setUpClass/tearDownClass为类方法,需要通过@classmethod进行装饰。另外,方法的参数为cls。其实,cls与self没什么本质区别,都指标是方法的第一个参数。