1、测试框架的价值
1、实现对所有测试脚本、测试数据文件以及测试报告文件的管理,提升接口测试执行和回归的效率。
2、降低人工的工作成本,可以在下班之后通过框架来自动运行,提高单位人工的产能。
3、框架可以应对多种不同的接口测试工作的需求,适用性和可扩展性强。
4、对接口测试成果物进行规范化管理,方便随时进行工作的开展以及成果物的查阅
2、测试框架设计思路
2.1 框架设计目标
最终只需要调整框架配置文件的一些参数,不需要人工干预测试脚本的执行
2.2 框架设计过程
1、明确框架层次确定下来
a、配置层: config 框架的配置文件 主要是CSV文件
b、脚本层:script 分为独立接口脚本ind_interface和联调接口脚本mul_interface
c、数据层:testdatafile 分为独立接口ind_interface,数据联调接口数据mul_interface
d、报告层:testresultfile 分为框架测试报告fram_result ,此次框架执行过程中,运行了哪些接口测试脚本
独立接口测试报告: ind_interface
联调接口测试报告:mul_interface
2、对框架的设计进行评审
3、创建框架对应的文件夹
名称最好都是英文的,拼音的
4、把现有相关的成果物归类
把现有相关的成果物归类,包括脚本成果物,测试数据文件,测试报告文件,框架配置文件等放入对应的文件夹中,把命名尽量有一个统一的规范。
5、框架的设计
6、框架的实现
7、框架的调试运行
3、框架试验
首先下载HTMLTestRunner.py
HTMLTestRunner - tungwaiyip's software
放在框架的文件夹下
3.1 V1.0版本,传入一组固定的测试数据,进行接口测试
需求: 通过unittest框架实现注册接口的测试
1、导入unittest类库
import unittest
2、定义测试类,必须继承unittest.TestCase
class测试类名(unittest.TestCase):
class test_updateuser(unittest.TestCase):
3、测试方法的名字必须以test_打头
def test_case1(self):
4、在main函数中直接使用unittest.main()即可
if __name__ == '__main__':
unittest.main()
5、加入测试断言
脚本中要进行预期结果和实际结果的对比
assert断言函数,
self.assertIn("更新个人信息成功",response)
self.assertIn("更新个人信息成功",response)
6、通过使用setup进行测试的初始化工作
def setUp(self):
url="http://localhost:8080/jwshoplogin/user/login.do"
userinfo={"username":"张海",
"password":"123456"}
response=requests.post(url,data=userinfo)
self.sessionID=dict(response.cookies)['JSESSIONID']
print(self.sessionID)
7、通过使用teardown进行测试的回收工作
def tearDown(self):
pass
整体代码:
# 对更新用户信息的脚本进行测试,使用unittest框架技术,V1.0版本,传入一组固定的测试数据,进行接口测试
# 接口说明:
# 接口访问地址: http://localhost:8080/jwshoplogin/user/update_information.do
# 接口传入参数:1、email: 2、phone:3、answer: 4、question:
# 接口预期返回结果:
# 1、email已存在, 请更换email再尝试更新 2、更新个人信息成功 3、更新个人信息失败"
#*****************************************************************************
# 脚本实现:
# 导入相关类库
import unittest
import requests
# 定义测试类,继承unittest框架
class test_updateuser(unittest.TestCase):
# 通过setup方法实现登录接口的调用
def setUp(self):
url="http://localhost:8080/jwshoplogin/user/login.do"
userinfo={"username":"程勇4",
"password":"123456"}
response=requests.post(url,data=userinfo)
self.sessionID=dict(response.cookies)['JSESSIONID']
print(self.sessionID)
# V1.0版本,传入一组固定的测试数据,进行接口测试
def test_case1(self):
# 传入指定的接口测试数据
url="http://localhost:8080/jwshoplogin/user/update_information.do"
userinfo={"email":"1234561@qq.com",
"phone":"13311095555",
"question": "苹果",
"answer":"最喜欢的水果"
}
session={"JSESSIONID":self.sessionID}
# 进行接口调用
response=requests.post(url,data=userinfo,cookies=session).text
print(response)
self.assertIn("更新个人信息成功",response)
def tearDown(self):
pass
if __name__ == '__main__':
unittest.main()
输出结果:
51A4D6A5E348145E7C45FCF7B24C8977
{"status":0,"msg":"更新个人信息成功","data":{"id":33,"username":"程勇4","password":null,"email":"1234561@qq.com","phone":"13311095555","question":"苹果","answer":"最喜欢的水果","role":null,"createTime":null,"updateTime":null}}
Ran 1 test in 0.018s
OK
Process finished with exit code 0
3.2 V2.0 通过csv文件进行更新测试数据的读取
在这里读取testdatafile下面的test_updateuser_V21.csv文件
第0列是网址
第1列是userinfo里面有几个参数,
第2列是断言情况
第3列是参数名
第4列是参数值
第5列是参数名
第6列是参数值
通过unittest框架实现更新测试数据的读取,
1、导入unittest类库,导入csv库函数
# 导入相关类库
import os
import unittest
import requests
import csv
2、通过setup方法实现登录接口的调用
读取testdatafile下面的test_updateuser_V21.csv文件,只读第一行,
def setUp(self):
# # 从csv测试数据文件中读取url和登录测试数据
path=os.getcwd()
print(path)
# p1=os.path.abspath(os.path.dirname(path)+os.path.sep+".")
# print(p1)
p2 = os.path.abspath(os.path.dirname(path) + os.path.sep + "..")
self.fpath=p2+"\\testdatafile\\ind_interface\\test_updateuser_V21.csv"
# print(fpath)
userinfo={}
file1=open(self.fpath,'r')
逐行读取测试的数据
并取出 JSESSIONID
table=csv.reader(file1)
for row in table:
print(row[0])
url=row[0]
userinfo[row[3]]=row[4]
userinfo[row[5]]=row[6]
print(userinfo)
break # 读完一行就退出
response=requests.post(url,data=userinfo)
self.sessionID=dict(response.cookies)['JSESSIONID']
print(self.sessionID)
3、读取第二行以后的数据,并根据j读取参数填入到userinfo中。
if num>1:
url=row[0]
expresult=row[2]
j=int(row[1])
for i in range(3,j*2+3,2):
userinfo[row[i]]=row[i+1]
整体代码:
# V2.0 通过csv文件进行更新测试数据的读取
# 接口说明:
# 接口访问地址: http://localhost:8080/jwshoplogin/user/update_information.do
# 接口传入参数:1、email: 2、phone:3、answer: 4、question:
# 接口预期返回结果:
# 1、email已存在, 请更换email再尝试更新 2、更新个人信息成功 3、更新个人信息失败"
#*****************************************************************************
# 脚本实现:
# 导入相关类库
import os
import unittest
import requests
import csv
# 定义测试类,继承unittest框架
class test_updateuser_V2(unittest.TestCase):
# 通过setup方法实现登录接口的调用
def setUp(self):
# # 从csv测试数据文件中读取url和登录测试数据
path=os.getcwd()
print(path)
# p1=os.path.abspath(os.path.dirname(path)+os.path.sep+".")
# print(p1)
p2 = os.path.abspath(os.path.dirname(path) + os.path.sep + "..")
self.fpath=p2+"\\testdatafile\\ind_interface\\test_updateuser_V21.csv"
# print(fpath)
userinfo={}
file1=open(self.fpath,'r')
table=csv.reader(file1)
for row in table:
print(row[0])
url=row[0]
userinfo[row[3]]=row[4]
userinfo[row[5]]=row[6]
print(userinfo)
break # 读完一行就退出
response=requests.post(url,data=userinfo)
self.sessionID=dict(response.cookies)['JSESSIONID']
print(self.sessionID)
# V2.0版本,读取指定的测试数据文件中对应的内容,进行接口测试
def test_case1(self):
# 打开对应的文件
file1=open(self.fpath,'r')
# 如何从指定行开始读取
table=csv.reader(file1)
userinfo={}
num=0
for row in table:
num=num+1
if num>1:
url=row[0]
expresult=row[2]
j=int(row[1])
for i in range(3,j*2+3,2):
userinfo[row[i]]=row[i+1]
print(userinfo)
session={"JSESSIONID":self.sessionID}
print(session)
response=requests.post(url,data=userinfo,cookies=session).text
print(response)
userinfo={}
self.assertIn("更新个人信息成功",response)
if __name__ == '__main__':
unittest.main()
返回结果:
D:\python\interfacefram\script\ind_interface
http://localhost:8080/jwshoplogin/user/login.do
{'username': '张海1', 'password': '123456'}
6F9569002161C3B7388ED9E0000CDE58
{'email': '1234564@qq.com'}
{'JSESSIONID': '6F9569002161C3B7388ED9E0000CDE58'}
{"status":0,"msg":"更新个人信息成功","data":{"id":26,"username":"张海1","password":null,"email":"1234564@qq.com","phone":null,"question":null,"answer":null,"role":null,"createTime":null,"updateTime":null}}
{'phone': '13311095551'}
{'JSESSIONID': '6F9569002161C3B7388ED9E0000CDE58'}
3.3 v3.0 创建HTML格式的测试报告文件
使用测试套件执行
1、导入unittest框架文件,及测试报告库
import os
import unittest
import requests
import csv
from HTMLTestRunner import HTMLTestRunner
2、定义测试报告文件
path=os.getcwd()
p2 = os.path.abspath(os.path.dirname(path) + os.path.sep + "..")
filename=p2+"\\testresultfile\\ind_interface\\test_updatauser_report.html"
3、加载测试套
suite=unittest.TestSuite()
suite.addTest(test_updateuser_V3("test_case1"))
4、 以wb的方式打开文件
file=open(filename,"wb")
5、调用HTML测试报告的报告生成测试报告
runner=HTMLTestRunner(stream=file,title="更新用户接口测试",description="接口测试报告")
print("测试报告")
runner.run(suite)
file.close()
程序:
# v3.0 创建HTML格式的测试报告文件
# 接口说明:
# 接口访问地址: http://localhost:8080/jwshoplogin/user/update_information.do
# 接口传入参数:1、email: 2、phone:3、answer: 4、question:
# 接口预期返回结果:
# 1、email已存在, 请更换email再尝试更新 2、更新个人信息成功 3、更新个人信息失败"
#*****************************************************************************
# 脚本实现:
# 导入相关类库
import os
import unittest
import requests
import csv
from HTMLTestRunner import HTMLTestRunner
# 定义测试类,继承unittest框架
class test_updateuser_V3(unittest.TestCase):
# 通过setup方法实现登录接口的调用
def setUp(self):
# # 从csv测试数据文件中读取url和登录测试数据
path=os.getcwd()
# print(path)
# p1=os.path.abspath(os.path.dirname(path)+os.path.sep+".")
# print(p1)
p2 = os.path.abspath(os.path.dirname(path) + os.path.sep + "..")
print(p2)
self.fpath=p2+"\\testdatafile\\ind_interface\\test_updateuser_V21.csv"
# print(fpath)
userinfo={}
file1=open(self.fpath,'r')
table=csv.reader(file1)
for row in table:
print(row[0])
url=row[0]
userinfo[row[3]]=row[4]
userinfo[row[5]]=row[6]
print(userinfo)
break
response=requests.post(url,data=userinfo)
self.sessionID=dict(response.cookies)['JSESSIONID']
print(self.sessionID)
def test_case1(self):
# 打开对应的文件
file1=open(self.fpath,'r')
# 如何从指定行开始读取
table=csv.reader(file1)
userinfo={}
num=0
for row in table:
num=num+1
if num>1:
url=row[0]
expresult=row[2]
j=int(row[1])
for i in range(3,j*2+3,2):
userinfo[row[i]]=row[i+1]
print(userinfo)
session={"JSESSIONID":self.sessionID}
print(session)
response=requests.post(url,data=userinfo,cookies=session).text
print(response)
userinfo={}
self.assertIn("更新个人信息成功",response)
if __name__ == '__main__':
# unittest.main()
# 定义测试报告文件
path=os.getcwd()
p2 = os.path.abspath(os.path.dirname(path) + os.path.sep + "..")
filename=p2+"\\testresultfile\\ind_interface\\test_updatauser_report.html"
# 加载测试套
suite=unittest.TestSuite()
suite.addTest(test_updateuser_V3("test_case1"))
# 以wb的方式打开文件
file=open(filename,"wb")
# 调用HTML测试报告的报告生成测试报告
runner=HTMLTestRunner(stream=file,title="更新用户接口测试",description="接口测试报告")
print("测试报告")
runner.run(suite)
file.close()
此时右键运行,输出结果如下:
D:\python\interfacefram
http://localhost:8080/jwshoplogin/user/login.do
{'username': '张海1', 'password': '123456'}
95A706B0546303971C2D3158D347B4A5
D:\Program Files\python\lib\unittest\case.py:546: ResourceWarning: unclosed file <_io.TextIOWrapper name='D:\\python\\interfacefram\\testdatafile\\ind_interface\\test_updateuser_V21.csv' mode='r' encoding='cp936'>
self.setUp()
ResourceWarning: Enable tracemalloc to get the object allocation traceback
{'email': '1234564@qq.com'}
{'JSESSIONID': '95A706B0546303971C2D3158D347B4A5'}
{"status":0,"msg":"更新个人信息成功","data":{"id":26,"username":"张海1","password":null,"email":"1234564@qq.com","phone":null,"question":null,"answer":null,"role":null,"createTime":null,"updateTime":null}}
{'phone': '13311095551'}
{'JSESSIONID': '95A706B0546303971C2D3158D347B4A5'}
Ran 1 test in 0.031s
OK
{"status":0,"msg":"更新个人信息成功","data":{"id":26,"username":"张海1","password":null,"email":null,"phone":"13311095551","question":null,"answer":null,"role":null,"createTime":null,"updateTime":null}}
Process finished with exit code 0
发现问题1:此时testresultfile\ind_interface\test_updatauser_report.html没有生成
解决办法,这时右键运行是在测试套里跑的,没有生成测试报告,单独跑就会生成
注意:运行模式要改为以python文件而不是测试框架运行
点开上方"Edit Configurations"
选择python,点击加号+
选择python
在Unnamed中选择这个脚本,点击ok
此时选择刚添加的那个配置,执行,此时就会生成测试报告
可以看到测试报告:
3.4 V4.0 测试文件执行
以文件的方式来进行框架的执行 声明文件所在路径
testdir='./'
discover=unittest.defaultTestLoader.discover(testdir,pattern='test_updateser_v1.py')
#声明测试运行对象
runner=unittest.TextTestRunner()
runner.run(discover)
整体程序:
# v4.0 执行任意指定路径下的任意相关命名的python测试脚本
# 脚本实现:
import unittest
import requests
if __name__ == '__main__':
#**********************************************
#以文件的方式来进行框架的执行
#声明文件所在路径
testdir='./'
discover=unittest.defaultTestLoader.discover(testdir,pattern='test_updateser_v1.py')
#声明测试运行对象
runner=unittest.TextTestRunner()
runner.run(discover)
执行结果:
{"status":0,"msg":"更新个人信息成功","data":{"id":33,"username":"程勇4","password":null,"email":"1234561@qq.com","phone":"13311095555","question":"苹果","answer":"最喜欢的水果","role":null,"createTime":null,"updateTime":null}}
.
----------------------------------------------------------------------
Ran 1 test in 0.019s
OK
4、三种不同的框架小结
4.1、unittest框架的使用要求
1、import unittest
2、定义测试类需要继承unittest
class 测试类名(unittest.TestCase)
4.2、 unittest测试框架的基本组成要素
1、setUp初始化方法
测试前期的初始化工作,作为可选项
2、test_XXX测试方法
测试方法必须以test_开头
3、tearDown资源回收方法
可选、关闭对象、释放对象
4、运行方式
unittest.main()、测试套件执行、测试文件执行
4.3 unittest框架的执行顺序
setUp进行初始化
执行测试方法
tearDown进行资源回收
4.4 三种不同的框架进行运行的对比
4.4.1 unittest.main()
1、依次执行当前文件中对应测试类的所有测试方法
2、执行顺序以asc码顺序
是按照asc码顺序进行执行
setUp 测试方法test_case1 tearDown
setUp 测试方法test_case2 tearDown
3、一般测试方法名称建议定义为
test_case1、test_case2
4.4.2 测试套件执行
1、声明测试套
suite=unittest.TestSuite()
2、通过addtest方法添加测试用例
suite.addTest(类名("测试方法名"))
3、声明测试运行对象
runner=unittest.TestRunner()
4、执行测试套
runner.run(suite)
执行特点:按照加载顺序的顺序和个数进行执行
注意:运行模式要改为以python文件而不是测试框架运行
4.4.3 测试文件执行
1、声明文件所在路径
2、定义discover对象打开相关的脚本文件
discover=unittest.defaultTestLoader.discover(文件路径,pattern='test3.py')
3、声明测试运行对象
runner=unittest.TextTestRunner()
4、执行测试套
runner.run(discover)
特点:执行任意指定路径下的任意相关命名的python测试脚本;执行每一个文件中所有的测试方法,顺序也是按照asc码顺序进行
愿每个测试都能顺利转为测试开发,提高职业技能,成为前1%的存在,为公司节约更多的成本,为社会创造更大的价值,为自己和家庭谋求更高的收入,所有人不受职业年龄限制,越老越吃香,直至财富自由;愿测试技术越来越进步,测试效率提高,软件质量不断提高。愿祖国更加美好,人民更加幸福。多喜乐,常安宁。