Unittest单元测试
Unittest单元测试
单元测试的定义
什么是单元测试
单元测试是指,对软件中的最小可测试单元在与程序其他部分相隔离的情况下进行检查和验证的工作,这里的最小可测试单元通常是指函数或者类,一般是开发来做的,按照测试阶段来分,就是单元测试、集成测试、系统测试以及验收测试。
为什么要做单元测试
- 单元测试之后,才是集成测试,单个单个的功能模块测试通过之后,才能把单个功能模块集成起来做集成测试,为了从底层发现bug,单元测试时可以减少合成后出现的问题。
- 越早发现bug越好,这样可以早点发现问题,不然问题累计到后面,很可能会因为一个做错了而导致整个模块甚至更大范围的推倒重来,对于时间和经费来说,是非常浪费的!
- 对于测试来说,单元测试就是为了执行用例,输入测试数据–>输出测试结果
unittest框架及原理
unittest单元测试框架是python自带的一套测试框架,不需要下载。
unittest框架最核心的四个概念:
- test case:就是我们的测试用例,unittest中提供了一个基本类TestCase,可以用来创建新的测试用例,一个TestCase的实例就是一个测试用例;unittest中测试用例方法都是以test开头的,且执行顺序会按照方法名的ASCII值排序。
- test fixure:测试夹具,用于测试用例环境的搭建和销毁。即用例测试前准备环境的搭建(SetUp前置条件),测试后环境的还原(TearDown后置条件),比如测试前需要登录获取token等就是测试用例需要的环境,运行完后执行下一个用例前需要还原环境,以免影响下一条用例的测试结果。
- test suite:测试套件,用来把需要一起执行的测试用例集中放到一块执行,相当于一个篮子。我们可以使用TestLoader来加载测试用例到测试套件中。
- test runner:用来执行测试用例的,并返回测试用例的执行结果。它还可以用图形或者文本接口,把返回的测试结果更形象的展现出来,如:HTMLTestRunner。
unittest的断言
在python基础中,我们有讲过一个assert断言,使用方法比较简单,即assert 表达式, 提示信息
,而unittest框架中也提供了一个自带的断言方式,主要有以下几种:
unittest断言 | |
---|---|
方法 | 检查 |
assertEqual(a, b,msg=None) | 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) |
如果断言失败即不通过就会抛出一个AssertionError
断言错误,成功则标识为通过,以上几种方式都有一个共同点,就是都有一个msg参数(表中只列了一个,其实都有),默认是None,即msg = None
,如果指定msg参数的值,则将该信息作为失败的错误信息返回。
1 | self.assertEqual('自动化测试_百度搜索', self.driver.title, msg='错误提示信息') # 等于 |
TestCase测试用例
编写测试用例前,我们需要建一个测试类继承unittest里面的TestCase类
,继承这个类之后我们才是真正的使用unittest框架去写测试用例,编写测试用例的步骤如下:
- 导入unittest模块
- 创建一个测试类,并继承
unittest.TestCase()
- 定义测试方法,
方法名必须以test开头
- 调用
unittest.main()
方法来运行测试用例,unittest.main()方法会搜索该模块下所有以test开头的测试用例方法,并自动执行 - 执行顺序会按照方法名的
ASCII值排序
,即 0-9,A-Z,a-z
TestFixure测试夹具
unittest的测试夹具有两种使用方式,一种是以测试方法为维度的setUp()
和tearDown()
,一种是以测试类为维度的setUpClass()
和tearDownClass()
。以注册功能为例,但这个注册代码比较简单,没有真正需要用到测试夹具的地方,因此这只是个用法演示。
- setUp前置条件:在每一条测试用例执行前执行
- tearDown后置条件:在每一条测试用例执行后执行
- setUpClass前置条件:在测试类执行前执行
- tearDownClass后置条件:在测试类执行后执行
注意:
- setupClass和tearDownClass需要
@classmethod修饰
- @classmethod指明这是个类方法以类为维度去执行的
TestSuite测试套件
unittest.TestSuite()类来表示一个测试用例集,把需要执行的用例类或模块存到一起,常用的方法如下:
unittest.TestSuite()
addTest()
:添加单个测试用例方法addTest([..])
:添加多个测试用例方法,方法名存在一个列表unittest.TestLoader() 或unittest.defaultTestLoader
loadTestsFromTestCase(测试类名)
:添加一个测试类loadTestsFromModule(模块名)
:添加一个模块discover(测试用例的所在目录)
:指定目录去加载,会自动寻找这个目录下所有符合命名规则的测试用例
TestRunner执行用例
test runner顾名思义就是用来执行测试用例的,并且可以生成相应的测试报告。测试报告有两种展示形式,一种是text文本,一种是html格式。
html格式的就是HTMLTestRunner了,HTMLTestRunner
是 Python 标准库的 unittest 框架的一个扩展,它可以生成一个直观清晰的 HTML 测试报告。使用的前提就是要下载 HTMLTestRunner.py,下载完后放在python的安装目录下的scripts目录下即可。
unittest.TextTestRunner()
run(测试套件)
HTMLTestRunner.HTMLTestRunner(stream=sys.stdout, verbosity=1, title=None, description=None)
- run(测试套件)
参数:
stream
:指定输出的方式title
:测试报告的标题description
:报告中要显示的面熟信息-
verbosity
:表示测试报告信息的详细程度,一共三个值,默认是2 - 0 (静默模式):你只能获得总的测试用例数和总的结果,如:总共100个 失败10 成功90
- 1 (默认模式):类似静默模式,只是在每个成功的用例前面有个. 每个失败的用例前面有个F
- 2 (详细模式):测试结果会显示每个测试用例的所有相关的信息
skip规则设定
在执行测试用例时,有时候有些用例是不需要执行的,那我们怎么办呢?难道删除这些用例?那下次执行时如果又需要执行这些用例时,又把它补回来?这样操作就太麻烦了。
unittest提供了一些跳过指定用例的方法。
- @unittest.skip(reason):强制跳转。reason是跳转原因
- @unittest.skipIf(condition, reason):condition为True的时候跳转
- @unittest.skipUnless(condition, reason):condition为False的时候跳转
- @unittest.expectedFailure:如果test失败了,这个test不计入失败的case数目
1 | import unittest |
unittest结合ddt数据驱动实战
1、创建Python Package命名为data
login_data.yml:
1 | - |
ceshi_data.yml:
1 | - |
2、创建Python Package命名为test_case
test_login.py:
1 | from selenium import webdriver |
test_ceshi.py:
1 | import unittest |
3、创建Python Package命名为run_case
run_case.py:
1 | import unittest |
4、创建Python Package命名为report
report包用于存放HTML测试报告
在run_case:run_case_html.py:
1 | import unittest |
5、HTML测试报告结果