Files
apiautotest/README.md

705 lines
34 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
## 前言
公司突然要求你做自动化,但是没有代码基础不知道怎么做?或者有自动化基础,但是不知道如何系统性的做自动化, 放在yaml文件中维护不知道如何处理多业务依赖的逻辑
那么本自动化框架,将为你解决这些问题。
- 框架主要使用 python 语言编写,结合 pytest 进行二次开发,用户仅需要在 yaml 文件中编写测试用例, 编写成功之后,会自动生成测试用例代码。
- 如果是具备代码基础的,也可以直接通过 py 文件编写测试用例。
- 使用 Allure 生成报告,并针对测试报告样式进行了调整,使得报告更加美观;
- 测试完成后,支持发送 企业微信通知/ 钉钉通知/ 邮箱通知,灵活配置。
- 使用GitLink个人建站服务部署Allure在线测试报告随时随地查看测试报告。
## 一、框架介绍
本框架主要是基于 Python + Pytest + Allure + Loguru + 邮件通知/企业微信通知/钉钉通知 实现的接口自动化框架。
* git地址: [https://www.gitlink.org.cn/kytest/apiautotest.git](https://www.gitlink.org.cn/floraachy/apiautotest)
* 项目参与者: floraachy
* 个人主页: [https://www.gitlink.org.cn/floraachy](https://www.gitlink.org.cn/floraachy)
* 测试社区地址: [https://www.gitlink.org.cn/zone/tester](https://www.gitlink.org.cn/zone/tester)
<img src="https://www.gitlink.org.cn//api/attachments/ca4845c4-9bdd-4485-9f68-14352520a757" alt="加入我们" style="width: 300px; height: 350px;">
如果对您有帮助,请点亮 小星星 以表支持,谢谢!
对于框架有任何问题,请先仔细阅读本文~ 如果还有不了解的,欢迎联系我!
## 二、实现功能
* 通过session会话方式解决了登录之后cookie关联处理`
* 动态多断言: 如接口需要同时校验响应数据和sql校验支持多场景断言
* 支持单独调试用例,支持用例的重复执行
* 框架天然支持接口动态传参、关联灵活处理
* 支持测试数据分析,测试数据不符合规范有预警机制
* 支持通过用例数据动态配置pytest.mark 包括自定义标记pytest.mark.skip以及pytest.mark.usefixtures
* 支持利用allure设置用例优先级运行指定优先级的用例
* 执行环境一键切换,解决多环境相互影响问题
* 自动生成用例代码: 测试人员在yaml/excel文件中填写好测试用例, 程序可以直接生成用例代码,纯小白也能使用
* 支持参数多类型提取支持从响应数据数据库用例数据中通过jsonpath或者正则方式提取数据
* 使用Allure生成测试报告并对测试报告进行了定制化修改使得测试报告更加美观
* 日志模块: 采用loguru管理日志可以输出更为优雅简洁的日志
* 钉钉、企业微信通知: 支持多种通知场景,执行成功之后,可选择发送钉钉、或者企业微信、邮箱通知
* 使用pipenv管理虚拟环境和依赖文件提供了一系列命令和选项来帮助你实现各种依赖和环境管理相关的操作
* 支持将swagger.json接口文档转为YAML用例
* 支持接口相应后添加等待时间,方便接口调用后,进行一系列数据初始化操作,待操作成功后,执行后续接口
## 三、依赖库
```
allure_python_commons==2.9.45
click==8.1.7
Faker==21.0.0
jsonpath==0.82.2
loguru==0.7.2
openpyxl==3.1.2
pydantic==2.7.1
PyMySQL==1.1.0
pytest==8.0.2 Pytest 8.2.0 和 8.1.0 的几个版本会破坏 allure 的 listener 导致执行报错也就是版本不兼容需把pytest 回退到8.0.2就不报错啦!
PyYAML==6.0.1
PyYAML==6.0.1
Requests==2.31.0
requests_toolbelt==1.0.0
ruamel.base==1.0.0
sshtunnel==0.4.0
xpinyin==0.7.6
yagmail==0.15.293
```
## 四、安装教程
1. 通过Git工具clone代码到本地 或者 直接下载压缩包ZIP
```
https://gitlink.org.cn/floraachy/apiautotest.git
```
2. 本地电脑搭建好 python环境我使用的python版本是3.9。包括allure测试报告所需的java环境安装jdk
3. 安装依赖包
方法一使用pipenv管理依赖包
```
注意: 如果不熟悉pipenv 可以跳过该步骤。
```
1) 安装pipenv
```
# 建议在项目根目录下执行命令安装
pip install pipenv
```
2) 使用pipenv管理安装环境依赖包pipenv install (必须在项目根目录下执行)
```
注意使用pipenv install会自动安装Pipfile里面的依赖包该依赖包仅安装在虚拟环境里不安装在测试机。
```
方法二:直接将依赖包安装在本机
```
pip install -r requirements.txt
```
扩展: 使用 pipreqs 生成 requirements.txt
```
# 安装
pip install pipreqs
# 在当前目录生成
pipreqs . --encoding=utf8 --force
注意 --encoding=utf8 为使用utf8编码不然可能会报UnicodeDecodeError: 'gbk' codec can't decode byte 0xae in position 406: illegal multibyte sequence 的错误。
--force 强制执行,当 生成目录下的requirements.txt存在时覆盖。
```
如上环境都已经搭建好了,包括框架依赖包也都安装好了。
<br/>
注意:
- 很多同学不太熟悉pipenv会存在问题比如我按照上述操作安装了依赖包怎么运行报错呢一定要记住使用pipenv安装依赖包依赖包只安装在虚拟环境不安装在你的测试机器。所以你安装完成后直接运行肯定会报错。我们需要进入我们创建的虚拟环境再运行测试代码。具体步骤参考章节"运行自动化测试"。
- 如果存在Python版本与我的不一致的问题请移步最后的章节"初始化项目可能遇到的问题" 查找解决办法。
- 另外我们如果是使用pycharm直接右键run的情况我们需要pycharm解释器选择我们创建的虚拟环境才不会报少包的错误。
## 五、如何创建用例
### 1. 修改配置文件 `config.settings.py`
1确认用例是通过YAML还是Excel编写由CASE_FILE_TYPE控制
2确认测试完成后是否发送测试结果由SEND_RESULT_TYPE控制并填充对应邮件/钉钉/企业微信配置信息
3确认测试是否需要进行数据库断言如有需求填充数据库配置信息
4指定日志收集级别由LOG_LEVEL控制
### 2. 修改全局变量,增加测试数据 `config.settings.py`
1确认RunConfig的各项参数可以调整失败重跑次数`rerun` 失败重跑间隔时间`reruns_delay`,当达到最大失败数,停止执行`max_fail`
2确认测试完成后是否发送测试结果由SEND_RESULT_TYPE控制并填充对应邮件/钉钉/企业微信配置信息
3指定日志收集级别由LOG_LEVEL控制
4 配置测试相关数据:
ENV_VARS["common"]是一些公共参数,如报告标题,报告名称,测试者,测试部门。后续会显示在测试报告上。如果还有其他,可自行添加
ENV_VARS["test"]是保存test环境的一些测试数据。ENV_VARS["live"]是保存live环境的一些测试数据。如果还有其他环境可以继续增加例如增加ENV_VARS["dev"] = {"host": "", ......}
### 3. 删除框架中的示例用例数据
1删除 `interface`目录下所有的YAML和EXCEL文件(每一个文件都保存的接口测试用例)
2删除 `test_case/test_manual_case`目录下所有手动编写的用例,后续有需要可以在该目录下手动编写用例。
注意conftest.py文件中非业务相关的代码可以保留。
### 4. 编写测试用例(两种方式任选其一或者都选)
#### 1自动生成测试用例 `data` `test_case.test_auto_case`
- 在目录`interface`下新建一个YAML/Excel文件。按照如下字段要求进行测试用例数据添加
- 注意如果需要自动创建测试用例文件YAML/Excel文件的文件名需要以"test"开头。
#### 2手动编写测试用例 `interface` `test_case.test_manual_case`
- 原则上如果是手动编写测试用例python代码 测试用例数据文件不要以"test"开头。 如果以“test”开头可能导致用例运行多次。
1在目录`interface`下新建一个YAML/Excel文件按照要求编写测试用例数据
2在test_case.test_manual_case下新建一个以"test"开头的测试方法,进行测试用例方法编写。
### 5. 用例中相关字段的介绍
```yaml
case_common: # 公共参数
allure_epic: 用作于@allure.epic()装饰器中的内容。
allure_feature: 用作于@allure.feature()装饰器中的内容。
allure_story: 用作于@allure.story()装饰器中的内容。
case_markers: 给测试方法添加标记支持自定义标记skip, usefixtures。 格式是列表嵌套字符串或者字典。例如: # ['glcc', {'skip': '跳过执行该用例'}]
common_dependence: # 放置公共依赖, 作用范围是class
setup:
interface:
database:
env_vars:
teardown:
interface:
database:
env_vars:
case_info: # 具体的用例数据,是以列表的形式进行管理
-
id: 用例id注意需要全局唯一方便后续用于用例接口依赖
title: 用例标题
severity: 用例优先级支持如下几种NORMAL BLOCKERCRITICALMINORTRIVIAL 为空和错误都认为是NORMAL
run: 是否执行用例为空或者True都会执行为False则不执行。
url: 请求路径(可填写全路径 或者 资源路径。通常我们填写资源路径。在用例执行前会针对路径进行处理。具体可见case_utils.request_control.py.RequestPreDataHandle.url_handle。注请求路径=基准路径host/base_url+资源路径(url)。
method: 请求方式例如GET, POST, DELETE, PUT, PATCH等
headers: 请求头注意如果在headers里面防止cookies其值类型需要是字符串
cookies: 请求cookies格式是DICT CookieJar对象
request_type: 请求数据类型params, json, file, data
payload: 请求参数
files: 需要上传的文件的相对路径会自动拼接files目录。 os.path.join(files, "这里传递的files参数值")
wait_seconds: 选填,接口请求后的等待时间,单位是秒。传递错误,会被认为是空
assert_response: 响应断言
assert_sql: 数据库断言
extract: 后置提取参数
case_dependence: # 用例依赖, 作用范围是function
setup:
interface:
database:
env_vars:
teardown:
interface:
database:
env_vars:
```
### 6. 参数提取说明
目前支持从响应数据response、数据库database、用例数据case中提取数据。
目前支持3种方式的参数提取type_jsonpath, type_re, type_response
注意:
- 提取来源关键字case, response, database必须保持完全一致
- 提取方式关键字type_jsonpath, type_re, type_response必须保持完全一致
#### 1从响应数据中提取参数
目前从响应数据中提取参数支持提取方式type_jsonpath, type_re, type_response。
参考写法如下:
```
extract:
response:
type_jsonpath:
res_j_nickname: $.username
type_re:
res_re_nickname: \"username":"(.*?)"
type_response:
cookies1: response.cookies
```
其中`res_j_nickname`表示提取的变量名,后续会保存在全局变量`GLOBAL_VARS`中, 可以直接在其他接口中使用:`${res_j_nickname}`
其中`$.username`表示提取表达式,根据提取方式来写不同的表达式,表达式要写正确,否则提取不到值。
注意:
- jsonpath提取方式`type_jsonpath`如果提取到的值是长度为1的列表会自动获取第一个元素其值类型由list变更为str。例如通过`name: $.data` 提取到的值是:`["flora"]`, 最后name的值会是`"flora"`
- 正则表达式提取方式`type_re`如果提取到的值是长度为1的列表会自动获取第一个元素其值类型由list变更为str。例如通过`name: "username":"(.*?)"` 提取到的值是:`["flora"]`, 最后name的值会是`"flora"`
- 响应对应提取方式`type_response` 则可以获取Reponse对应自带方法的一些值例如`response.status_code` `response.cookies`, `response.text`, `response.headers`, `response.is_redirect`等。;
注意:之前老版本是没有指定提取来源的,本次更新兼容了老版本的写法:
```
extract:
type_jsonpath:
res_j_nickname: $.username
type_re:
res_re_nickname: \"username":"(.*?)"
type_response:
cookies1: response.cookies
```
#### 2从用例数据中提取参数
目前从响应数据中提取参数支持提取方式type_jsonpath, type_re。
参考写法如下:
```
case:
type_jsonpath:
case_login: $.payload.login
type_re:
case_url_key: "'url': 'https?://[^/]+/api/(.*?)/login.json'"
```
注意假如需要提取url中的参数由于url我们是处理过的。比如用例数据中的url是`/api/login.json`但是实际执行过程中的url是带有域名的 `https://www.gitlink.org.cn/api/login.json` 因此提取表达式需要将目标值对准是有域名的url。
#### 3从数据库中提取参数
目前从响应数据中提取参数支持提取方式type_jsonpath, type_re。
注意:
- 查询数据库的方法我用的是查询所有如果有多条符合条件的数据则返回所有数据。查询结果是list格式
- 如果不需要查询数据库,`setting.py`中的`ENV_VARS`中对应环境的`db_info`字段为空。代码中判断了`db_info`字段不为空,才进行数据库参数提取。
参考写法如下:
```
database:
# 数据库查询用的是查询所有符合条件的数据,查询结果是一个列表
sql: select * from users limit 2;
type_re:
sql_re_nickname: "'login': '(.*?)'"
type_jsonpath:
sql_j_login: $..login
```
### 7. 断言方式
以下是支持的几种断言方式:
| 断言方式 | 说明 |
| ------------ | ------------ |
| == | 相等,判断预期结果是否等于实际结果 |
| lt | 小于, 判断预期结果是否小于实际结果 |
| le | 小于等于, 判断预期结果是否小于等于实际结果 |
| gt | 大于, 判断预期结果是否大于实际结果 |
| ge | 大于等于,判断预期结果是否大于等于实际结果 |
| not_eq | 不相等,判断预期结果是否不等于实际结果 |
| str_eq | 字符串相等,判断预期结果是否等于实际结果 |
| len_eq | 长度等于,判断预期结果是否等于实际结果的长度 |
| len_gt | 长度大于,判断预期结果是否大于实际结果的长度 |
| len_ge | 长度大于等于,判断预期结果是否大于等于实际结果的长度 |
| len_lt | 长度小于,判断预期结果是否小于实际结果的长度 |
| len_le | 长度小于等于,判断预期结果是否小于等于实际结果的长度 |
| contains | 包含,判断预期结果内容被实际结果包含, 预期结果 in 实际结果 |
| contained_by | 被包含,判断预期结果包含实际结果, 实际结果 in 预期结果 |
| startswith | 以什么开头,判断实际结果是否是以预期结果开头的 |
| endswith | 以什么结尾,判断实际结果是否是以预期结果结尾的 |
### 8. 响应断言说明
#### 断言状态码
如果想要断言接口响应码,直接这样写即可:
参考示例:
```
assert_response:
status_code: 200
```
#### 响应数据断言
响应断言的参数说明:
```
断言标识(自定义,不为空即可,没有实际的意义):
message: 断言信息,非必填,可为空
expect_value: 预期结果
assert_type: 断言类型,支持如下:==, lt, le, gt, ge, not_eq, str_eq, len_eq, len_gt, len_ge, len_lt, len_le, contains, contained_by, startswith, endswith
type_jsonpath: 通过jsonpath表达式从response.json()提取实际结果与type_re任选其一
type_re: 通过正则表达式从response.text提取实际结果与type_jsonpath任选其一;如果不填则默认获取response.text作为实际结果
```
注意:在进行断言的时候,左侧是预期结果,右侧是实际结果。比如我断言类型是`lt` 那么就是预期结果<实际结果
参考示例:
```
assert_response:
user_id:
message: 断言接口返回的user_id
expect_value: ${user_id}
assert_type: ==
type_jsonpath: $.user_id
```
```
assert_response:
user_id:
expect_value: ${user_id}
assert_type: ==
type_jsonpath: $.user_id
```
### 9. 数据库断言说明
数据库断言的参数说明:
```
断言标识(自定义,不为空即可,没有实际的意义):
message: 断言信息,非必填,可为空
sql: 数据库查询语句,必填
expect_value: 预期结果
assert_type: 断言类型,支持如下:==, lt, le, gt, ge, not_eq, str_eq, len_eq, len_gt, len_ge, len_lt, len_le, contains, contained_by, startswith, endswith
type_jsonpath: 通过jsonpath表达式通从数据库查询结果提取实际结果与type_re任选其一
type_re: 通过正则表达式从数据库查询结果提取实际结果与type_jsonpath任选其一;如果不填则默认SQL直接查询结果作为实际结果
```
注意:在进行断言的时候,左侧是预期结果,右侧是实际结果。比如我断言类型是`lt` 那么就是预期结果<实际结果
参考示例:
```
assert_sql:
contains_user:
message: 断言数据库查询tokens表表中存在该登录用户记录预期查询结果的长度为1
sql: select * from tokens where user_id=${user_id};
expect_value: 1
assert_type: len_eq
contains_user2:
message: 断言数据库查询tokens表表中存在该登录用户记录;预期 ${user_id} in 查询结果jsonpath式匹配后的结果
sql: select * from tokens where user_id=${user_id};
type_jsonpath: $..user_id
expect_value: ${user_id}
assert_type: ==
contains_user3:
message: 断言数据库查询tokens表表中存在该登录用户记录预期 ${user_id} in 查询结果(正则表达式匹配后的结果)
sql: select * from tokens;
type_re: "'user_id': (.*?),"
expect_value: ${user_id}
assert_type: contains
```
### 10. 用例依赖说明
目前支持3种依赖方式环境变量依赖env_vars接口依赖interface数据库查询依赖database
用例依赖分为有2个范围case_dependence作用于functioncommon_dependence作用于class。
用例依赖分为前置setup和后置依赖teardown。
注意:
- 依赖关键字env_vars, interface, database必须保持完全一致
- 提取方式关键字type_jsonpath, type_re必须保持完全一致
- 不同依赖方式,不同作用范围,前置和后置可以不同时存在,也可以同时存在;
#### 1环境变量依赖env_vars
环境变量依赖信息, 字典格式key为环境变量名称value为环境变量值。value可以为常量也可以为data_handle内支持的方法也可以是全局变量。为空时表示没有依赖。
参考写法如下(单个用例的依赖作用域是function)
```
case_dependence:
setup:
env_vars:
pms_project_words: ${generate_words()}
teardown:
env_vars:
user_login: flora
```
参考写法如下(用例方法的依赖作用域是class)
```
common_dependence:
setup:
env_vars:
pms_project_words: ${generate_words()}
teardown:
env_vars:
user_login: flora
```
#### 2接口依赖interface
用例依赖的接口id支持str和list格式。接口id指的是每一个YAML/EXCEL用例中的ID。
参考写法如下(单个用例的依赖作用域是function)
```
case_dependence:
setup:
interface: pms_get_project_user_list_01
teardown:
interface:
- pms_get_project_user_list_01
- pms_get_enterprise_user_list_01
```
参考写法如下(用例方法的依赖作用域是class)
```
common_dependence:
setup:
interface: pms_get_project_user_list_01
teardown:
interface:
- pms_get_project_user_list_01
- pms_get_enterprise_user_list_01
```
#### 3数据库查询依赖database
数据库依赖支持dict和list方式。提取方式支持两种type_jsonpath, type_re。
注意:
- 必须要有sql关键字。并且查询数据库的方法我用的是查询所有如果有多条符合条件的数据则返回所有数据。查询结果是list格式
- 如果存在数据库依赖setting.py中的ENV_VARS中对应环境的db_info字段必须不为空才进行数据库相关操作。
参考写法如下(单个用例的依赖作用域是function)
```
case_dependence:
setup:
database:
sql: select * from pms_project limit 2;
type_re:
sql_re_project_assignee_id: "(?<=project_assignee_id': )[^,]+"
type_jsonpath:
sql_j_project_assignee_id: $..project_assignee_id
teardown:
database:
-
sql: select * from pms_project limit 2;
type_re:
sql_re_project_assignee_id: "(?<=project_assignee_id': )[^,]+"
type_jsonpath:
sql_j_project_assignee_id: $..project_assignee_id
```
参考写法如下(用例方法的依赖作用域是class)
```
common_dependence:
setup:
database:
sql: select * from pms_project limit 2;
type_re:
sql_re_project_assignee_id: "(?<=project_assignee_id': )[^,]+"
type_jsonpath:
sql_j_project_assignee_id: $..project_assignee_id
teardown:
database:
-
sql: select * from pms_project limit 2;
type_re:
sql_re_project_assignee_id: "(?<=project_assignee_id': )[^,]+"
type_jsonpath:
sql_j_project_assignee_id: $..project_assignee_id
```
### 11. Excel用例单独说明
框架支持excel多表单自动生成测试用例每一个表单作为一个测试用例模块。
例如:
excel表格名称是test_demo.xlsx
excel表单1名称是GitLink-登录模块
excel表单2名称是示例模块
生成规则:
- 如果excel表单中存在"-",我们将取"-"后面的部分的首字母拼接excel文件名称作为测试用例模块/测试用例类/测试用例方法名称
- 如果excel表单中不存在"-"我们将直接获取表单名称首字母拼接excel文件名称作为测试用例模块/测试用例类/测试用例方法名称
- 测试用例模块/测试用例类/测试用例方法名称同时也将遵循python语法规则进行适当调整
<br/>
基于上述规则:
- excel第一个表单生成的测试用例
测试用例模块test_demo_dlmk.py
测试用例类TestDemoDlmkAuto
测试用例方法test_demo_dlmk_auto
- excel第二个表单生成的测试用例
测试用例模块test_demo_slmk.py
测试用例类TestDemoSlmkAuto
测试用例方法test_demo_slmk_auto
## 六、运行自动化测试
### 方式一使用pipenv管理虚拟环境
#### 1. 激活已存在的虚拟环境
- 如果不存在会创建一个pipenv shell (必须在项目根目录下执行)
#### 2. 运行
```
在pycharm>terminal或者电脑命令窗口进入项目根路径执行如下命令如果依赖包是安装在虚拟环境中需要先启动虚拟环境
> python run.py 默认在test环境运行测试用例, 生成allure测试报告
> python run.py -m demo 在test环境仅运行打了标记demo用例生成allure测试报告
> python run.py -env live 在live环境运行测试用例
> python run.py -env=test 在test环境运行测试用例
> python run.py -report=no 在test环境下允许测试用例不生成allure测试报告
```
或者上述步骤可以合并为pipenv run python run.py
### 方式二:依赖包安装在本机
```
在pycharm>terminal或者电脑命令窗口进入项目根路径执行如下命令如果依赖包是安装在虚拟环境中需要先启动虚拟环境
> python run.py 默认在test环境运行测试用例, 生成allure测试报告
> python run.py -m demo 在test环境仅运行打了标记demo用例生成allure测试报告
> python run.py -env live 在live环境运行测试用例
> python run.py -env=test 在test环境运行测试用例
> python run.py -report=no 在test环境下允许测试用例不生成allure测试报告
```
注意:
- 如果pycharm.interpreter拥有了框架所需的所有依赖包可以通过pycharm直接在`run.py`中右键运行
## 七、查看测试报告
### Allure测试报告
1. Allure生成的测试报告支持通过pycharm点击`outputs/report/allure_html/index.html`,文件右上角选择浏览器打开查看测试报告
2. 如果不通过pycharm打开直接通过文件夹打开windows系统环境下可以点击`outputs/report/allure_html/双击打开Allure报告.bat`打开查看测试报告
<br/>
注意:
- 通过点击`outputs/report/allure_html/双击打开Allure报告.bat`打开测试报告的方法暂时不支持mac系统
- 如果通过点击`outputs/report/allure_html/双击打开Allure报告.bat`打开测试报告,命令窗口显示乱码,或者打不开,可以把`.bat`的文件名称修改为英文的名称,里面的所有中文注释全部移除,再次尝试
## 八 、详细功能说明
- [如何实现动态数据、随机数据的热加载?](https://www.gitlink.org.cn/zone/tester/newdetail/236)
我们有些特殊的场景,可能会涉及到一些定制化的数据,每次执行数据,需要按照指定规则随机生成,实时加载数据,那么这部分应该如何处理呢?
- [如何处理同一环境存在多域名的情况?](https://www.gitlink.org.cn/zone/tester/newdetail/234)
很多公司,通常一套环境是由多个微服务组成。每一个微服务具备不同的域名。那么针对这种同一环境存在多域名的情况,我们应该如何处理呢?
- [如何处理同一套框架测试多套环境的情况?](https://www.gitlink.org.cn/zone/tester/newdetail/233)
假如我想要我的自动化代码分别在不同环境执行,如何处理呢?
- [如何处理用例中需要依赖登录的token/cookies的情况](https://www.gitlink.org.cn/zone/tester/newdetail/235)
我们进行测试的时候,很多接口都是需要先登录之后再进行操作。但是我们不可能每测试一次接口,都登录一次吧,这样有点冗余了。那么,针对这种情况如何处理呢?
- [如何测试上传文件接口?](https://www.gitlink.org.cn/zone/tester/newdetail/238)
我们通过MultipartEncoder的方式进行文件上传。
- [如何通过用例数据动态配置pytest.mark](https://www.gitlink.org.cn/zone/tester/newdetail/257)
在测试过程中我们经常需要对测试用例进行分类运行时仅执行这一类用例。为了实现这一功能我在测试用例中引入了添加pytest的自定义标记的功能同时扩展支持了pytest.mark.skip以及pytest,mark.usefixtues。
注意目前这一功能仅支持通过YAML格式编写用例。EXCEL用例暂时不支持。
- [如何设置测试用例优先级](https://www.gitlink.org.cn/zone/tester/newdetail/260)
测试用例会分优先级, 我们可以利用allure的特性设置用例优先级以及运行指定优先级的用例。
- [如何提取响应数据作为全局变量并使用?](https://www.gitlink.org.cn/zone/tester/newdetail/237)
在测试过程中,通常下一个接口需要用到上一个接口的响应数据,这个时候就涉及到参数的提取。
- [如何进行响应数据断言以及数据库断言?](https://www.gitlink.org.cn/zone/tester/newdetail/239)
目前支持的断言方式:==, lt, le, gt, ge, not_eq, str_eq, len_eq, len_gt, len_ge, len_lt, len_le, contains, contained_by, startswith, endswith
- [如何配置邮箱通知?](https://www.gitlink.org.cn/zone/tester/newdetail/242)
我们通过第三方模块yagmail发送邮件。
- [如何配置钉钉通知?](https://www.gitlink.org.cn/zone/tester/newdetail/243)
我们通过封装钉钉机器人发送钉钉通知。
- [如何配置企业微信通知?](https://www.gitlink.org.cn/zone/tester/newdetail/241)
我们通过封装企业微信机器人发送通知。
- [python虚拟管理工具--pipenv使用教程](https://www.gitlink.org.cn/zone/tester/newdetail/505)
在使用Python语言的时候我们使用pip来安装第三方包但是由于pip的特性系统中只能安装每个包的一个版本。但是在实际项目开发中不同项目可能需要第三方包的不同版本Python的解决方案就是虚拟环境。
顾名思义虚拟环境就是虚拟出来的一个隔离的Python环境每个项目都可以有自己的虚拟环境用pip安装各自的第三方包不同项目之间也不会存在冲突。
创建虚拟环境需要一些工具, 我们使用pipenv来创建虚拟环境和管理依赖包。
- [如何调试单个用例?](https://www.gitlink.org.cn/zone/tester/newdetail/512)
有些小伙伴在测试的时候,想要单独调试用例,但是不清楚如何调试。本文将详细讲解~
- [如何重复执行用例?](https://www.gitlink.org.cn/zone/tester/newdetail/514)
平常在做功能测试的时候经常会遇到某个模块不稳定偶然会出现一些bug对于这种问题我们会针对此用例反复执行多次最终复现出问题来。
自动化运行用例时候也会出现偶然的bug可以针对单个用例重复执行多次。
- [pytest-xdist(分布式执行)](https://www.gitlink.org.cn/zone/tester/newdetail/785)
当测试用例非常多的时候,一条条按顺序执行测试用例,是很浪费测试时间的。这时候就可以用到 pytest-xdist让自动化测试用例可以分布式执行从而大大节省测试时间。
## 九、初始化项目可能遇到的问题
- [测试机安装python版本与本框架要求不一致怎么办](https://www.gitlink.org.cn/zone/tester/newdetail/245)
- [无法安装依赖包或者安装很慢,怎么办?](https://www.gitlink.org.cn/zone/tester/newdetail/244)
## ## 🐳 Docker构建运行
前提条件:
- 宿主机已经安装docker
- 仓库根目录下已编写好`dockerfile`
### 1.构建镜像
**语法**`docker build -f Dockerfile的路径 -t 镜像的名称及标签 镜像构建的目录`
- `-f`:指定 Dockerfile 文件路径(可使用绝对/相对路径)
- `-t`:指定镜像名称及标签格式 `[name]:[tag]`
- `.`:表示当前构建上下文目录
- `--no-cache` 表示禁用缓存
**示例**
```bash
docker build -f dockerfile --no-cache -t apitest:2.0 .
```
### 2. 运行镜像
**语法**`docker run [OPTIONS] IMAGE[:TAG|@DIGEST] [COMMAND] [ARG…]`
- `-d/detach`:后台运行容器
- `p/publish`:端口映射格式 [主机IP:]主机端口:容器端口[/协议]
- `name`:指定容器名称(未指定时会自动生成随机名称)
- `-e/env`:设置环境变量
- `-v/volume`:挂载数据卷(将宿主机上的一个目录(文件夹)/文件挂载到容器内的指定目录/文件,使得容器内的该目录/文件与宿主机保持同步。)
- `restart`:设置重启策略(如 restart=always
**示例**
```bash
docker run --rm --name apitest -e NGINX="http://xxx" -v -v /data/nginx/html/apiautotest/:/apiautotest/ -v /data/chytest/env/test.yaml:/apiautotest/env/test.yaml apitest:2.0
docker run \
-v /data/nginx/html/apiautotest/:/apiautotest/ \
-v /data/chytest/env/test.yaml:/apiautotest/env/test.yaml \
-e NGINX="http://xxx" \
--name apitest \
apitest:2.0
```
- 挂载目录
将宿主机的 `/data/nginx/html/apiautotest/` 目录挂载到容器内的 `/apiautotest/` 目录:
(运行的时候,会运行宿主机目录`/apiautotest/`的文件,运行完成后,将宿主机目录`/data/nginx/html/apiautotest/`拷贝到容器内的目录`/apiautotest/`)
`-v /data/nginx/html/apiautotest/output/:/apiautotest/output/`
- 挂载单个文件
将宿主机的 `/data/chytest/env/test.yaml` 文件挂载到容器内的 `/apiautotest/env/test.yaml` 文件:
(实际运行的时候,会读取将宿主机的 `/data/chytest/env/test.yaml`的内容作为测试数据)
`-v /data/chytest/env/test.yaml:/apiautotest/env/test.yaml`
### 3. 流水线参考
```yaml
name: "接口测试-生成报告"
on:
push:
branches:
- '*'
paths-ignore:
- '.gitea/workflows/**'
- '.github/workflows/**'
jobs:
job-487fcffc:
name: "测试[job-487fcffc]"
# 运行环境,这里就是上面定义的多个 os
runs-on: 'ubuntu-latest'
steps:
- name: "克隆代码[ssh-bbc2533]"
uses: http://xxx/actions/ssh-action@v1.0.3
with:
host: 'xxx'
port: '22'
username: 'root'
password: 'xxx'
script: 'cd /data/nginx/html/ && git clone --recurse-submodules https://gitlink.org.cn/kytest/apiautotest.git>/dev/null || echo "代码已存在无需重新克隆,仅需拉取最新代码" && cd /data/nginx/html/apiautotest && git pull --force origin master:master && git log -1 '
- name: "ssh登录服务器[ssh-1bd148b]"
uses: http://xxx/actions/ssh-action@v1.0.3
with:
host: 'xxx'
port: '22'
username: 'root'
password: 'xxx'
script: 'cd /data/nginx/html/apiautotest && docker build -f dockerfile --no-cache -t apitest:2.0 .>/dev/null || echo "镜像已存在无需构建" && docker images | grep apitest'
- name: "执行测试[ssh-7cf8368e]"
uses: http://xxx/actions/ssh-action@v1.0.3
with:
host: 'xxx'
port: '22'
username: 'root'
password: 'xxx'
script: 'docker run --rm --name apitest -e NGINX="http://xxx:8001" -v /data/nginx/html/apiautotest/:/apiautotest/ apitest:2.0'
- name: "获取测试报告信息[log_match_action-7515d3d]"
uses: http://xxx/xxq250/log_match_action@master
with:
match-step: '3'
match-key: 'out: 测试报告地址:'
match-job-name: '自动化测试报告'
upload-api-domain: ''
check-contains-link: ''
show-type: 'html'
```
## 赞赏
如果这个库有帮助到你并且你很想支持库的后续开发和维护,那么你可以扫描下方二维码随意打赏我,我将不胜感激~
<img src="https://www.gitlink.org.cn/api/attachments/437395" style="width: 150px; height: auto;" />