pytest+requests+allure自动化测试接入Jenkins学习

发布时间:2026/6/13 2:22:26

pytest+requests+allure自动化测试接入Jenkins学习 点击文末小卡片免费获取软件测试全套资料资料在手涨薪更快最近在这整理知识发现在pytest的知识文档缺少系统性这里整理一下方便后续回忆。在python中大家比较熟悉的两个框架是unittest和pytestUnittest是Python标准库中自带的单元测试框架Unittest有时候也被称为PyUnit就像JUnit是Java语言的标准单元测试框架一样Unittest则是Python语言的标准单元测试框架。Pytest是Python的另一个第三方单元测试库。它的目的是让单元测试变得更容易并且也能扩展到支持应用层面复杂的功能测试。两者之间的区别如下这里试用的pytest框架加上request来实现接口自动化的测试整个框架考虑到使用数据驱动的方式将数据维护在Excel文档中。1、下载安装allure下载地址https://github.com/allure-framework/allure2/releaseshttps://repo.maven.apache.org/maven2/io/qameta/allure/allure-commandline/选择需要的版本下载这里我下载的是2.13.2版本下载好后解压到你需要存放的路目录并配置环境变量检查是否配置成功执行cmd输入命令 allure出现如下图则表示安装成功2、下载安装python下载地址https://www.python.org/下载好后安装并配置环境变量具体流程可以网络查找3、python安装依赖包cmd命令执行也可以通过项目中的requirements.txt来安装安装步骤后面再说pip3 install allure-pytest pip3 install pytest pip3 install pytest_html pip3 install request4、下载并安装pycharm工具查看网络教程5、在pycharm新建项目及编码项目目录如图base存放一些最底层的方法封装协议请求发送等。common存放一些公共方法。config存放配置文件。testData存放测试数据。log存放日志。report存放报告。testCase存放用例。utils存放公共类。readme用于说明文档。requirements.txt用于记录所有依赖包极其版本号便于环境部署可以通过pip命令自动生成和安装这里采用数据驱动的方式数据通过读取excel文件来执行测试所以这里需要封装读取excel的方法使用xlrd来操作读取# operationExcel.py import json from common.contentsManage import filePath import xlrd, xlwt class OperationExcel: # 获取shell表 def getSheet(self, index0): book xlrd.open_workbook(filePath()) return book.sheet_by_index(index) #根据索引获取到sheet表 # 以列表形式读取出所有数据 def getExcelData(self, index0): data [] sheet self.getSheet(indexindex) title sheet.row_values(0) # (0)获取第一行也就是表头 for row in range(1, sheet.nrows): # 从第二行开始获取 row_value sheet.row_values(row) data.append(dict(zip(title, row_value))) # 将读取出第一条用例作为一个字典存放近列表 return data # 对excel表头进行全局变量定义 class ExcelVarles: case_Id 用例ID case_module用例模块 case_name用例名称 case_server用例地址 case_url请求地址 case_method请求方法 case_type请求类型 case_data请求参数 case_headers请求头 case_preposition前置条件 case_isRun 是否执行 case_code 状态码 case_result 期望结果 if __name__ __main__: opExcel OperationExcel() # opExcel.getSheet() # print(opExcel.getExcelData()) opExcel.writeExcelData(1, 7, ftest{2})excel 文件内容如图封装用例# test_api_all.py # 参数化运用所有用例 import json import pytest from utils.operationExcel import OperationExcel, ExcelVarles from base.method import ApiRequest from common.log import logger opExcel OperationExcel() apiRequest ApiRequest() pytest.mark.parametrize(data, opExcel.getExcelData()) # 装饰器进行封装用例 def test_api(data, login_tokenNone): if data[ExcelVarles.case_isRun] N : logger.info(跳过执行用例) return # 请求头作为空处理并添加token headers data[ExcelVarles.case_headers] if len(str(headers).split()) 0: pass elif len(str(headers).split()) 0: headers json.loads(headers) # 转换为字典 # headers[Authorization] login_token # 获取登录返回的token并添加到读取出来的headers里面 headers headers # 对请求参数做为空处理 params data[ExcelVarles.case_data] if len(str(params).split()) 0: pass elif len(str(params).split()) 0: params params url data[ExcelVarles.case_server] data[ExcelVarles.case_url] ? params r apiRequest.all_method( data[ExcelVarles.case_method] ,url, headersheaders) logger.info(f响应结果{r}) responseResult json.loads(r) case_result_assert(data[ExcelVarles.case_code], responseResult[code]) # 断言封装 def case_result_assert(expectedResult, actualReuls) : 断言封装 :param expectedResult: 预期结果 :param actualReuls: 实际结果 :return: assert expectedResult actualReuls # 状态码封装日志文件# log.py #!/usr/bin/python # -*- coding: utf-8 -*- import logging import time import os from common.contentsManage import logDir # BASE_PATH os.path.dirname(os.path.dirname(os.path.realpath(__file__))) # # 定义日志文件路径 # LOG_PATH os.path.join(BASE_PATH, log) # if not os.path.exists(LOG_PATH): # os.mkdir(LOG_PATH) # 方法1 # 封装自己的logging class MyLogger: def __init__(self): self._logName os.path.join(logDir(), {}.log.format(time.strftime(%Y%m%d))) self._logger logging.getLogger(logger) self._logger.setLevel(logging.DEBUG) self._formatter logging.Formatter([%(asctime)s][%(filename)s %(lineno)d][%(levelname)s]:%(message)s) self._streamHandler logging.StreamHandler() self._fileHandler logging.FileHandler(self._logName, modea, encodingutf-8) self._streamHandler.setFormatter(self._formatter) self._fileHandler.setFormatter(self._formatter) self._logger.addHandler(self._streamHandler) self._logger.addHandler(self._fileHandler) # 获取logger日志记录器 def get_logger(self): return self._logger logger MyLogger().get_logger()封装请求方法# method.py import json import requests from common.log import logger from utils.commonUtils import isJson class ApiRequest(object): # ---- 第一种请求方式封装requests库调用可根据实际情况传参 ---- # def send_requests(self, method, url, dataNone, paramsNone, headersNone, # cookiesNone,jsonNone,filesNone,authNone,timeoutNone, # proxiesNone,verifyNone,certNone): # self.res requestes.request(methodmethod, url url, headersheaders,datadata, # paramsparams, cookiescookies,json json,filesfiles, # authauth, timeout timeout, proxiesproxies,verifyverify, # certcert) # return self.res # 第二种封装方法 def get(self, url, dataNone, headersNone, payloadNone): if headers is not None: res requests.get(urlurl, datadata,headersheaders) else: res requests.get(urlurl, datadata) return res def post(self, url, data, headers, payload:dict, filesNone): if headers is not None: res requests.post(urlurl, datadata, headersheaders) else : res requests.post(urlurl, datadata) if str(res) Response [200] : return res.json() else : return res.text def put(self,url,data,headers, payload:dict, filesNone): if headers is not None : res requests.put(urlurl,datadata,headersheaders) else: res requests.put(urlurl,datadata) return res def delete(self,url,data,headers, payload:dict): if headers is not None : res requests.delete(urlurl,datadata,headersheaders) else: res requests.delete(urlurl,datadata) return res def all_method(self, method, url, dataNone, headersNone, payloadNone, filesNone): logger.info(f请求方法是{method}, 请求地址{url}) if headers None: headers {} if method.upper()GET: res self.get(url,data,headers, payload) elif method.upper()POST: res self.post(url, data, headers, payload, files) elif method.upper() PUT: res self.put(url, data, headers, payload, files) elif method.upper() DELETE: res self.delete(url, data, headers, payload) else : res f请求{method}方式不支持或者不正确 return json.dumps(res, ensure_asciiFalse, indent4, sort_keysTrue, separators(,,:))运行# run.py import shutil import pytest import os from common.log import logger import subprocess # 通过标准库中的subprocess包来fork一个子进程,并运行一个外部的程序 from common.contentsManage import htmlDir, resultDir if __name__ __main__: htmlPath htmlDir() resultPath resultDir() if os.path.exists(resultPath) and os.path.isdir(resultPath): logger.info(清理上一次执行的结果) shutil.rmtree(resultPath, True) logger.info(开始测试) pytest.main([-s, -v, --alluredir, resultPath]) #运行输出并在resport/result目录下生成json文件 logger.info(结束测试) # 如果是代码单独执行需要立马看到报告可以执行下面语句如果配合Jenkins使用则可以不需要执行Jenkins自带的插件allure会操作 # logger.info(生成报告) # subprocess.call(allure generate resultPath -o htmlPath --clean, shellTrue) # 读取json文件并生成html报告,--clean诺目录存在则先清楚 # logger.info(查看报告) # subprocess.call(allure open -h 127.0.0.1 -p 9999 htmlPath, shellTrue) #生成一个本地的服务并自动打开html报告依赖包安装可以执行命令 pip3 install -r requirements.txt来安装# requirements.txt pytest7.4.3 pytest-html4.1.1 pytest-xdist3.5.0 pytest-ordering0.6 pytest-rerunfailures13.0 allure-pytest2.13.2 xlrd1.2.0 requests2.31.0至此项目的代码框架就基本结束了6、安装并配置JenkinsJenkins的安装看你需要在Windows还是Linux下安装具体教程可以网络查找Jenkins安装allure插件Jenkins安装并登录后可以创建任务添加构建步骤根据你安装环境的不同选择不同的构建添加构建后操作选择 allure Report配置代码执行的结果地址运行测试后可以在任务中查看allure生成的报告至此jenkinspythonpytestrequestsallure的接口自动化测试就记录到这里刚兴趣的可以去看看pytest的官方文档了解更多知识。最后感谢每一个认真阅读我文章的人礼尚往来总是要有的虽然不是什么很值钱的东西如果你用得到的话可以直接拿走这些资料对于做【软件测试】的朋友来说应该是最全面最完整的备战仓库这个仓库也陪伴我走过了最艰难的路程希望也能帮助到你凡事要趁早特别是技术行业一定要提升技术功底。

相关新闻