1、层级结构
2、/datas/files/test_case.xlsx sheet:student
3、/common/readcases.py
import openpyxl class ReadCase(object): def __init__(self, filename): self.filename = filename # 加载excel self.wb = openpyxl.load_workbook(self.filename) def read_sheetname(self, sheetname): # 获取工作表 sheet = self.wb[sheetname] # 将生成器转换为列表 sheetdatas = list(sheet.values) # 获取第一行标题作为key keys = sheetdatas[0] # 从第二行开始获取value values = sheetdatas[1:] # 定义一个空的列表 case_list = [] # 遍历获取到的用例参数值 for value in values: case_list.append(zip(keys, value)) return case_list if __name__ == '__main__': ReadCase("../datas/files/test_case.xlsx").read_sheetname("student") #可在当前页面执行验证4、/config/config.py
import os.path class Config(object): project_path = os.path.split(os.path.split(__file__)[0])[0] # __file__获取当前文件的绝对路径 if __name__ == '__main__': print(os.path.split(os.path.split(__file__)[0])[0]) print(os.path.join(Config.project_path, "datas/files/test_case.xlsx"))5、/case/test_student.py
import pytest import requests, allure from PytestApiExcel.config.config import Config from PytestApiExcel.common.readcases import ReadCase class TestStudent(object): # 调用文件读取的方法,获取excel文件中,sheet页名为login的文件用例数据 case_data = ReadCase(Config.project_path + "/datas/files/test_case.xlsx").read_sheetname("student") # 减少登录次数 def setup_class(self): self.r = requests.session() login_r = self.r.request("POST", url="http://localhost/login", data={"username": "test", "password": "123456"}) assert login_r.json().get("msg") == "login-pass" # 通过数据参数化的方式,用“case”进行接收 @pytest.mark.parametrize("case", case_data) def test_student(self, case): allure.dynamic.epic(case.get("板块")) # 动态获取一级目录 allure.dynamic.feature(case.get("模块")) # 动态获取二级目录 allure.dynamic.story(case.get("客户管理")) # 动态获取三级目录 allure.dynamic.title(f'{case.get("用例编号")}_{case.get("用例标题")}') # 动态获取标题 if case.get("是否执行") != "是": pytest.skip("用例跳过执行!") search_r = self.r.request(case.get("请求方法"), case.get("请求地址"), **eval(case.get("请求参数"))) # 请求参数是字典套字典形式,利用eval进行解包——》数据形式(data={},{},{}) # 美化alluer报告获取详细的请求响应日志 allure.attach(str(search_r.request.url), "请求地址", attachment_type=allure.attachment_type.TEXT) allure.attach(str(search_r.request.method), "请求方法", attachment_type=allure.attachment_type.TEXT) allure.attach(str(search_r.request.headers), "请求header", attachment_type=allure.attachment_type.TEXT) allure.attach(str(search_r.request.body), "请求body", attachment_type=allure.attachment_type.TEXT) allure.attach(str(search_r.status_code), "响应状态码", attachment_type=allure.attachment_type.TEXT) allure.attach(str(search_r.headers), "响应header", attachment_type=allure.attachment_type.TEXT) allure.attach(str(search_r.text), "响应body", attachment_type=allure.attachment_type.TEXT) # 从case中获取响应的body,用冒号分割,最大分割一次 # 分割的两部分分别赋值给how、what how, what = case.get("预期响应body").split(":", maxsplit=1) # 判断是否为json if how == "json": # 如果是,就将what的数据通过eval转化为字典形式 expect = eval(what) # 将字典形式的数据进行遍历,取出对应的key、value for key, value in expect.items(): # 根据响应结果中的key获取value,断言响应的value与预期的value值是否相等 assert search_r.json().get(key) == value elif how == "contains": assert what in search_r.text elif how == "json_len": expect = eval(what) for key, value in expect.items(): if key == "gt": assert len(search_r.json()) > int(value) elif key == "eql": assert len(search_r.json()) == int(value) else: raise TypeError(f"你传入的json长度判断方法[{key}]不支持!") else: raise TypeError(f"你填写的断言方法[{how}不支持!]")6、runner
import pytest import subprocess allure_result=r"D:\Study\pythonProject\PytestApiExcel\report\allure_result" #存放结果数据的 allure_html=r"D:\Study\pythonProject\PytestApiExcel\report\allure_html"#存放html报告的 pytest.main(["-k case","-v","-s",f"--alluredir={allure_result}","--clean-alluredir"]) #2.调用命令生成报告 subprocess.run(f"allure generate {allure_result} -o {allure_html} --clean",shell=True,universal_newlines=True) #阻塞式的,等待报告生成