Unittest框架使用教程
-
- UnitTest框架介绍
- [1. UnitTest框架的组件](#1. UnitTest框架的组件)
-
- [TestCase 测试用例](#TestCase 测试用例)
- [TestSuite 测试套件](#TestSuite 测试套件)
- [TestLoader 测试加载](#TestLoader 测试加载)
- [TestRunner 测试执行](#TestRunner 测试执行)
- [Fixture 测试夹具](#Fixture 测试夹具)
- [2. TestLoader与TestSuite区别](#2. TestLoader与TestSuite区别)
- [3. 断言与参数化](#3. 断言与参数化)
- [4. 测试报告和跳过](#4. 测试报告和跳过)
UnitTest框架介绍
框架(framework):
为解决一类事情的功能集合
UnitTest框架:
1.定义 : 是Python自带的一个单元测试框架,可以直接使用,不需要单外安装。
不仅仅可以用来做单元测试,测试人员也经常用来做自动化测试。
- 用途: 能够组织多个用例去执行,提供丰富的断言方法,最终生成测试报告
1. UnitTest框架的组件
TestCase 测试用例
用来书写真正的用例代码(脚本)
步骤:
- 导包 unittest
- 定义测试类,只要集成unittest.TestCase类,就是测试类
- 书写测试方法,方法中的代码就是用例代码,方法名必须以test开头
- 运行:在类名或者方法名后边右键运行; 调用unittest.main()来运行
代码如下:
python
# 导包 unittest
import unittest
#定义测试类,只要集成unittest.TestCase类,就是测试类
class TestDemo(unittest.TestCase):
#书写测试方法,方法中的代码就是用例代码,方法名必须以test开头
def test_01(self):
print("测试方法1")
def test_02(self):
print("测试方法2")
#运行:在类名或者方法名后边右键运行; 调用unittest.main()来运行
if __name__ == "__main__":
unittest.main()
注意事项 :
- 代码文件名,要满足标识符的规则,不要使用中文
运行结果:


TestSuite 测试套件
用来组装(打包)TestCase(测试用例)的,即多条测试用例集合在一起就是一个测试套件
使用步骤:
- 实例化测试套件: unittest.TestSuite()
- 添加用例方法
- 实例化 执行对象: unittest.TextTestRunner()
- 执行对象执行: run()
先将TestCase.py文件复制一份,粘贴后修改文件名为TestCase_02.py
修改的内容如下,为了区分第一个用例:

新建测试套件类并运行:

代码如下:
python
import unittest
from TestCase import TestDemo
from TestCase_02 import TestDemo02
#实例化测试套件: unittest.TestSuite()
suite = unittest.TestSuite()
#添加用例方法
suite.addTest(TestDemo('test_01'))
suite.addTest(TestDemo('test_02'))
suite.addTest(TestDemo02('test_01'))
suite.addTest(TestDemo02('test_02'))
#实例化 执行对象并执行: unittest.TextTestRunner().run()
unittest.TextTestRunner().run(suite)
运行结果:

添加扩展:把指定ClassName类中的测试用例全部添加到测试套件中
复制TestSuite_TestRunner.py文件,命名为TestSuite_TestRunner_02.py
代码修改:

python
#把指定ClassName类中的测试用例全部添加到测试套件中
suite.addTest(unittest.makeSuite(TestDemo))
suite.addTest(unittest.makeSuite(TestDemo02))
运行结果和挨个添加测试用例方法一样的:

TestLoader 测试加载
用来加载TestCase到TestSuite中,即夹杂满足条件的测试用例,并把测试用例封装成测试套件
使用unittest.TestLoader,通过该类下面的discover()方法自动搜索执行目录下指定开头的.py文件,并将查找到的测试用例组装到测试套件中
用法 :
suite = inittest.TestLoader().discover(test_dir,pattern = 'test*.py')
最终返回的还是测试套件对象,运行测试套件还需要使用TestRunner
使用步骤:
- 实例化加载对象并加载用例 ,返回的是套件对象
- 实例化执行对象并执行
新建文件TestLoader_TestRunner.py文件
代码如下:
python
import unittest
#实例化加载对象并加载用例 ,返回的是套件对象
#unittest.TestLoader().discover('用例所在的目录','用例代码文件名*.py')
# .:代表当前目录下
suite = unittest.TestLoader().discover('.','TestCase*.py')
# 实例化执行对象并执行
unittest.TextTestRunner().run(suite)

TestRunner 测试执行
用来执行用例和测试套件
使用步骤:
- 导包
- 实例化: unittest.TextTestRunner
- 执行
Fixture 测试夹具
是一种代码结构,书写 前置方法(执行用例之前的方法)和 后置方法(执行用例之后的方法)代码,即用例执行顺序 前置 → 用例 → 后置
分类:
- 方法级别 Fixture :在每个用例执行前后都会自动调用
python
def setUp(self): #方法前置
pass
def tearDown(self): #方法后置
pass
- 类级别 Fixture : 在类中所有的测试方法前后 会自动执行的代码,只执行一次
python
@classmethod
def setUpClass(cls): #类前置
pass
def tearDownClass(cls): #类后置
pass
- 模块级别 Fixture
模块就是代码文件,在这个代码文件执行前后执行一次(在类外部定义函数)
python
@classmethod
def setUpModule(): #模块前置
pass
@classmethod
def tearDownModule(): #模块后置
pass
2. TestLoader与TestSuite区别
TestSuite (测试套件) :
灵活,方便控制要执行的测试用例,需要手动挑选、组装用例,可以自由控制执行顺序。
estLoader(测试加载器):自动去找、读取、加载用例,生成 Suite,自动发现用例,不用手动一个个 add。
3. 断言与参数化
断言:
让程序代替人为判断测试程序执行结果是否符合预期结果的过程
常用的UnitTest断言方法 :
参数化 :通过参数的方式来传递数据,从而实现数据和脚本分离。并且可以实现用例的重复执行。
unittest测试框架,本身不支持参数化,但是可以通过安装unittest扩展插件parameterized来实现.
安装parameterized: pip install parameterized

查看已安装插件列表:pip list

使用:
- 导包 from parameterized import parameterized
- 修改测试方法,将测试方法张的测试数据使用变量表示
- 组织测试数据,格式: () , () , () , ...,一个元组就是一组数据。
- 参数化:在测试方法上方是哟个装饰器@parameterized.expand(测试数据)
- 运行
元组参数化:
新建参数化添加功能文件,代码如下:
python
import unittest
from parameterized import parameterized
data = [(1,1,2),(1,2,3),(2,3,5),(4,5,9)]
class tools_add (unittest.TestCase):
@parameterized.expand(data)
def test_add(self,a,b,expect):
print(f'a:{a},b:{b},expect:{expect}')
self.assertEqual(expect, a+b)
if __name__ == '__main__':
unittest.main()
运行结果:

json参数化
- json数组参数化:
创建一个json数组格式的数据文件:add_data.json
python
[
[1,1,2],
[1,2,3],
[2,3,5],
[4,5,9],
[10,10,20]
]
将json文件中的数组格式转换为unittest参数化元组格式:
新建read_data.py文件:
代码如下:
python
import json
def build_add_data():
with open('add_data.json') as f:
data = json.load(f)
return data
调整之前的测试参数化添加功能文件,代码如下:
python
import unittest
from parameterized import parameterized
from read_data import build_add_data
class tools_add (unittest.TestCase):
@parameterized.expand(build_add_data())
def test_add(self,a,b,expect):
print(f'a:{a},b:{b},expect:{expect}')
self.assertEqual(expect, a+b)
if __name__ == '__main__':
unittest.main()
运行输出结果:

- json字典参数化
创建一个json数组格式的数据文件:add_data_02.json
python
[
{
"a": 1,
"b": 2,
"expect": 3
},
{
"a": 10,
"b": 20,
"expect": 30
},
{
"a": 2,
"b": 3,
"expect": 5
},
{
"a": 20,
"b": 30,
"expect": 50
}
]
在read_data.py文件中新增方法build_add_data_02(),代码如下:
python
def build_add_data_02():
base_path = os.path.dirname(__file__)
json_full_path = os.path.join(base_path, "add_data_02.json")
with open(json_full_path, "r", encoding="utf-8") as f:
data_list = json.load(f)
new_list = []
for data in data_list:
new_list.append(tuple(data.values()))
return new_list
将test_tools_add_parameterized.py文件中的test_add()参数化方法调整一下,

运行后的结果如下:

4. 测试报告和跳过
HTML测试报告:就是执行完测试用例后,使用第三方的报告模板(HTMLTestReport),以HTML(网页)方式将执行结果生成报告。本质是TestRunner
安装:
pip install HTMLTestReport


使用:
- 导包 unittest,HTMLTestReport
- 组装用例(套件,loader)
- 使用HTMLTestReport 中的runner执行套件
- 查看报告
新建文件 TestReporter.py,执行参数化tools_add接口,生成测试报告
内容如下:
python
import unittest
from htmltestreport import HTMLTestReport
# 这里注意一下:我的用例是写在case文件夹下的,所以加载的路径是:`../case`
suite = unittest.TestLoader().discover('../case', 'test_tools_add_paramete*.py')
runner = HTMLTestReport('test_add_report.html','参数化tools_add接口测试报告','json参数化+parameterized测试')
runner.run(suite)
执行结果:

报告文件及查看:


跳过:对于一些未完成的或者不满足测试条件的测试函数和测试类,可以跳过执行。
使用方式:
- 直接将测试函数标记跳过:@unittest.skip('代码未完成')
- 根据条件判断测试函数是否跳过:@unittest.skipif(condition,reason)
创建跳过用例文件:test_skip.py
python
import unittest
a = 11
class TestSkip(unittest.TestCase):
@unittest.skip('跳过,代码未完成')
def test_skip_01(self):
print(f'测试跳过01')
@unittest.skipIf('a >=10 ','a大于10,跳过不执行')
def test_skip_02(self):
print(f'测试跳过02')
def test_skip_03(self):
print(f'测试跳过03')
if __name__ == '__main__':
unittest.main()
执行结果:

组装到suite里执行:
代码如下:
python
import unittest
from case.test_skip import TestSkip
suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(TestSkip) )
unittest.TextTestRunner().run(suite)
执行结果:

