问题描述:
搭建接口测试框架, 执行用例请求多个不同请求方式的接口
实现步骤:
1 创建配置文件 config.INI, 写入部分公用参数, 如接口的基本 url, 测试报告文件路径, 测试数据文件路径等配置项
- [DATABASE]
- data_address = ./data/data.xlsx
- report_address = ./report/
- driver = ./drivers/chromedriver.exe
- [HTTP]
- base_url = https://***.***.cn//
2 从配置文件中读取并返回文件中内容, 或写入配置文件的方法, 文件命名 readConfig.py
- import os
- import configparser
- # 获取当前 py 文件地址
- proDir = os.path.split(os.path.realpath(__file__))[0]
- # 组合 config 文件地址
- configPath = os.path.join(proDir,"config.ini")
- class ReadConfig:
- def __init__(self):
- # 获取当前路径下的配置文件
- self.cf = configparser.ConfigParser()
- self.cf.read(configPath)
- def get_config(self,field,key):
- # 获取配置文件中的 key 值
- result = self.cf.get(field,key)
- return result
- def set_config(self,field,key,value):
- # 向配置文件中写入配置信息
- fb = open(configPath,'w')
- self.cf.set(field,key,value)
- self.cf.write(fb)
3 从配置文件中获取到接口的基本 url 后, 根据不同的接口请求方式读取请求体或其他参数信息, 参数信息从 Excel 中读取, 因此文件 readExcel.py 用于读取并返回 Excel 文件中内容, 或写入 Excel 的方法
- import xlrd
- import xlutils.copy
- from Base.readConfig import ReadConfig
- import time
- class ReadExcel:
- def __init__(self,section,field,sheet):
- # 打开工作表, 并定位到 sheet
- data_address = ReadConfig().get_config(section,field)
- workbook = xlrd.open_workbook(data_address)
- self.table = workbook.sheets()[sheet]
- def get_rows(self):
- # 获取 Excel 行数
- rows = self.table.nrows
- return rows
- def get_cell(self,row,col):
- # 获取单元格数据
- cell_data = self.table.cell(row,col).value
- return cell_data
- def get_col(self,col):
- # 获取整列数据
- col_data = self.table.col_value(col)
- return col_data
- class WriteExcel:
- def __init__(self,section,field,sheet):
- # 打开工作表
- self.address = ReadConfig().get_config(section,field)
- self.workbook = xlrd.open_workbook(self.address)
- self.wf = xlutils.copy.copy(self.workbook)
- self.ws = self.wf.get_sheet(sheet)
- def set_cell(self,row,col,value):
- #设置单元格数据
- self.ws.write(row,col,value)
- def save_excel(self,filename,format):
- #获取当前时间
- self.time = time.strftime("%Y%m%d%H%M%S", time.localtime())
- #生成文件的文件名及格式
- self.report = filename + '_' +self.time + format
- #保存文件
- self.wf.save(self.report)
4 将获取接口的 url, 请求头, 参数等方法封装成类并写入 base.py 中, 用于测试框架中测试集的直接调取
- from Base.readConfig import ReadConfig
- from Base.readExcel import ReadExcel
- # 实例化
- readexcel = ReadExcel('DATABASE','data_address',0)
- class BasePage(object):
- def __init__(self, selenium_driver):
- self.driver = selenium_driver
- def get_api(self, row, col):
- # 获取 url
- self.base_url = ReadConfig().get_config('HTTP', 'base_url')
- # 获取 Excel 中的接口地址, 与 url 进行拼接
- self.url = self.base_url + readexcel.get_cell(row, col)
- print(self.url)
- return self.url
- def get_cell(self, row, col):
- # 获取 Excel 单元格数据, 获取接口请求的参数
- self.cell = readexcel.get_cell(row, col)
- return self.cell
5 从 base.py 文件获取到请求地址后, 需要组合不同类型的请求方式, 如 get 请求直接将参数与地址进行拼接, 或 post 请求以 JSON 数据格式等为请求体请求接口, 然后再获取接口对象, 得到接口返回的数据, 此过程涉及的方法封装到 request_way.py(注: 该实例 get 请求返回数据格式为 JSONP, 因此需要 JSONP 格式数据转换为 JSON 格式的方法)
- from Base.readExcel import ReadExcel
- from base import BasePage
- import requests
- import urllib.parse
- import JSON
- import re
- # 实例化
- readexcel = ReadExcel('DATABASE','data_address',0)
- # JSONP 格式数据转换为 JSON 格式
- def jsonp_to_json(_jsonp):
- # 解析 JSONP 数据格式为 JSON
- try:
- return JSON.loads(re.match(".*?({.*}).*", _jsonp, re.S).group(1))
- except:
- raise ValueError('Invalid Input')
- class RequestPage(BasePage):
- # post 方式请求, JSON 格式为请求体
- def post_requests(self, url, i):
- # 定义请求数据, 获取 Excel 中参数信息赋值给 data, 以 JSON 格式拼接好数据
- data_1_json = JSON.dumps(BasePage(self.driver).get_cell(i, 4))
- data_2_json = JSON.dumps(BasePage(self.driver).get_cell(i + 1, 4))
- data = "{" + data_1_json + ":" + data_2_json + "}"
- print(data)
- # 打开请求, 获取对象
- response = requests.post(url, data)
- # 打印状态码
- print(response)
- return response
- # get 方式请求
- def get_request(self, url, j):
- # 定义请求数据, 获取 Excel 中参数信息赋值给 values
- #values = {}
- values = BasePage(self.driver).get_cell(j, 4)
- # 如果参数不止一个则对请求数据进行编码拼接'&'
- #data = urllib.parse.urlencode(values)
- # 将数据与 url 进行拼接
- req = url + '?' + values
- print(req)
- # 打开请求, 获取对象
- response = urllib.request.urlopen(req)
- # 打印 Http 状态码
- print(response.status)
- # 读取服务器返回的数据, 对 HTTPResponse 类型数据进行读取操作, bytes 格式数据编译成中文编码
- the_page = response.read().decode("unicode_escape")
- # 将返回的 bytes 格式数据先转换成 str, 再将返回的 JSONP 格式数据转换成 JSON 格式
- the_page = jsonp_to_json(str(the_page))
- return the_page
6 得到接口实际返回结果后, 需要与预期结果做比对, 判断用例执行结果, 所以封装校验类到 check.py 文件. 校验方式其一是校验 JSON 数组内每个数值是否一致, 其二是直接简单校验数组中的 status 值和 message 是否返回正确
- from base import BasePage
- from Base.readExcel import WriteExcel
- # 实例化
- writeexcel = WriteExcel('DATABASE','data_address',0)
- class CheckPage(BasePage):
- # 校验 JSON 数组内每个值是否一致
- def check_value(self, i, actualresult, expectresult):
- # 遍历字典的值 value, 并将 value 赋值给实际接口数据的值
- for value in actualresult.values():
- actualresult_value = value
- # 遍历字典的值 value, 并将 value 赋值给 Excel 中预期数据的值
- for value in expectresult.values():
- expectresult_value = value
- # 如果实际接口返回的每个键值与 Excel 中预期返回的数据的每个键值一样, 则接口测试用例执行通过, 如果不是则打印预期结果和实际结果, 可比较差异
- if actualresult_value == expectresult_value:
- writeexcel.set_cell(i, 8, 'SUCCESS')
- print("接口用例执行结果通过")
- else:
- writeexcel.set_cell(i, 8, 'FAILURE')
- writeexcel.set_cell(i, 7, str(actualresult))
- print('第', i + 1, '行用例执行失败: 预期结果是', expectresult, '实际结果是', actualresult)
- # 保存测试报告
- writeexcel.save_excel('testreport', '.xls')
- # 校验 JSON 数组中的 status 值和 message 是否返回成功
- def easy_check_value(self, i, actualresult,expectresult):
- # 判断实际接口值是否状态码和消息返回成功
- if actualresult['status'] == 1 and actualresult['message'] == '完成':
- writeexcel.set_cell(i, 8, 'SUCCESS')
- print('第', i+1, '行用例执行结果正确, 用例通过')
- else:
- writeexcel.set_cell(i, 8, 'FAILURE')
- writeexcel.set_cell(i, 7, str(actualresult))
- print('第', i + 1, '行用例执行失败: 预期结果是', expectresult, '实际结果是', actualresult)
- # 保存测试报告
- writeexcel.save_excel('testreport', '.xls')
7 最后编写测试集 testcase.py, 其中用例包含有执行 post 和 get 方式的请求, 增加用例可直接在该文件继续添加编写
- import unittest
- from selenium import webdriver
- from Base.readConfig import ReadConfig
- from base import BasePage
- from requests_way import RequestPage
- from check import CheckPage
- from packages.htmlTestRunner import HTMLTestRunner
- driver = webdriver.Chrome(ReadConfig().get_config('DATABASE', 'driver'))
- class SmokeTest(unittest.TestCase):
- #初始化
- def setUp(self):
- self.driver = driver
- def test_case_10(self):
- """以 json 格式数据为请求体的 post 方式接口请求"""
- # 获取 url
- self.url = BasePage(self.driver).get_api(1,1)
- # 将接口实际返回数据转换为 JSON 可序列化, 使用 JSON.dumps() 时需要对象相应的类型是 JSON 可序列化的
- i = 3
- actualresult = RequestPage(self.driver).post_requests(self.url, i).JSON()
- # 获取 Excel 中的预期结果
- expectresult = eval(BasePage(self.driver).get_cell(i, 6))
- # 校验实际接口返回结果和用例预期结果是否一致 (校验 JSON 数组内每个值是否一致)
- CheckPage(self.driver).check_value(i, actualresult, expectresult)
- def test_case_11(self):
- """get 方式接口请求"""
- # 获取 url
- self.url = BasePage(self.driver).get_api(8, 1)
- # 获取接口实际返回值与 Excel 中的预期结果
- j = 8
- actualresult = RequestPage(self.driver).get_request(self.url, j)
- expectresult = eval(BasePage(self.driver).get_cell(j, 6))
- # 校验实际接口返回结果和用例预期结果是否一致 (校验 JSON 数组中的 status 值和 message 是否返回成功)
- CheckPage(self.driver).easy_check_value(j, actualresult, expectresult)
- # 释放资源
- def test_case_12(self):
- self.driver.quit()
- if __name__ == '__main__':
- #构造测试集合
- suite = unittest.TestSuite()
- suite.addTest(SmokeTest('test_case_10'))
- suite.addTest(SmokeTest('test_case_11'))
- suite.addTest(SmokeTest('test_case_12'))
- #创建 HTML 文件
- filename = ReadConfig().get_config('DATABASE', 'report_address') + 'testreport.html'
- fp = open(filename, 'wb')
- #执行测试并生成 HTML 测试报告
- runner = HTMLTestRunner(stream=fp, description='接口用例执行情况:', title='接口自动化测试报告')
- runner.run(suite)
- #关闭文件
- fp.close()
8 其中涉及 HTMLTestRunner.py 原生 HTML 测试报告库, 是用于生成测试报告 testreport.HTML, 模块下载后直接集成到该项目
模块下载地址:
9 以 python 文件模式执行脚本才能生成测试报告
参考: https://www.cnblogs.com/kristin/p/10332815.html
以上, 整体框架如下图
执行方式正确得到以下两种类型测试报告, Excel 表和 HTML 测试报告
来源: https://www.cnblogs.com/kristin/p/10387970.html