unittest 核心思想
1. unittest介绍

python自带的一个单元测试框架。
具备完整的测试结构,支持自动化测试的执行,对测试用例进行组织,并提供了丰富的断言方法,最后会生成测试报告。
unittest核心工作原理
unittest中最核心的四个概念是:test case, test suite, test runner, test fixture
- TestCase:一个testcase的实例就是一个测试用例
- TestSUite:多个测试用例集合在一起
- TestLoader:是用来加载Testcase到Testsuite中的
- TextTestRunner:用来执行测试用例的,其中run(test)会执行testsuite/testcase中的run(result)方法
- TextTestResult:保存TextTestRunner执行的测试结果
- fixture:测试用例环境的搭建和销毁
写好TestCase,然后由TestLoader加载TestCase到TestSuite,然后由TextTestRunner来运行TestSuite,运行的结果保存在TextTestResult中,我们通过命令行或者unittest.main()执行时,main会调用TextTestRunner中的run来执行,或者我们可以直接通过TextTestRunner来执行用例。这里加个说明,在Runner执行时,默认将执行结果输出到控制台,我们可以设置其输出到文件,在文件中查看结果(你可能听说过HTMLTestRunner,是的,通过它可以将结果输出到HTML中,生成漂亮的报告,它跟TextTestRunner是一样的,从名字就能看出来,这个我们后面再说)。
unittest初级使用
1.导入unittest模块,被测文件或者其中的类
2.创建一个测试类,并继承unittest.Testcase 自己创建的单元测试类都要继承它,是所有单元测试类的基类
3.重写set up和tear down方法(如果有初始化条件和结束条件)
4.定义测试函数,函数名以test_开头,否则无法识别并执行。
5.在函数体中使用断言来判断测试结果是否符合预期结果
6.调用unittest.main()方法运行测试用例,执行顺序是按照case的命名,会搜索当前module下所有以test开头的测试用例并运行
2. 核心概念
2.1 测试脚手架
前置 测试 后置
test fixture:环境的准备以及关联的清理动作。setUp()------前置条件、tearDown()-----后置条件,用于初始化测试用例及清理和释放资源。(setUpClass()/tearDownClass())
- setUp():每个测试方法运行前运行,测试前置的初始化工作。
- tearDown():每个测试方法结束后运行,测试后的清理工作。
- setUpClass():所有的测试方法运行前运行,单元测试类运行前的准备工作。必须使用@classmethod装饰器进行装饰。整个测试类运行过程中只会执行一次。
- tearDownClass():所有的测试方法结束后运行,单元测试类运行后的清理工作。必须使用@classmethod装饰器进行装饰。整个测试类运行过程中只会执行一次。
2.2 测试用例
TestCase:是最小的测试单元,用于检测特定的输入集合的特定的返回值。unittest提供了TestCase基类,我们创建的测试类需要继承该基类,它可以用来创建新的测试用例。
测试用例,通过继承unittest.TestCase,来实现用例的继承,Unitest中,测试用例都是通过test来识别的。
2.3 测试套件
- 直接通过unittest.main()方法加载单元测试的测试模块,这是一种最简单的加载方法。所有的测试用例的执行顺序都是按照方法名的字符串表示的
ASCII码升序排序。 - 将所有的单元测试用例TestCase加载到测试套件Test Suite集合中,然后一次性加载所有测试对象。
test suit是一系列的测试用例
测试套件是测试用例,测试套件或两者的集合。用于组装一组要运行的测试。
测试套件,也称为测试用例集,它用于归档需要一起执行的测试。
Test Suite
Test Loader
该类根据各种标准加载测试用例,并将它们返回给测试套件。正常情况下,不需要创建这个类的实例。unittest提供了可以共享的defaultTestLoader类,可以使用其子类和方法创建实例,discover()就是其中之一。
discover(start_dir,pattern='test*.py',top_level_dir=None)
找到指定目录下所有测试模块,并可递归查到子目录下的测试模块,只有匹配到文件名才能被加载。如果启动的不是顶层目录,那么顶层目录必须单独指定。
start_dir:要测试的模块名或测试用例目录pattern='test*.py':表示用例文件名的匹配原则。此处匹配文件名以“test”开头的“.py”类型的文件,幸好“*”表示任意多个字符top_level_dir=None:测试模块的顶层目录,如果没有顶层目录,默认为None
2.4 测试运行器
test runner 一个用于执行和输出测试结果的组件。
TextTestRunner()
beautifulreport
3. 单元测试案例
3.1 测试目标函数
testcode.py
3.2 设计用例
根据函数的参数和逻辑,设计如下用例:
| 序号 | 标题 | 测试数据 | 预期结果 | 实际结果 |
|---|---|---|---|---|
| 1 | 账号密码正确 | {"username":"python45", "password":"lemonban"} | {"code": 0, "msg": "登录成功"} | |
| 2 | 账号正确密码不正确 | {"username":"python45", "password":"lemonban123"} | {"code": 1, "msg": "账号或密码不正确"} | |
| 3 | 账号错误密码正确 | {"username":"python45123", "password":"lemonban"} | {"code": 1, "msg": "账号或密码不正确"} | |
| 4 | 账号正确,密码长度小于6 | {"username":"python45", "password":"lemo"} | {"code": 1, "msg": "密码长度在6-18位之间"} | |
| 5 | 账号正确,密码长度大于18位 | {"username":"python45", "password":"lemonbanlemonbanlemonbanlemonbanlemonban"} | {"code": 1, "msg": "密码长度在6-18位之间"} |
3.3.编写测试用例并运行
编写步骤:
-
导入
unittest模块,被检测函数或者类 -
创建测试类,继承
unittest.TestCase -
如果有初始化条件和结束条件需要编写脚手架代码
-
定义测试函数,函数名一定要以test开头
-
调用
unittest.main()方法运行测试用例test_login.py
3.4 测试脚手架
unittest的脚手架有4个?
- setUp 在每个单元测试开始之前执行
- tearDown在每个单元测试结束之后执行
- setUpClass 在整个测试用例类开始前执行
- tearDownClass 在整个测试用例类测试结束之后执行
3.5 单元测试的执行顺序
按照单元测试函数名的ASCII编码来排序。
3.6 断言方法
| 方法 | 检查 |
|---|---|
| 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 |
| assertIn(a,b) | a in b |
| assertNotIn(a,b) | a not in b |
4. 测试套件
测试套件就是收集所有的测试用例,然后集中执行。
4.1 通过TestSuite对象收集
这个麻烦,实际不用
4.2 通过TestLoader对象收集
unittest.defaultTestLoader.discover()
discover方法可以根据给定的目录,去自动查找目录下所有符合要求的测试用例,它接受三个参数:
- start_dir 需要查找的目录
- pattern 查找模块名的规则,保持默认就好
- top_level_dir 项目的顶层目录,保持默认就好
注意了:pattern=test*.py参数的规则,需要收的模块名必须以test开头
5. 执行用例&生成报告
直接输出的报告比较丑陋,比如TextTestRunner(unittest自带的)
-
HTMLTestRunnerNew 未知作者,更新什么的不靠谱,不用了
-
BeautifulReport 通过pip可以安装
- pip install beautifulreport
-
unittestreport 零檬班-木森老师开发的
- pip install unittestreport
main.py
6.忽略某个测试方法
unittest提供了一些跳过指定用例的方法
- @unittest.skip(reason):强制跳转。reason是跳转原因
- @unittest.skipIf(condition, reason):condition为True的时候跳转
- @unittest.skipUnless(condition, reason):condition为False的时候跳转
- @unittest.expectedFailure:如果test失败了,这个test不计入失败的case数目
执行结果:
可以看到skip有两个分别是test_2和test_3,因为他们的忽略条件都成立了。
7.HTML 测试报告生成
unittestteport 中封装了一个 TestRunner 类,可以用来代替 unittest 中的 TextTestRunner 来执行测试用例,执行完测试用例之后会自动生成测试报告。并且有多种报告风格可选
8、测试用例失败重运行
关于unittest重运行机制,unittestreport中提供了两种方式
方式一: rerun 装饰器
使用案例:使用 rerun 装饰失败需要重运行的用例,该用例失败后会自动重运行
参数说明1:
count:用来指定用例失败重运行的次数
interval:指定每次重运行的时间间隔
方式二:TestRunner.rerun 方法
使用案例:所有的用例失败,只要有失败的用例,会自动重运行该用例 用例正常编写即可
运行是使用 TestRunner.rerun_run 方法运行
参数说明2:
count:用来指定用例失败重运行的次数
interval:指定每次重运行的时间间隔
9.邮件发送测试报告
unittestreport 内部实现了发生测试结果到邮箱的方法,执行完测试用例之后调用发送测试报告的方法即可。发邮件的方法介绍:TestRunner 类中实现了 send_email 方法,可以方便用户,快速发送邮件。
使用案例
参数介绍 host: smtp 服务器地址 port:端口 user:邮箱账号 password:smtp 服务授权码 to_addrs:收件人邮箱地址(一个收件人传字符串,多个收件人传列表)
10. 发送测试结果到钉钉
关于把如果测试结果发送到钉钉群,unittestreport里面进行了封装。执行完用例之后,调用TestRunner对象的dingtalk_notice方法即可。 参数介绍 关于 dingtalk_notice 这个方法的参数如下,大家可以根据使用需求来进行选择。
- url: 钉钉机器人的 Webhook 地址
- key: (非必传:str 类型)如果钉钉机器人安全设置了关键字,则需要传入对应的关键字
- secret:(非必传:str 类型)如果钉钉机器人安全设置了签名,则需要传入对应的密钥
- atMobiles: (非必传,list 类型)发送通知钉钉中要@人的手机号列表,如:[137xxx,188xxx]
- isatall: 是否@所有人,默认为 False,设为 True 则会@所有人
- except_info:是否发送未通过用例的详细信息,默认为 False,设为 True 则会发送失败用例的详细信息
案例代码:
备注:关于钉钉群机器人的创建大家可以去看钉钉开放平台上的教程,关键字和秘钥,根据创建钉钉机器人时设置的去添加,没有设置就不需要传这个参数。
11. 多线程运行测试用例
注意点:
- 确保每个线程在执行的时候不会出现资源竞争(对全局依赖的数据进行修改)
- 用例类执行没有先后顺序的依赖关系
本文来自博客园,作者:测试玩家勇哥,转载请注明原文链接:https://www.cnblogs.com/Nephalem-262667641/articles/17302192.html

浙公网安备 33010602011771号