unittest简单介绍
- 单元测试框架
- 还可以适用WEB自动化测试用例的开发与执行
- 提供丰富的断言方法
- 官方文档:https://docs.python.org/zh-cn/3/library/unittest.html
unittest基础使用
1 # 导入unittest模块 2 import unittest 3 4 5 # 创建单元测试类,继承unittest.TestCase 6 class testCase(unittest.TestCase): 7 8 def setUp(self): 9 print("case执行前") 10 11 def tearDown(self): 12 print("case执行后") 13 14 @classmethod 15 def setUpClass(cls): 16 print("对象执行前") 17 18 @classmethod 19 def tearDownClass(cls): 20 print("对象执行后") 21 22 # 测试用例 23 def test_01(self): 24 print("test01") 25 26 def test_02(self): 27 print("test02") 28 29 30 if __name__ == '__main__': 31 unittest.main()
运行结果
1 对象执行前 2 case执行前 3 test01 4 case执行后 5 case执行前 6 test02 7 case执行后 8 对象执行后 9 10 11 Ran 2 tests in 0.002s 12 13 OK
这里包含的知识点:
unittest.Testcase
- 自己创建的单元测试类都要继承它,它是所有单元测试类的基类
setUp
- 用于每个测试用例执行前的初始化工作
- 所有类中方法的入参为 self ,定义实例变量也要 self.变量
tearDown
- 每个测试用例执行后的都会执行此方法
setUpClass
- 每个单元测试类运行前调用该方法,只会执行一次
- 属于类方法,需要加上装饰器 @classmethod
- 默认入参是 cls ,指的就是“类对象”本身,其实和self没什么区别,用法一致
tearDownClass
- 每个单元测试类运行后调用该方法,只会执行一次
- 属于类方法,需要加上装饰器 @classmethod
测试用例
- 必须以“test_”开头命名的方法,否则无法识别并执行
- 方法里面需要有断言,才能在最后运行时有该用例的执行结果
- 可包含多个测试用例
unittest.main()
- 运行单元测试
- 该命令会搜索当前module 下所有以 test开头的测试用例,并运行它们
- 执行顺序是按照case的命名
unitteest提供的各种断言方式
1 class testCase(unittest.TestCase): 2 3 def test_03(self): 4 # 断言 - 是否为True 5 flag = True 6 self.assertTrue(flag, msg="测试失败的信息,可不填") 7 8 def test_04(self): 9 # 断言 - 是否为False 10 flag = False 11 self.assertFalse(flag) 12 13 def test_05(self): 14 # 断言 - 提供的两个参数是否相同(任意类型) 15 self.assertEqual("123", "123") # 字符串 16 self.assertEqual({"a": 1}, {"a": 1}) # 字典 17 self.assertEqual([1, 2], [1, 2]) # 列表 18 self.assertEqual((1, 2), (1, 2)) # 元组 19 self.assertEqual({1, 2}, {1, 2}) # 集合 20 21 def test_06(self): 22 # 断言 - 列表是否相同 23 self.assertListtEqual([1, 2], [1, 2]) 24 25 def test_07(self): 26 # 断言 - 字典是否相同 27 self.assertDictEqual({"a": 1}, {"a": 1}) 28 29 def test_08(self): 30 # 断言 - 元组是否相同 31 self.assertTupleEqual((1, 2), (1, 2)) 32 33 def test_09(self): 34 # 断言 - 集合是否相同 35 self.assertSetEqual({1, 2}, {1, 2})
这是比较常见的断言方式,当然还有一些比较容易理解的断言方式就没有一一举例啦,具体可以看看下面列表
方法 | 等同于python里面的写法 |
assertEqual(a, b) | a == b |
assertNotEqual(a, b) | a != b |
assertTrue(x) | bool(x) is True |
assertFalse(x) | bool(x) is False |
assertIs(a, b) | a is b |
assertIsNot(a, b) | a is not b |
assertIsNone(x) | x is None |
assertIsNotNone(x) | x is not None |
assertIn(a, b) | a in b |
assertNotIn(a, b) | a not in b |
assertIsInstance(a, b) | isinstance(a, b) |
assertNotIsInstance(a, b) | not isinstance(a, b) |
assertRegex(s, r) | r.search(s) |
unittest测试用例跳过执行
1 class testCase(unittest.TestCase): 2 3 # 直接跳过 4 @unittest.skip("直接跳过") 5 def test_skip(self): 6 self.fail("shouldn't happen") 7 8 # 满足condition则跳过 9 @unittest.skipIf(1 < 2, "满足condition则跳过") 10 def test_skipIf(self): 11 print("skip if") 12 13 # 不满足condition则跳过 14 @unittest.skipUnless(sys.platform.startswith("win"), "需要window平台才不会跳过") 15 def test_skipUnless(self): 16 print("skip Unless") 17 18 # 预计该测试用例会测试失败 19 @unittest.expectedFailure 20 def test_fail(self): 21 self.assertEqual(1, 0, "broken") 22 23 # 方法体内跳出不执行case 24 def test_maybe_skipped(self): 25 if True: 26 self.skipTest("调用unittest的skipTest,在方法体内满足某些条件则跳过该case") 27 pass
运行结果
1 Skipped: 调用unittest的skipTest,在方法体内满足某些条件则跳过该case 2 3 Skipped: 直接跳过 4 5 Skipped: 满足condition则跳过 6 skip Unless 7 8 9 Ran 5 tests in 0.010s 10 11 OK (skipped=3, expected failures=1)
跳过执行测试用例共有四种写法
- @unittest.skip(reason) :跳过测试用例,reason 为测试被跳过的原因
- @unittest.skipIf(condition, reason) :当 condition 为真时,跳过测试用例。
- @unittest.skipUnless(condition, reason) :跳过测试用例,除非 condition 为真
- @unittest.expectedFailure :把测试用例标记为预计失败;如果测试不通过,会被认为测试成功;如果测试通过了,则被认为是测试失败
self.skipTest(reason)
在方法体内满足某些条件下才跳过执行该测试用例
跳过执行测试用例注意点
- 被跳过的测试的 setUp() 和 tearDown() 不会被运行
- 只输入 unittest.skip ,也可以正常跳过,不必写reason
- 若输入 unittest.skip() ,括号内必须写reason,不得为空
- 可以针对单元测试类级别设置跳过执行(在class声明上面直接加装饰器即可),该单元测试类所有测试用例不会被执行
- 被跳过的类的 setUpClass() 和 tearDownClass() 不会被运行
- 当方法体内调用了 self.skipTest(reason) 方法,该测试用例还是会调用 setUp() 和 tearDown()