一,单元测试
首先要先理解什么是单元测试,测试按照阶段来分,一般就是单元测试,集成测试,系统测试,验收测试
单元测试的定义:对的单个模块,类,或者函数进行测试。将访问接口的过程封装在函数里面,接口测试就变成了单元测试。单元测试是通过传参,对某个模块,某个类,某个函数进行结果输出后验证的测试。
意义:
做单元测试,可以从底层发现问题,降低修复bug的成本。
二,unittest组成
unittest框架主要包括四大类。
1,TestCase 类, (测试用例), 一个TestCase的实例就是一个测试用例,包括,测试前的环境准备(setUp),实现测试过程的代码,以及测试完成后的测试环境的还原,单元测试的本质也在这里,一个测试用例就是一个完整的测试单元
2,Testsuite,测试集,用来收集测试用例的,其中最常用的是TestLoader,有一个discover方法,是用来把TestCase加载到Testsuite中的
3,Test runner, 用来执行测试用例的
4,Test fixture,对一个测试用例环境的搭建和销毁,通过setUp(), 和tearDown实现。
举例:测试用例中需要访问数据库,那么可以在setUp() 中建立数据库连接以及进行一些初始化,在tearDown()中清除在数据库中产生的数据,然后关闭连接。注意tearDown的过程很重要,要为以后的 TestCase留下一个干净的环境。关于fixture,还有一个专门的库函数叫做fixtures,功能更加强大。
三;详细介绍
1,TestCase
测试用例类,必须继承unittest.TestCase
2,TestLoader()
TestLoader是将测试用例收集到Testsuite中,是一个类,所以用的时候,记得实例化类,要加上()。
TestLoader().discover,方法,是最常用的收集用例的方法,
用法如下:
TestLoader().discover(搜索路径),用例的搜索原则是:目录 -- 文件 -- (文件命名是test_*.py的命名方式命名的,都是测试用例)
# 收集全部用例
s = TestLoader().discover(cases_dir) # 其中cases_dir 为测试用例的路径
# 收集指定模块测试用例
from TestCases import test_register # 因为需要单独调试注册模块
s = TestLoader().loadTestsFromModule(test_register) # 这个方法是从指定的模块中收集用例,一般都是单独调试某个模块时使用
# 收集指定的测试用例,基本不用
# from TestCases import test_login
# s = TestLoader().loadTestsFromTestCase(test_login.TestLogin)
# # 以上是单独调试指定测试用例的时候的收集测试用例的方法,精确到每个测试用例,因为用了ddt,所以才会全部读取出来
3,Text runner
主要是执行测试用例 + 生成测试报告,但是自带的太垃圾了。所以引用第三方的库,都需要用pip安装下载
HtmlTestRunner 先实例化,在运行用例,生成html报告
eg:
import unittest
from HTMLTestRunnerNew import HTMLTestRunner
s = unittest.TestLoader().discover(r"D:\Pychram-Workspace\py30")
# 运行测试用例并生成html的结果
# 创建一个html文件,以写的模式打开,因为是html文件,所以是二进制 wb
with open("report.html", "wb") as fs:
# 运行测试用例,将结果写html当中
runner = HTMLTestRunner(fs, title="py30期单元测试报告", tester="小简") # 实例化HTMLTestRunner对象,传参看源码
runner.run(s) # 调用run方法,运行测试用例,生成测试报告
BeautifulReport 先实例化,在运行用例,生成html报告(必须先导入BeautifulReport)
eg:
import unittest
import os
from BeautifulReport import BeautifulReport
from Common.handle_path import cases_dir, reports_dir, debug_dir
# 收集全部用例
s = unittest.TestLoader().discover(debug_dir)
# 生成报告
br = BeautifulReport(s) # 实例化一个BeautifulReport对象,如果不知道要传什么参数,自己去看源码
br.report("py30-注册用例自动化", "report_.html", reports_dir) # 调用br对象的report方法,参数看源码
测试用例的执行顺序,是按照ASCII码顺序,从小到大执行的
0~9< A~Z<a~z
所以想要内部调整测试用例的执行顺序的时候,在给用例命名的时候可以如下 操作:
test_01_register
test_02_login
4,Test fixture
说简单点就是做各种前置和后置工作。实际上在框架中,还可以把前置后置放在excel中。
测试用例级别:
1:测试用例级别:
setup(前置), teardown(后置),类下面的每一个用例在执行之前会执行setup,在每一个用例执行之后,会执行teardown
def setUp(self):
print("===== 单个用例开始执行 ======")
def tearDown(self):
print("===== 单个用例结束执行 ======")
2:测试类级别,注意:测试类级别的函数都要用@classmethod 装饰
setupClass(类级别的前置), teardownClass(类级别的后置),类里面的第一个用例执行之前,执行setupClass,类里面的最后一个用例执行之后,执行teardownClass。
eg:
@ddt
class TestAdd(unittest.TestCase):
@classmethod
def setUpClass(cls) -> None:
logger.info("++++创建项目接口开始测试++++") # 类级别的前置
clear_Envata_attrs()
def tearDownClass(cls) -> None:
logger.info("----创建项目接口结束测试----") # 类级别的后置
@data(*cases)
def test_add(self, case):
case = replace_case_by_regular(case)
if hasattr(EnvData, "token"):
response = send_requests(case["method"], case["url"], case["request_data"], token=EnvData.token)
else:
response = send_requests(case["method"], case["url"], case["request_data"])
if case["extract_data"]:
extract_data_from_response(case["extract_data"], response.json())
四,DDT介绍
ddt,data driver test,数据驱动测试,还有说法,叫做参数化,记得。
适用场景:
一个测试流程,N组测试用例,流程不变,只是测试数据和断言的数据不一样
模块名就叫ddt,需要和测试框架配合使用
引入ddt,(ddt本身不支持用例名称介绍,在ddt的基础上,修改了源码,增加了展示测试用例名称的功能,命名为myddt,需要的可私聊)
from Common.myddt import ddt, data # 先把myddt文件放在框架的Common目录下
在测试类名上面使用: @ddt
在测试函数上面使用: @data(*列表) ,这里的列表是从excel中读取出来的以列表形式存储的测试数据。* 是拆包的用法
在测试函数的参数中,定义一个参数用来接收每一组的测试数据
eg:
cases = he.read_all_datas()
he.close_file()
db = HandleDb()
@ddt
class TestRegistr(unittest.TestCase):
@classmethod
def setUpClass(cls) -> None: # 前置
pass
@classmethod
def tearDownClass(cls) -> None: # 后置
pass
@data(*cases)
def test_register(self, case): # case就是用来接收@data中的*case(解包出来的数据)的。
pass
五:总结
1:定义测试类,必须继承unittest.TestCase,在测试类中,以test_开头,定义测试函数,每一个以test_开头的函数就是一个测试用例。
2:编写测试用例:
2.1:准备测试数据(前置,后置,excel等)
2.2: 测试步骤
2.3:断言:预期结果与实际结果的对比 AssertionError :断言失败,用例不通过(是unittest框架识别用例失败的唯一标识,所以做异常捕获的时候,不要忘记用raise抛出异常!!)
assert 表达式 (返回结果为True,用例通过, False 用例不通过)pytest框架常用
在unittest框架中,比较常用的self.assertXXX()
常见的有如下:(无需记住,会用即可)
2.4 前置后置工作要提前想好
自动化用例: 1:前置后置, 2:用例步骤, 3:断言