# pytestapi-frame **Repository Path**: wang-zhong-wang/pytestapi-frame ## Basic Information - **Project Name**: pytestapi-frame - **Description**: 2024个人原创 -最新版 python+pytest+allure接口自动化测试框架 - **Primary Language**: Python - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 40 - **Forks**: 4 - **Created**: 2024-01-31 - **Last Updated**: 2025-06-09 ## Categories & Tags **Categories**: Uncategorized **Tags**: Python, pytest, Allure, request ## README ### 一、APITestFrame - 1. 介绍 主要使用python语言编写的基于pytest+request+yaml+allure实现的接口自动化测试框架,按照指定格式 只需编写yaml文件,结合配置文件的读取可实现0代码的接口自动化测试,支持DDT数据驱动、接口关联,jsonpath、正则表达式、数据库断言方式,自动生成测试报告联动邮箱发送等功能。 - 2. 环境准备 建议使用python3.8及以上版本解释器 ### ### 二、本框架大致功能: - 1、基于 pytest 框架安装插件即可使用,环境非常简单 - 2、只需要写 yaml 文件或Excel用例即可运行,使用 pytest 运行的命令 - 3、extract 功能实现多个接口步骤的参数关联 - 4、全局仅登录一次,在用例中自动在请求头部添加 Authentication token认证 - 5、用例参数化 parameters 功能实现 - 6、yaml 中调用 fixture 功能实现 - 7、yaml 中调用辅助函数功能使用 - 8、支持邮箱配置 - 9、用例分层机制:API和用例层 - 10、支持 logging 日志 - 11、支持 allure 报告 - 12、支持 mysql 数据库增删改查 - 13、支持钉钉机器人通知测试结果和 allure 报告地址 - 14、接口参数关联支持 键值对、$ 等方式提取变量 - 15、支持生成随机测试数据,如字符串,姓名,手机号,邮箱等 - 16、yaml 中调用 动态参数、自定义函数(faker0.py、datetime_util.py) 待扩展: - 17、yaml 中调用 热加载、hooks 功能 ### 三、目录结构 ``` |--pytestapi_frame # 主目录 ├─case └─conftest.py #pytest配置文件 请求前置后置处理 └─test_BusinessFlow.py #业务流接口驱动脚本 └─test_FileUpload.py #文件上传接口驱动脚本 └─test_single.py #单接口驱动脚本 ├─ common # 封装断言以及requests请求、数据统一格式处理、邮箱发送等方法 ├─ conf # 配置文件 └─ conf.ini #邮箱、数据库、执行环境等配置信息 ├─ datas #测试用例数据 └─xxx_project #测试项目名称 (名称同conf.ini执行环境配置中 execute=xxx 一致) └─BusinessFlow #业务流接口存放目录 └─FileUpload #文件上传接口存放目录 └─single #单接口存放目录 └─extract.yaml#接口关联数据存放文件 └─login_token.yaml # 用户登录用例文件-提取认证信息 ├─ logs # 日志文件 ├─ report # allure离线测试报告、钉钉、linux在线报告等文件 ├─ pytest.ini # pytest配置 ├─ requirements.txt ├─ README.md └─ run.py # 整体执行程序。 ``` ### 四、框架操作介绍 注:此框架只需要修改配置信息(conf.in、pytest.ini)+编写测试用例(data目录>>业务流程接口、单接口、文件上传接口),无须编写逻辑驱动代码,即可执行简单的接口自动化测试; #### 1、配置文件介绍 ``` [Email] #发送人 邮箱的配置信息 ,我用的是qq邮箱 send_User = 1923425117@qq.com send_Password = zzmrvlncqyifj send_Smtp = smtp.qq.com [addreSsee] #发送邮箱的地址,可填写多个 495654801@qq.com = 王忠的邮箱 495651231@qq.com = 张三的邮箱 [send_email] # 是否发送报告 y, Y,yes send_or_not = y [mysql] #数据库连接配置 host = 192.167.6.181 port = 3306 user = root passwd = Test123456 dbname = dah-park-cds [Excel_yaml] # 0代表执行Excel和yaml两种格式的用例(暂未实现,意义不大),1代表Excel用例,2代表yaml文件用例 case = 2 [environment]#环境配置 tf_project需要和存放测试用例数据的目录名称 保持一致 sys_name = 天府生命科技园(测试环境) execute = tf_project tf_project = http://192.167.6.185:8090 [linux] #测试报告放在服务器中,永久保存测试数据,访问地址则发送至钉钉群 host = 192.167.6.185 user = root passwd = zip_file_path = [send_dingding] #url_webhook是机器人的url地址(必填),如机器人 不选择加签模式 的话 secret可以不填 url_webhook = https://oapi.dingtalk.com/robot/send?access_token=64d0f36d9be5c4ab7c210f56ac5f495cc22760e2d7b6 secret = SEC5103f3f646fc7b2010207ff5883da2c2c4eeef437a14b17c446607 ``` #### 2、接口参数提取、关联介绍 (extract.yaml文件每次运行完后不清理关联数据_方便失败查看关联数据排错,运行时遇到相同的key会替换 ) ##### a、接口响应参数提取 通过 _response_extraction_ 字段来判断是否需要关联 如果不需要 _response_extraction_ 字段为空即可,方法如下: 响应参数提取(采用 _jsonpath_ 语法,提取接口响应),提取后的参数通过 **自定义变量(key):提取的值(value)** 字典形式写入到 extract.yaml 文件中 ``` response_extraction: #提取变量 - rex: ["$..['rows'][0][id]","yqid"] #考虑全局不止一个id需要提取数据做关联,到时候不知道取哪一个,所以存入字典的时候进行自定义(yqid)变量命名 - rex: ["$..['rows'][0][id]","yq"] ``` ##### b、接口请求body关联/此方式不兼容嵌套数据(暂不使用)统一用下方的${变量名} 同理,通过 _relation_ 字段来判断是否需要关联 如果不需要 _relation_ 字段为空即可(适用单层数据,请求body不是嵌套字典)——已弃用,统一使用下面的 ${变量名} 方式提取变量 ``` relation: unitId: "yqid" #提取参数一定要和存入的变量一致,入参的键(unitId) 参考接口文档写入实际参数 ``` 另外一种场景,请求body数据是嵌套字典,如需关联数据上面方法则不适用,编写格式如下: 采用${变量名}提取数据 (同样适用单层数据,改进版适合全部), ``` json: drillsSummary: "2" emergencyDrillsFiles: [{"filePath": "${temp_path}" , "name": "1.jpg", "fileName": "1.jpg", "fileType": ".jpg" }]# ``` #### 3、用例编写介绍 ---->> [pycharm快捷方式创建用例模版](https://www.cnblogs.com/zcjbky/p/18331985) ##### a、登录文件如下 ``` login: #需要登录就写此节点数据 - execute: yes #不需要登录或者用临时token就写no 需要就写yes title: 用户成功登录—> 提取token request: url: http://192.167.6.185:8090/dah-park-api/login/aso/password method: POST #登录请求体的格式是 data applicaiton/x-www-from-urlencoded json: username: admin-gov password: 123456.. extract_data: - rex: [ "$.access_token","Authorization" ] expected: #jsonpath提取器进行断言 - eq: [ $.expires_in,604800 ] Temporary token: #可在网页登陆后 复制token进行临时使用 Authorization存入的key会在后续请求头使用 - Authorization: "Bearer d3a15bc4-f9bb-485a-bdae-7b0b82449450" Password encryption:#是否需要 密码加密处理 需要则去掉注释,填写对应函数和入参(如不是rsa加密方式则需要自己根据实际业务的加密规则编写函数),会通过类反射的方式代入 - type: #rsa_encrypt values: [ MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQClc1O4MC6YKREh2lmCxf4aEmJRWEVbyhTa5KrBHcDFgkZTxEvGt7Lu9lyXlaaJqSMHHlE02eVLTRmwJkK4DJsxAvQCeLuYkhzfcmH+ai9pc/90n7wQCV9IHDTWU9TK1vF7IAMosbLNo7rATHaZGNCVeWn+REkZQDEs3MJC2L270wIDAQAB,111111a ] ``` ##### b、业务流类型 ![输入图片说明](images/case_ex.png) ``` business process: #选项节点名称、业务流 读取次节点数据 - system: 项目系统名称 describe: 业务流程描述 查看xxx》新建xxx》检查xxx》 title: 查看一企一档 request: url: /dah-park-api/unit-document/page #其他请求方法说明:大写POST是用data传参,form-data表单格式(有些登陆接口是此类型) 请求参数类型为data; #小写post是用json传参,application/json;文件上传接口直接写method:file; (request请求做了统一封装 逻辑判断处理) method: GET json: #接口入参 GET请求也可以写在url后面,json下面置空就行 pageNum: 1 pageSize: 20 name: "${random_name}这是我的名字" #($自动引用faker0函数下的方法并替换{}值) headers: #请求头信息 Accept: application/json, text/plain, */* Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9 Authorization: "Bearer ${token}" #或者下面这种写法 Authorization: "${Authorization}" #根据存入的key进行提取,这样比以前更兼容 因为有的项目请求头认证的key是access-token response_extraction: #提取响应变量 (下文中会介绍具体用法) - rex: ["$..['rows'][0][id]","yqid"] - rex: ["$..['rows'][0][id]","yq"] relation: #不需要关联则下面置空 # unitId: "yqid" expected: #业务关键字断言 - eq: [$.code,200] - eq: [$.message,"请求成功"] #jsonpath提取断言方式 - contain: ["监督"] #文本包含断言 - db: ["SELECT * FROM system_book WHERE `name`='python数据构造'",1] #数据库断言 查询到的数据,存在1条 ``` ##### c、单接口用例,简单示例 ``` one: #用来区分单接口的 用例节点 - id: 1 describe: 一企一档模块 request: url: /dah-park-api/unit-document/page method: GET headers: Accept: application/json, text/plain, */* Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9 Authorization: "${Authorization}" relation: #没有关联数据则不写 参数不可删除 response_extraction: #参数化写下面 #------------------------------------------------------------------------------------------------------------------ parametrize: - title: 错误的入参 json: #body pageNum12: 1 pageSize: 20 expected: #期望值 - eq: [$.code,xxxx] - title: 错误的数据 json: pageNum: gfgf pageSize: 20 expected: - eq: [$.code,xxxx] ``` #### 4、执行用例 执行用例需要配置两处地方如下, ##### a、pytest.ini中的执行文件 ``` ;模块名的规则,配置测试搜索的模块文件名称 python_files = test_F*.py F代表的是业务流接口(test*.py 则执行全部用例) ``` ##### b、conf.ini中的执行系统目录 ``` [environment]#环境配置 tf_project需要和存放测试用例数据的目录名称 保持一致 sys_name = 天府生命科技园(测试环境) execute = tf_project tf_project = http://192.167.6.185:8090 prod_env = http://111.8.55.74:1562/internet ``` 最后运行run.py文件 #### 5、执行结果Allure 报告展示 ![输入图片说明](images/allure.png) ![输入图片说明](images/report1.png) ### 五、yaml语法简介 xx峰讲解地址:http://www.ruanyifeng.com/blog/2016/07/yaml.html ``` yaml文件编写规范: 1. 语法规则: 大小写敏感 使用缩进表示层级关系,缩进空格不重要,只要相同层级的元素左侧对齐即可(可用Tab缩进,但建议尽量用空格缩进) #号表示注释 2. yaml支持的数据结构 对象:键值对的组合,又称 映射(mapping)/ 哈希(hashes)/ 字典(dictionary) 数组:一组按次序排列的值,又称 序列(sequence)、列表(list) 纯量:单个的,不可分割的值 3. yaml数据结构用法 对象:对象的一组键值,用冒号表示(注意:编写时,最好冒号前后各一个空格) animal : dog # 类似于python中的字典{“animal”:”dog“} 数组:一组连词线构成的行,组成一组数组 -animal -vegetables -meet -people 类似于python中的列表["animal","vegetables","meet","people"] ``` ### 六、Docker实现Jenkins+Python + Pytest +Allure 接口自动化(大致环境流程图如下图) 持续集成 (后续补充) ![输入图片说明](images/automate.png) #### Docker的基础介绍:(一切皆云端,万物皆容器) 先简单介绍下基础概念以便更好的理解入手,Docker 是一个开源的应用容器引擎,它允许开发者将他们的应用程序和依赖项打包到一个可移植的容器中,然后发布到任何Linux机器或Windows机器上(解决了环境依赖等普适性问题,真正达到了 一次镜像,处处运行的目的),实现应用程序的轻量级、快速、可靠和一致的部署。 ``` Docker中有这样三个重要的概念: dockerfile(文件) 写程序需要源代码,那么“写”image就需要dockerfile,dockerfile就是image的源代码,docker就是"编译器"。 ⬇ image(镜像) 实际上你可以简单的把image理解为可执行程序,container就是运行起来的进程。 ⬇ container(容器) 由镜像(Images) 创建的运行实例,独立运行的一个或一组应用(相互隔离)。 总结:因此我们只需要在dockerfile中指定需要哪些程序、依赖什么样的配置,之后把dockerfile交给“编译器”docker进行“编译”,也就是docker build命令,生成的可执行程序就是image,之后就可以运行这个image了,这就是docker run命令,image运行起来后就是docker container。 ``` #### a、[环境搭建 linux下安装docker服务](https://www.cnblogs.com/zcjbky/p/18101710) #### b、[Docker安装Gitlab教程](https://www.cnblogs.com/zcjbky/p/18218371) #### c、[Docker构建python镜像](https://www.cnblogs.com/zcjbky/p/18196247) #### d、[docker部署jenkins容器并配置构建任务](https://www.cnblogs.com/zcjbky/p/18182488)