目录
一、unittest简介
二、基本概念
三、unittest基础使用
四、unitteest提供的各种断言方式
五、unittest测试用例跳过执行
六、总结
测试框架-unittest,相当于是一个 python 版的 junit。python 里面的单元测试框架除了 unittest,还有一个 pytest 框架,这个实际上用的比较少,后面有空再继续介绍和分享。unittest单元测试框架不仅可以适用于单元测试,还可以适用WEB自动化测
试用例的开发与执行,该测试框架可组织执行测试用例,并且提供了丰富的断言方法,判断测试用例是否通过,最终生成测试结果。查看其中文官网:docs.python.org/zh-cn/3/lib… 英文官网:docs.python.org/3/library/u…
Unittest支持的功能
Unittest使用方法
导入unittest模块:import unittest
测试类需要继承unitest.TestCase
测试用例必须以test开头
assert断言来判断测试结果
使用HTMLTestRunner生产测试报告
test fixture:一般用于准备及清理工作;
test case:通常是使用assert方法检查动作和输入的响应,一般是基于TestCase类扩充;
test suite:多个测试的集合;
test runner:测试执行;
class TestDemo(unittest.TestCase)
复制代码
import unittest
class TestDemo(unittest.TestCase):
@classmethod
def setupClass(cls):
print("hello world")
复制代码
import unittest
class TestDemo(unittest.TestCase):
@classmethod
def tearDownClass(cls):
print("tearDownClass")
复制代码
import unittest
class TestDemo(unittest.TestCase):
def setUp(self):
print("setUp")
复制代码
import unittest
class TestDemo(unittest.TestCase):
def tearDown(self):
print("tearDown")
复制代码
import unittest
class TestDemo(unittest.TestCase):
def test_case1(self):
print('test_case1')
复制代码
执行方法的默认顺序是:根据ASCII码的顺序加载测试用例,数字与字母的顺序为:0-9,A-Z,a-z。所以以A开头的测试用例方法会优先执行,以a开头会后执行。
例如:将test_Demo1模块下的TestDemo1类下的test_case1测试用例添加到测试套件中
suite = unittest.TestSuite() suite.addTest(test_Demo1.TestDemo1('test_case1'))
复制代码
unittest.TestLoader().loadTestsFromName()
unittest.TestLoader().loadTestsFromNames()
unittest.TestLoader().loadTestsFromTestCase()
unittest.TestLoader().loadTestsFromModule()
unittest.TestLoader().discover()
复制代码
加载一个目录下所有的测试用例:通过测试加载器:加载测试用例套件或者测试用例
import unittest if __name__ == '__main__':
# discover发现
# 在punlic目录下寻找test_开头的py文件
suite=unittest.defaultTestLoader.discover("./public",pattern='test_*.py')
unittest.main(defaultTest="suite")
复制代码
例如:将test_case包下的test_Demo1模块下的TestDemo1类下的test_case1测试用例添加到测试套件中:
suite = unittest.TestSuite()
suite.addTests(unittest.TestLoader().loadTestsFromName('test_case.test_Demo1.TestDemo1.test_case1'))
复制代码
discover=unittest.defaultTestLoader.discover(test_dir, pattern='test_*.py')
复制代码
suite = unittest.TestSuite()
suite.addTest(TestDemo('test_case1'))
runner = unittest.TextTestRunner()
runner.run(suite)
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
复制代码
这里包含的知识点:
自己创建的单元测试类都要继承它,它是所有单元测试类的基类
用于每个测试用例执行前的初始化工作
所有类中方法的入参为 self ,定义实例变量也要 self.变量
每个测试用例执行后的都会执行此方法
每个单元测试类运行前调用该方法,只会执行一次
属于类方法,需要加上装饰器 @classmethod
默认入参是 cls ,指的就是“类对象”本身,其实和self没什么区别,用法一致
每个单元测试类运行后调用该方法,只会执行一次
属于类方法,需要加上装饰器 @classmethod
必须以“test_”开头命名的方法,否则无法识别并执行
方法里面需要有断言,才能在最后运行时有该用例的执行结果
可包含多个测试用例
运行单元测试
该命令会搜索当前module 下所有以 test开头的测试用例,并运行它们
执行顺序是按照case的命名
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) |
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 :把测试用例标记为预计失败;如果测试不通过,会被认为测试成功;如果测试通过了,则被认为是测试失败
在方法体内满足某些条件下才跳过执行该测试用例
被跳过的测试的 setUp() 和 tearDown() 不会被运行
只输入 unittest.skip ,也可以正常跳过,不必写reason
若输入 unittest.skip() ,括号内必须写reason,不得为空
可以针对单元测试类级别设置跳过执行(在class声明上面直接加装饰器即可),该单元测试类所有测试用例不会被执行
被跳过的类的 setUpClass() 和 tearDownClass() 不会被运行
当方法体内调用了 self.skipTest(reason) 方法,该测试用例还是会调用 setUp() 和 tearDown()
本期,我们对Python提供的unittest单元测试模块,对其工作原理以及unittest执行步骤进行了解和学习。
我们在写自动化用例后,可以使用unittest测试验证我们用例正确和稳定性。
以上是本期内容,欢迎大佬们评论区写出你们的问题,下期见~
B站最牛的Python自动化测试框架全栈测试开发实战项目入门到精通,涨薪必备教程!!!