unittest框架
1.单元测试的定义
1.1.什么是单元测试?
单元测试是指,对软件中的最小可测试单元在与程序其他部分相隔离的情况下进行检查和验证的工作,这里的最小可测试单元通常是指函数或者类,一般是开发来做的,按照测试阶段来分,就是单元测试、集成测试、系统测试以及验收测试。
1.2.为什么要做单元测试?
- ?? 单元测试之后,才是集成测试,单个单个的功能模块测试通过之后,才能把单个功能模块集成起来做集成测试,为了从底层发现bug,单元测试时可以减少合成后出现的问题。
- ?? 越早发现bug越好,这样可以早点发现问题,不然问题累计到后面,很可能会因为一个做错了而导致整个模块甚至更大范围的推倒重来,对于时间和经费来说,是非常浪费的!
- ?? 对于测试来说,单元测试就是为了执行用例,输入测试数据--》输出测试结果
2.unittest框架及原理
断言就是判断预期和实际是否一致,一致即用例通过
? 做过自动化测试的同学应该都知道python中的unittest框架,它是python自带的一套测试框架,学习起来也相对较容易,unittest框架最核心的四个概念:
?? test case:就是我们的测试用例,unittest中提供了一个基本类TestCase,可以用来创建新的测试用例,一个TestCase的实例就是一个测试用例;unittest中测试用例方法都是以test开头的,且执行顺序会按照方法名的ASCII值排序。
? ?? test fixure:测试夹具,用于测试用例环境的搭建和销毁。即用例测试前准备环境的搭建(SetUp前置条件),测试后环境的还原(TearDown后置条件),比如测试前需要登录获取token等就是测试用例需要的环境,运行完后执行下一个用例前需要还原环境,以免影响下一条用例的测试结果。
? ?? test suite:测试套件,用来把需要一起执行的测试用例集中放到一块执行,相当于一个篮子。我们可以使用TestLoader来加载测试用例到测试套件中。
? ?? test runner:用来执行测试用例的,并返回测试用例的执行结果。它还可以用图形或者文本接口,把返回的测试结果更形象的展现出来,如:HTMLTestRunner。
3.unittest的断言
? 在python基础中,我们有讲过一个assert断言,使用方法比较简单,即assert 表达式, 提示信息
,而unittest框架中也提供了一个自带的断言方式,主要有以下几种:
如果断言失败即不通过就会抛出一个AssertionError
断言错误,成功则标识为通过,以上几种方式都有一个共同点,就是都有一个msg参数(表中只列了一个,其实都有),默认是None,即msg = None
,如果指定msg参数的值,则将该信息作为失败的错误信息返回。
4.TestCase测试用例
编写测试用例前,我们需要建一个测试类继承unittest里面的TestCase类,继承这个类之后我们才是真正的使用unittest框架去写测试用例,编写测试用例的步骤如下:
- 导入unittest模块
- 创建一个测试类,并继承
unittest.TestCase()
- 定义测试方法,方法名必须以test_开头
- 可以调用
unittest.main()
方法来运行测试用例,unittest.main()方法会搜索该模块下所有以test开头的测试用例方法,并自动执行
import unittest
# 写的函数
def my_sum(a, b):
a += 1
b += 2
return a + b
# 编写的测试用例类
class TestSum(unittest.TestCase):
def test_001(self):
number = my_sum(3, 4) # 调用my_sum函数 重写数据
self.assertEqual(number, 10) # 断言,预期和实际是否一致,一致即用例通过
def test_002(self):
number = my_sum(-3, 4) # 调用my_sum函数 重写数据
self.assertIn(number, [1, 2, 3, 4]) # 断言,判断实际结果在不在[1, 2, 3, 4]列表的范围内
def test_003(self):
number = my_sum(-1, -4)
self.assertEqual(number, -2)
def test_004(self):
number = my_sum(0, -4)
self.assertEqual(number, -1)
5.TestFixure测试夹具
unittest的测试夹具有两种使用方式,一种是以测试方法为维度的setUp()
和tearDown()
,一种是以测试类为维度的setUpClass()
和tearDownClass()
。
class TestRegister(unittest.TestCase):
"""注册接口测试用例类"""
def setUp(self):
# 每条用例执行之前都会执行
print("用例{}开始执行--".format(self))
def tearDown(self):
# 每条用例执行之后都会执行
print("用例{}执行结束--".format(self))
@classmethod # 指明这是个类方法以类为维度去执行的
def setUpClass(cls):
# 整个测试用例类中的用例执行之前,会先执行此方法
print("-----setup---class-----")
@classmethod
def tearDownClass(cls):
# 整个测试用例类中的用例执行完之后,会执行此方法
print("-----teardown---class-----")
6.TestSuite测试套件
unittest.TestSuite()类来表示一个测试用例集,把需要执行的用例类或模块存到一起,常用的方法如下:
-
?? unittest.TestSuite()
-
addTest()
:添加单个测试用例方法 -
addTest([..])
:添加多个测试用例方法,方法名存在一个列表
-
- ?? unittest.TestLoader()
loadTestsFromTestCase(测试类名)
:添加一个测试类loadTestsFromModule(模块名)
:添加一个模块discover(测试用例的所在目录)
:指定目录去加载,会自动寻找这个目录下所有符合命名规则的测试用例
# run_test.py,与test_register.py、register.py同一目录下
import unittest
import test_register
# 第一步,创建一个测试套件
suite = unittest.TestSuite()
# 第二步:将测试用例,加载到测试套件中
# 方式1,添加单条测试用例
# case = test_register.TestRegister("test_register_success") # 创建一个用例对象,注意:通过用例类去创建测试用例对象的时候,需要传入用例的方法名(字符串类型)
# suite.addTest(case) # 添加用例到测试套件中
# 方式2,添加多条测试用例
# case1 = test_register.TestRegister("test_register_success")
# case2 = test_register.TestRegister("test_username_isnull")
# suite.addTest([case1, case2]) # 添加用例到测试套件中
# 方式3,添加一个测试用例类
# loader = unittest.TestLoader() # 创建一个加载对象
# suite.addTest(loader.loadTestsFromTestCase(test_register.TestRegister))
# 方式4,添加一个模块
loader = unittest.TestLoader() # 创建一个加载对象
suite.addTest(loader.loadTestsFromModule(test_register))
# 方式5,指定测试用例的所在的目录路径,进行加载
# loader = unittest.TestLoader()
# suite.addTest(loader.discover(r"d:\learn\python"))
通常我们使用方式4、5比较多,你可以根据实际情况来运用。其中方式5,还可以自定义匹配规则,默认是会寻找目录下test*.py
文件,即所有以test开头命名的py文件,自定义如下:
loader = unittest.TestLoader() suite.addTest(loader.discover(start_dir = r"d:\learn\python", pattern="test_case*.py")) # 匹配规则:所有以test_case开头的
7.TestRunner执行用例
test runner顾名思义就是用来执行测试用例的,并且可以生成相应的测试报告。测试报告有两种展示形式,一种是text文本,一种是html格式。
? html格式的就是HTMLTestRunner了,HTMLTestRunner
是 Python 标准库的 unittest 框架的一个扩展,它可以生成一个直观清晰的 HTML 测试报告。使用的前提就是要下载 HTMLTestRunner.py,下载完后放在python的安装目录下的scripts目录下即可。
? text文本相对于html来说过于简陋,与控制台输出的没有什么区别,也几乎没有人使用,这里不作演示,使用方法是一样的。我们结合前面的测试套件来演示一下如何生成html格式的测试报告:
# run_test.py,与test_register.py、register.py同一目录下
import unittest
import test_register
from HTMLTestRunner import HTMLTestRunner
# 创建测试套件
suite = unittest.TestSuite()
# 通过模块加载测试用例
loader = unittest.TestLoader()
suite.addTest(loader.loadTestsFromModule(test_register))
# 创建测试运行程序启动器
runner = HTMLTestRunner(stream=open("report.html", "wb"), # 打开一个报告文件,将句柄传给stream
tester="miki", # 报告中显示的测试人员
description="注册接口测试报告", # 报告中显示的描述信息
title="自动化测试报告") # 报告的标题
# 使用启动器去执行测试套件里的用例
runner.run(suite)
运行完毕,你会发现你的项目目录下已经生成了一个report.html文件,在浏览器中打开,就可以查看测试报告了。