pytest-auto-api2-cli 0.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. pytest_auto_api2_cli-0.2.0/PKG-INFO +945 -0
  2. pytest_auto_api2_cli-0.2.0/README.md +925 -0
  3. pytest_auto_api2_cli-0.2.0/cli.py +9 -0
  4. pytest_auto_api2_cli-0.2.0/common/__init__.py +0 -0
  5. pytest_auto_api2_cli-0.2.0/common/setting.py +78 -0
  6. pytest_auto_api2_cli-0.2.0/pyproject.toml +35 -0
  7. pytest_auto_api2_cli-0.2.0/pytest_auto_api2/__init__.py +4 -0
  8. pytest_auto_api2_cli-0.2.0/pytest_auto_api2/cli.py +900 -0
  9. pytest_auto_api2_cli-0.2.0/pytest_auto_api2/runtime/__init__.py +1 -0
  10. pytest_auto_api2_cli-0.2.0/pytest_auto_api2/runtime/api.py +10 -0
  11. pytest_auto_api2_cli-0.2.0/pytest_auto_api2/runtime/loader.py +80 -0
  12. pytest_auto_api2_cli-0.2.0/pytest_auto_api2_cli.egg-info/PKG-INFO +945 -0
  13. pytest_auto_api2_cli-0.2.0/pytest_auto_api2_cli.egg-info/SOURCES.txt +76 -0
  14. pytest_auto_api2_cli-0.2.0/pytest_auto_api2_cli.egg-info/dependency_links.txt +1 -0
  15. pytest_auto_api2_cli-0.2.0/pytest_auto_api2_cli.egg-info/entry_points.txt +2 -0
  16. pytest_auto_api2_cli-0.2.0/pytest_auto_api2_cli.egg-info/requires.txt +13 -0
  17. pytest_auto_api2_cli-0.2.0/pytest_auto_api2_cli.egg-info/top_level.txt +6 -0
  18. pytest_auto_api2_cli-0.2.0/run.py +85 -0
  19. pytest_auto_api2_cli-0.2.0/setup.cfg +4 -0
  20. pytest_auto_api2_cli-0.2.0/test_case/Collect/test_collect_addtool.py +40 -0
  21. pytest_auto_api2_cli-0.2.0/test_case/Collect/test_collect_delete_tool.py +40 -0
  22. pytest_auto_api2_cli-0.2.0/test_case/Collect/test_collect_tool_list.py +40 -0
  23. pytest_auto_api2_cli-0.2.0/test_case/Collect/test_collect_update_tool.py +40 -0
  24. pytest_auto_api2_cli-0.2.0/test_case/Login/test_login.py +40 -0
  25. pytest_auto_api2_cli-0.2.0/test_case/UserInfo/test_get_user_info.py +40 -0
  26. pytest_auto_api2_cli-0.2.0/test_case/__init__.py +6 -0
  27. pytest_auto_api2_cli-0.2.0/test_case/conftest.py +132 -0
  28. pytest_auto_api2_cli-0.2.0/utils/__init__.py +9 -0
  29. pytest_auto_api2_cli-0.2.0/utils/assertion/__init__.py +4 -0
  30. pytest_auto_api2_cli-0.2.0/utils/assertion/assert_control.py +179 -0
  31. pytest_auto_api2_cli-0.2.0/utils/assertion/assert_type.py +141 -0
  32. pytest_auto_api2_cli-0.2.0/utils/cache_process/__init__.py +4 -0
  33. pytest_auto_api2_cli-0.2.0/utils/cache_process/cache_control.py +89 -0
  34. pytest_auto_api2_cli-0.2.0/utils/cache_process/redis_control.py +106 -0
  35. pytest_auto_api2_cli-0.2.0/utils/logging_tool/__init__.py +4 -0
  36. pytest_auto_api2_cli-0.2.0/utils/logging_tool/log_control.py +84 -0
  37. pytest_auto_api2_cli-0.2.0/utils/logging_tool/log_decorator.py +48 -0
  38. pytest_auto_api2_cli-0.2.0/utils/logging_tool/run_time_decorator.py +34 -0
  39. pytest_auto_api2_cli-0.2.0/utils/mysql_tool/__init__.py +4 -0
  40. pytest_auto_api2_cli-0.2.0/utils/mysql_tool/mysql_control.py +175 -0
  41. pytest_auto_api2_cli-0.2.0/utils/notify/__init__.py +1 -0
  42. pytest_auto_api2_cli-0.2.0/utils/notify/ding_talk.py +153 -0
  43. pytest_auto_api2_cli-0.2.0/utils/notify/lark.py +181 -0
  44. pytest_auto_api2_cli-0.2.0/utils/notify/send_mail.py +84 -0
  45. pytest_auto_api2_cli-0.2.0/utils/notify/wechat_send.py +109 -0
  46. pytest_auto_api2_cli-0.2.0/utils/other_tools/__init__.py +0 -0
  47. pytest_auto_api2_cli-0.2.0/utils/other_tools/address_detection.py +73 -0
  48. pytest_auto_api2_cli-0.2.0/utils/other_tools/allure_data/__init__.py +4 -0
  49. pytest_auto_api2_cli-0.2.0/utils/other_tools/allure_data/allure_report_data.py +84 -0
  50. pytest_auto_api2_cli-0.2.0/utils/other_tools/allure_data/allure_tools.py +54 -0
  51. pytest_auto_api2_cli-0.2.0/utils/other_tools/allure_data/error_case_excel.py +316 -0
  52. pytest_auto_api2_cli-0.2.0/utils/other_tools/exceptions.py +47 -0
  53. pytest_auto_api2_cli-0.2.0/utils/other_tools/get_local_ip.py +27 -0
  54. pytest_auto_api2_cli-0.2.0/utils/other_tools/install_tool/__init__.py +0 -0
  55. pytest_auto_api2_cli-0.2.0/utils/other_tools/install_tool/install_requirements.py +91 -0
  56. pytest_auto_api2_cli-0.2.0/utils/other_tools/jsonpath_date_replace.py +28 -0
  57. pytest_auto_api2_cli-0.2.0/utils/other_tools/models.py +269 -0
  58. pytest_auto_api2_cli-0.2.0/utils/other_tools/thread_tool.py +91 -0
  59. pytest_auto_api2_cli-0.2.0/utils/read_files_tools/__init__.py +1 -0
  60. pytest_auto_api2_cli-0.2.0/utils/read_files_tools/case_automatic_control.py +138 -0
  61. pytest_auto_api2_cli-0.2.0/utils/read_files_tools/clean_files.py +19 -0
  62. pytest_auto_api2_cli-0.2.0/utils/read_files_tools/excel_control.py +55 -0
  63. pytest_auto_api2_cli-0.2.0/utils/read_files_tools/get_all_files_path.py +27 -0
  64. pytest_auto_api2_cli-0.2.0/utils/read_files_tools/get_yaml_data_analysis.py +156 -0
  65. pytest_auto_api2_cli-0.2.0/utils/read_files_tools/regular_control.py +209 -0
  66. pytest_auto_api2_cli-0.2.0/utils/read_files_tools/swagger_for_yaml.py +145 -0
  67. pytest_auto_api2_cli-0.2.0/utils/read_files_tools/testcase_template.py +103 -0
  68. pytest_auto_api2_cli-0.2.0/utils/read_files_tools/yaml_control.py +86 -0
  69. pytest_auto_api2_cli-0.2.0/utils/recording/__init__.py +0 -0
  70. pytest_auto_api2_cli-0.2.0/utils/recording/mitmproxy_control.py +225 -0
  71. pytest_auto_api2_cli-0.2.0/utils/requests_tool/__init__.py +0 -0
  72. pytest_auto_api2_cli-0.2.0/utils/requests_tool/dependent_case.py +273 -0
  73. pytest_auto_api2_cli-0.2.0/utils/requests_tool/encryption_algorithm_control.py +80 -0
  74. pytest_auto_api2_cli-0.2.0/utils/requests_tool/request_control.py +443 -0
  75. pytest_auto_api2_cli-0.2.0/utils/requests_tool/set_current_request_cache.py +73 -0
  76. pytest_auto_api2_cli-0.2.0/utils/requests_tool/teardown_control.py +280 -0
  77. pytest_auto_api2_cli-0.2.0/utils/times_tool/__init__.py +0 -0
  78. pytest_auto_api2_cli-0.2.0/utils/times_tool/time_control.py +87 -0
@@ -0,0 +1,945 @@
1
+ Metadata-Version: 2.4
2
+ Name: pytest-auto-api2-cli
3
+ Version: 0.2.0
4
+ Summary: CLI for generating and running pytest-auto-api2 test cases.
5
+ Requires-Python: >=3.8
6
+ Description-Content-Type: text/markdown
7
+ Requires-Dist: allure-pytest==2.13.5
8
+ Requires-Dist: colorlog==6.6.0
9
+ Requires-Dist: DingtalkChatbot==1.5.3
10
+ Requires-Dist: Faker==37.5.3
11
+ Requires-Dist: jsonpath==0.82.2
12
+ Requires-Dist: PyMySQL==1.1.1
13
+ Requires-Dist: pydantic==2.11.7
14
+ Requires-Dist: PyYAML==6.0.2
15
+ Requires-Dist: pytest==8.4.1
16
+ Requires-Dist: requests==2.32.5
17
+ Requires-Dist: requests-toolbelt==1.0.0
18
+ Requires-Dist: urllib3==2.5.0
19
+ Requires-Dist: xlwings==0.27.7
20
+
21
+
22
+ ## 框架介绍
23
+
24
+ 本框架主要是基于 Python + pytest + allure + log + yaml + mysql + redis + 钉钉通知 + Jenkins 实现的接口自动化框架。
25
+
26
+ * git地址: [https://gitee.com/yu_xiao_qi/pytest-auto-api2](https://gitee.com/yu_xiao_qi/pytest-auto-api2)
27
+ * 项目参与者: 余少琪
28
+ * 技术支持邮箱: 1603453211@qq.com
29
+ * 个人博客地址: [https://blog.csdn.net/weixin_43865008](https://blog.csdn.net/weixin_43865008)
30
+
31
+ 如果对您有帮助,请点亮 小星星 以表支持,谢谢
32
+
33
+ ![img.png](Files/image/starts.png)
34
+
35
+ ## 前言
36
+
37
+ 公司突然要求你做自动化,但是没有代码基础不知道怎么做?或者有自动化基础,但是不知道如何系统性的做自动化,
38
+ 放在yaml文件中维护,不知道如何处理多业务依赖的逻辑?
39
+
40
+ 那么这里 Gitte 中开源的自动化框架,将为你解决这些问题。
41
+ 框架主要使用 python 语言编写,结合 pytest 进行二次开发,用户仅需要在 yaml 文件中编写测试用例,
42
+ 编写成功之后,会自动生成 pytest 的代码,零基础代码小白,也可以操作。
43
+
44
+ 本框架支持多业务接口依赖,多进程执行,mysql 数据库断言和 接口响应断言,并且用例直接在yaml文件中维护,无需编写业务代码,
45
+ 接口pytest框架生成allure报告,并且发送 企业微信通知/ 钉钉通知/ 邮箱通知/ 飞书通知,灵活配置。
46
+
47
+ ## 实现功能
48
+
49
+ * 测试数据隔离, 实现数据驱动
50
+ * 支持多接口数据依赖: 如A接口需要同时依赖B、C接口的响应数据作为参数
51
+ * 数据库断言: 直接在测试用例中写入查询的sql即可断言,无需编写代码
52
+ * 动态多断言: 如接口需要同时校验响应数据和sql校验,支持多场景断言
53
+ * 自动生成用例代码: 测试人员在yaml文件中填写好测试用例, 程序可以直接生成用例代码,纯小白也能使用
54
+ * 代理录制: 支持代理录制,生成yaml格式的测试用例
55
+ * 统计接口的运行时长: 拓展功能,订制开关,可以决定是否需要使用
56
+ * 日志模块: 打印每个接口的日志信息,同样订制了开关,可以决定是否需要打印日志
57
+ * 钉钉、企业微信通知: 支持多种通知场景,执行成功之后,可选择发送钉钉、或者企业微信、邮箱通知
58
+ * 自定义拓展字段: 如用例中需要生成的随机数据,可直接调用
59
+ * 多线程执行
60
+ * 支持swagger接口文档转成yaml用例,节省用例编写时间
61
+
62
+
63
+ ## 遇到问题
64
+
65
+ * 请仔细阅读文档,文档中几乎可以帮你避免所有的问题
66
+ * 可以添加微信: being_chaoren, 添加微信会将你拉倒自动化交流群中,群内有很多热心的小伙伴,但是前提是希望你已经阅读了文档中的所有内容
67
+ * 你也可以请作者为你解答,当然我不是免费的
68
+
69
+ ![img.png](Files/image/wechat.png)
70
+
71
+ ## 目录结构
72
+
73
+
74
+ ├── common // 配置
75
+ │ ├── conf.yaml // 公共配置
76
+ │ ├── setting.py // 环境路径存放区域
77
+ ├── data // 测试用例数据
78
+ ├── File // 上传文件接口所需的文件存放区域
79
+ ├── logs // 日志层
80
+ ├── report // 测试报告层
81
+ ├── test_case // 测试用例代码
82
+ ├── utils // 工具类
83
+ │ └── assertion
84
+ │ └── assert_control.py // 断言
85
+ │ └── assert_type.py // 断言类型
86
+ │ └── cache_process // 缓存处理模块
87
+ │ └── cacheControl.py
88
+ │ └── redisControl.py
89
+ │ └── logUtils // 日志处理模块
90
+ │ └── logControl.py
91
+ │ └── logDecoratrol.py // 日志装饰器
92
+ │ └── runTimeDecoratrol.py // 统计用例执行时长装饰器
93
+ │ └── mysqlUtils // 数据库模块
94
+ │ └── get_sql_data.py
95
+ │ └── mysqlControl.py
96
+ │ └── noticUtils // 通知模块
97
+ │ └── dingtalkControl.py // 钉钉通知
98
+ │ └── feishuControl.py // 飞书通知
99
+ │ └── sendmailControl.py // 邮箱通知
100
+ │ └── weChatSendControl.py // 企业微信通知
101
+ │ └── otherUtils // 其他工具类
102
+ │ └── allureDate // allure封装
103
+ │ └── allure_report_data.py // allure报告数据清洗
104
+ │ └── allure_tools.py // allure 方法封装
105
+ │ └── error_case_excel.py // 收集allure异常用例,生成excel测试报告
106
+ │ └── localIpControl.py // 获取本地IP
107
+ │ └── threadControl.py // 定时器类
108
+ │ └── readFilesUtils // 文件操作
109
+ │ └── caseAutomaticControl.py // 自动生成测试代码
110
+ │ └── clean_files.py // 清理文件
111
+ │ └── excelControl.py // 读写excel
112
+ │ └── get_all_files_path.py // 获取所有文件路径
113
+ │ └── get_yaml_data_analysis.py // yaml用例数据清洗
114
+ │ └── regularControl.py // 正则
115
+ │ └── yamlControl.py // yaml文件读写
116
+ │ └── recordingUtils // 代理录制
117
+ │ └── mitmproxyContorl.py
118
+ │ └── requestsUtils
119
+ │ └── dependentCase.py // 数据依赖处理
120
+ │ └── requestControl.py // 请求封装
121
+ │ └── timeUtils
122
+ ├── Readme.md // help
123
+ ├── pytest.ini
124
+ ├── run.py // 运行入口
125
+
126
+
127
+ ## 依赖库
128
+
129
+
130
+ allure-pytest==2.9.45
131
+ allure-python-commons==2.9.45
132
+ atomicwrites==1.4.0
133
+ attrs==21.2.0
134
+ certifi==2021.10.8
135
+ cffi==1.15.0
136
+ charset-normalizer==2.0.7
137
+ colorama==0.4.4
138
+ colorlog==6.6.0
139
+ cryptography==36.0.0
140
+ DingtalkChatbot==1.5.3
141
+ execnet==1.9.0
142
+ Faker==9.8.3
143
+ idna==3.3
144
+ iniconfig==1.1.1
145
+ jsonpath==0.82
146
+ packaging==21.3
147
+ pluggy==1.0.0
148
+ py==1.11.0
149
+ pycparser==2.21
150
+ PyMySQL==1.0.2
151
+ pyOpenSSL==21.0.0
152
+ pyparsing==3.0.6
153
+ pytest==6.2.5
154
+ pytest-forked==1.3.0
155
+ pytest-xdist==2.4.0
156
+ python-dateutil==2.8.2
157
+ PyYAML==6.0
158
+ requests==2.26.0
159
+ six==1.16.0
160
+ text-unidecode==1.3
161
+ toml==0.10.2
162
+ urllib3==1.26.7
163
+ xlrd==2.0.1
164
+ xlutils==2.0.0
165
+ xlwt==1.3.0
166
+
167
+ ## 安装教程
168
+
169
+ 首先,执行本框架之后,需要搭建好 python、jdk、 allure环境
170
+
171
+ 搭建python教程:[http://c.biancheng.net/view/4161.html](http://c.biancheng.net/view/4161.html)
172
+
173
+ 搭建jdk环境:[https://www.cnblogs.com/zll-wyf/p/15095664.html](https://www.cnblogs.com/zll-wyf/p/15095664.html)
174
+
175
+ 安装allure:[https://blog.csdn.net/m0_49225959/article/details/117194318](https://blog.csdn.net/m0_49225959/article/details/117194318)
176
+
177
+
178
+ 如上环境如都搭建好,则安装本框架的所有第三方库依赖,执行如下命令
179
+
180
+ pip3 install -r requirements.txt
181
+
182
+
183
+ ![img.png](Files/image/安装异常.png)
184
+
185
+ 如果在安装过程中出现如下 Could not find a version 类似的异常, 不用担心,可能是因为你安装的python环境
186
+ 版本和我不一致导致的,直接 pip install 库名称,不指定版本安装就可以了。
187
+
188
+ 如上方截图说没有找到 asgiref==3.5.1,报错的意思是,没有找到3.5.1这个版本,那么直接控制台输入 pip3 install asgiref 进行安装即可
189
+
190
+
191
+ ## 接口文档
192
+
193
+ 这里非常感谢一位安卓的朋友,给我推荐了开源的接口文件,框架中会针对开源接口中的登录、个人信息、收藏(新增、查看、修改、删除)等功能,编写结果自动化案例
194
+ 下方是接口文档地址,大家可以自行查看(因为开源的接口,里面有些逻辑性的功能,如修改被删除的网址接口并没有过多的做判断,
195
+ 因此用例中只写了一些基础的场景,仅供大家参考。)
196
+ [https://wanandroid.com/blog/show/2](https://wanandroid.com/blog/show/2)
197
+
198
+ ## 如何创建用例
199
+
200
+ ### 创建用例步骤
201
+ 1、在data文件夹下方创建相关的yaml用例
202
+
203
+ 2、写完之后,需要执行 utils\readFilesUtils\caseAutomaticControl.py 这个文件,生成自动化代码
204
+
205
+ 3、执行caseAutomaticControl.py文件之后,会发现,在test_case层新增该条用例的对应代码,可直接执行该用例调试
206
+
207
+ 4、注意,如果生成对应的测试代码之后,期间有更改过yaml用例中的内容,需要重新生成代码,必现因为更改yaml用例之后导致运行失败
208
+
209
+ 5、当所有接口都编写好之后,可以直接运行run.py主程序,执行所有自动化接口
210
+
211
+
212
+ 下面我们来看一下,如何创建用例
213
+
214
+ ### 用例中相关字段的介绍
215
+
216
+ ![img.png](Files/image/case_data.png)
217
+
218
+ 上方截图,就是一个用例中需要维护的相关字段,下面我会对每个字段的作用,做出解释。
219
+
220
+ ![img.png](Files/image/case_detail.png)
221
+
222
+ ### 如何发送get请求
223
+ 上方了解了用例的数据结构之后,下面我们开始编写第一个get请求方式的接口。
224
+ 首先,开始编写项目之后,我们在 conf.yaml 中配置项目的域名
225
+
226
+ ![img.png](Files/image/conf.png)
227
+
228
+ 域名配置好之后,我们来编写测试用例,在 data 文件下面,创建一个名称为
229
+ collect_tool_list.yaml 的用例文件,请求/lg/collect/usertools/json这个收藏网址列表接口,所有接口的详细信息,可以在接口文档中查看,下方不在做赘述
230
+
231
+ 接口文档:[https://wanandroid.com/blog/show/2](https://wanandroid.com/blog/show/2)
232
+
233
+ # 公共参数
234
+ case_common:
235
+ allureEpic: 开发平台接口
236
+ allureFeature: 收藏模块
237
+ allureStory: 收藏网址列表接口
238
+
239
+ collect_tool_list_01:
240
+ host: ${{host()}}
241
+ url: /lg/collect/usertools/json
242
+ method: GET
243
+ detail: 查看收藏网址列表接口
244
+ headers:
245
+ Content-Type: multipart/form-data;
246
+ # 这里cookie的值,写的是存入缓存的名称
247
+ cookie: login_cookie
248
+ # 请求的数据,是 params 还是 json、或者file、data
249
+ requestType: data
250
+ # 是否执行,空或者 true 都会执行
251
+ is_run:
252
+ data:
253
+ pageNum: 1
254
+ pageSize: 10
255
+ # 是否有依赖业务,为空或者false则表示没有
256
+ dependence_case: False
257
+ # 依赖的数据
258
+ dependence_case_data:
259
+ assert:
260
+ # 断言接口状态码
261
+ errorCode:
262
+ jsonpath: $.errorCode
263
+ type: ==
264
+ value: 0
265
+ AssertType:
266
+ sql:
267
+
268
+ get请求我们 requestType 写的是 params ,这样发送请求时,我们会将请求参数拼接中url中,最终像服务端发送请求的地址格式会为:
269
+
270
+ 如: ${{host()}}/lg/collect/usertools/json?pageNum=1&pageSize=10
271
+
272
+ ### 如何发送post请求
273
+
274
+ # 公共参数
275
+ case_common:
276
+ allureEpic: 开发平台接口
277
+ allureFeature: 收藏模块
278
+ allureStory: 收藏网址接口
279
+
280
+ collect_addtool_01:
281
+ host: ${{host()}}
282
+ url: /lg/collect/addtool/json
283
+ method: POST
284
+ detail: 新增收藏网址接口
285
+ headers:
286
+ Content-Type: multipart/form-data;
287
+ # 这里cookie的值,写的是存入缓存的名称
288
+ cookie: login_cookie
289
+ # 请求的数据,是 params 还是 json、或者file、data
290
+ requestType: data
291
+ # 是否执行,空或者 true 都会执行
292
+ is_run:
293
+ data:
294
+ name: 自动化生成收藏网址${{random_int()}}
295
+ link: https://gitee.com/yu_xiao_qi/pytest-auto-api2
296
+ # 是否有依赖业务,为空或者false则表示没有
297
+ dependence_case: False
298
+ # 依赖的数据
299
+ dependence_case_data:
300
+ assert:
301
+ # 断言接口状态码
302
+ errorCode:
303
+ jsonpath: $.errorCode
304
+ type: ==
305
+ value: 0
306
+ AssertType:
307
+ sql:
308
+
309
+ 这里post请求,我们需要请求的数据格式是json格式的,那么requestType 则填写为json格式。
310
+ 包括 PUT/DELETE/HEAD 请求的数据格式都是一样的,唯一不同的就是需要配置 reuqestType,
311
+ 如果需要请求的参数是json格式,则requestType我们就填写json,如果是url拼接的形式,我们就填写 params
312
+
313
+ ### 如何测试上传文件接口
314
+
315
+ 首先,我们将所有需要测试的文件,全部都放在 files 文件夹中
316
+ ![img.png](Files/image/files.png)
317
+
318
+ requestType: file
319
+ # 是否执行,空或者 true 都会执行
320
+ is_run:
321
+ data:
322
+ file:
323
+ xxx: 排入水体名.png
324
+
325
+
326
+ 在yaml文件中,我们需要注意两个地方,主要是用例中的requestType、和 filename 字段:
327
+
328
+ * requestType: 上传文件,我们需要更改成 file
329
+ * file: 上传文件中,新增一个file关键字,在下方传我们需要的数据
330
+ * file_name: 首先,这个xxx是我们公司接口定义的上传文件的参数,排入水体名.png 这个是我们放在Files这个文件夹下方的文件名称
331
+ 程序在执行的时候,会判断如果你的requestType为 file的时候,则会去执行file下方的参数,然后取到文件名称直接去执行用例
332
+
333
+ ### 上传文件接口,即需要上传文件,又需要上传其他参数
334
+ requestType: file
335
+ # 是否执行,空或者 true 都会执行
336
+ is_run:
337
+ data:
338
+ file:
339
+ file_name: 排入水体名.png
340
+ data:
341
+ is_upload: 0
342
+ params:
343
+ collect: false
344
+
345
+ 上方的这个案例,请求参数即上传了文件,又上传了其他参数
346
+
347
+ * 1、file: 这里下方上传的是文件参数
348
+ * 2、data: 这个data下方是该接口,除了文件参数,还需要上传其他的参数,这个参数会以json的方式传给服务端(如果没有其他参数,可以不用写这个)
349
+ * 3、params: 这个是除了文件参数以外的,上传的其他参数,这个参数是拼接在url后方的
350
+
351
+ ![img.png](Files/image/files_up.png)
352
+
353
+ 为了方便大家理解,上方将该参数,以postman的形式上传
354
+
355
+ ### 多业务逻辑,如何编写测试用例
356
+
357
+ 多业务这一块,我们拿个简单的例子举例,比如登录场景,在登陆之前,我们需要先获取到验证码。
358
+
359
+ ![img.png](Files/image/send_sms_code.png)
360
+
361
+ ![img.png](Files/image/login.png)
362
+
363
+ 首先,我们先创建一个 get_send_sms_code.yaml 的文件,编写一条发送验证码的用例
364
+
365
+ # 公共参数
366
+ case_common:
367
+ allureEpic: 盲盒APP
368
+ allureFeature: 登录模块
369
+ allureStory: 获取登录验证码
370
+
371
+ send_sms_code_01:
372
+ host: ${{host()}}
373
+ url: /mobile/sendSmsCode
374
+ method: POST
375
+ detail: 正常获取登录验证码
376
+ headers:
377
+ appId: '23132'
378
+ masterAppId: masterAppId
379
+ Content-Type: application/json;charset=UTF-8
380
+ # 请求的数据,是 params 还是 json、或者file
381
+ requestType: json
382
+ # 是否执行,空或者 true 都会执行
383
+ is_run:
384
+ data:
385
+ phoneNumber: "180****9278"
386
+ # 是否有依赖业务,为空或者false则表示没有
387
+ dependence_case: False
388
+ # 依赖的数据
389
+ dependence_case_data:
390
+ assert:
391
+ code:
392
+ jsonpath: $.code
393
+ type: ==
394
+ value: '00000'
395
+ AssertType:
396
+ success:
397
+ jsonpath: $.success
398
+ type: ==
399
+ value: true
400
+ AssertType:
401
+
402
+ sql:
403
+
404
+ 编写好之后,我们在创建一个 login.yaml 文件
405
+
406
+ # 公共参数
407
+ case_common:
408
+ allureEpic: 盲盒APP
409
+ allureFeature: 登录模块
410
+ allureStory: 登录
411
+
412
+ login_02:
413
+ host: ${{host()}}
414
+ url: /login/phone
415
+ method: POST
416
+ detail: 登录输入错误的验证码
417
+ headers:
418
+ appId: '23132'
419
+ masterAppId: masterAppId
420
+ Content-Type: application/json;charset=UTF-8
421
+ # 请求的数据,是 params 还是 json、或者file
422
+ requestType: json
423
+ # 是否执行,空或者 true 都会执行
424
+ is_run:
425
+ data:
426
+ phoneNumber: 18014909278
427
+ code: $cache{login_02_v_code}
428
+ # 是否有依赖业务,为空或者false则表示没有
429
+ dependence_case: True
430
+ # 依赖的数据
431
+ dependence_case_data:
432
+ - case_id: send_sms_code_01
433
+ dependent_data:
434
+ - dependent_type: response
435
+ jsonpath: $.code
436
+ set_cache: login_02_v_code
437
+
438
+ assert:
439
+ code:
440
+ jsonpath: $.code
441
+ type: ==
442
+ value: '00000'
443
+ AssertType:
444
+ sql:
445
+
446
+ 其中处理多业务的核心区域,主要在这里:
447
+
448
+ dependence_case: True
449
+ # 依赖的数据
450
+ dependence_case_data:
451
+ - case_id: send_sms_code_01
452
+ dependent_data:
453
+ - dependent_type: response
454
+ jsonpath: $.code
455
+ set_cache: login_02_v_code
456
+
457
+ 首先,我们 dependence_case 需要设置成 True,并且在下面的 dependence_case_data 中设计相关依赖的数据。
458
+
459
+ * case_id:上方场景中,我们登录需要先获取验证码,因此依赖的case_id 就是发送短信验证码的 case_id :send_sms_code_01
460
+ * dependent_type:我们依赖的是获取短信验证码接口中的响应内容,因此这次填写的是 response, 同样也支持request、sql等方式
461
+ * jsonpath: 通过jsonpath 提取方式,提取到短信验证码中的验证码内容(jsonpath规格和jmeter中的json在线提取器的规则一致)
462
+ * set_cache:拿到验证码之后,这里我们可以自定义一个缓存名称 如: login_02_v_code,程序中会将你所提取到的验证码存入缓存中,
463
+ 因此我们在这条用例的 data 中,有个code 的参数,值设置成 $cache{login_02_v_code},程序中会将我们 send_sms_code_01中的验证码给提取出来,
464
+ 通过 $cache{login_02_v_code} 语法获取到。
465
+
466
+ * 注意,定义缓存名称,每个公司最好定义一个规范,比如 当前这条 case_id名称 + 缓存自定义名称,如 login_02_v_code, case_id 是唯一的,
467
+ 这样可以避免不同用例之间缓存名称重复的问题,导致无法获取到对应的缓存数据
468
+
469
+ ### 多业务逻辑,需要依赖同一个接口中的多个数据
470
+
471
+ dependence_case_data:
472
+ - case_id: send_sms_code_01
473
+ dependent_data:
474
+ # 提取接口响应的code码
475
+ - dependent_type: response
476
+ jsonpath: $.code
477
+ set_cache: v_code
478
+ # 提取接口响应的accessToken
479
+ - dependent_type: response
480
+ jsonpath: $.data.accessToken
481
+ # 替换请求头中的accessToken
482
+ set_cache: accessToken
483
+
484
+
485
+ 如上方示例,可以添加多个 dependent_type
486
+
487
+ ### 多业务逻辑,需要依赖不同接口的数据
488
+
489
+ 假设我们需要获取 send_sms_code_01、get_code_01两个接口中的数据,用例格式如下
490
+
491
+ dependence_case: True
492
+ # 依赖的数据
493
+ dependence_case_data:
494
+ - case_id: send_sms_code_01
495
+ dependent_data:
496
+ # 提取接口响应的code码
497
+ - dependent_type: response
498
+ jsonpath: $.code
499
+ set_cache: v_code
500
+ - case_id: get_code_01
501
+ dependent_data:
502
+ # 提取接口响应的code码
503
+ - dependent_type: response
504
+ jsonpath: $.code
505
+ set_cache: v_code2
506
+
507
+ ### 请求参数为路径参数
508
+
509
+
510
+ collect_delete_tool_01:
511
+ host: ${{host()}}
512
+ url: /lg/collect/deletetool/json/$cache{collect_delete_tool_01_id}
513
+ method: POST
514
+ detail: 正常删除收藏网站
515
+ headers:
516
+ Content-Type: multipart/form-data;
517
+ # 这里cookie的值,写的是存入缓存的名称
518
+ cookie: $cache{login_cookie}
519
+ # 请求的数据,是 params 还是 json、或者file、data
520
+ requestType: None
521
+ # 是否执行,空或者 true 都会执行
522
+ is_run:
523
+ data:
524
+ dependence_case: True
525
+ # 依赖的数据
526
+ dependence_case_data:
527
+ - case_id: collect_addtool_01
528
+ dependent_data:
529
+ - dependent_type: response
530
+ jsonpath: $.data.id
531
+ set_cache: collect_delete_tool_01_id
532
+
533
+ 以上方实例,我们的参数是在url中的,因此我们可以通过 dependence_case 获取到我们需要依赖的数据,
534
+ 将本条用例需要用到的数据存入缓存,从而在 /lg/collect/deletetool/json/$cache{collect_delete_tool_01_id} 直接调用缓存数据即可
535
+
536
+ ### 将当前用例的请求值或者响应值存入缓存中
537
+
538
+ 有些小伙伴之前有反馈过,比如想要做数据库的断言,但是这个字段接口没有返回,我应该怎么去做校验呢?
539
+ 程序中提供了current_request_set_cache这个关键字,可以将当前这条用例的请求数据 或者响应数据 给直接存入缓存中
540
+ 如下案例所示:
541
+
542
+ current_request_set_cache:
543
+ # 1、response 从响应中提取内容 2、request从请求中提取内容
544
+ - type: response
545
+ jsonpath: $.data.data.[0].id
546
+ # 自定义的缓存名称
547
+ name: test_query_shop_brand_list_02_id
548
+
549
+ ### 请求用例时参数需要从数据库中提取
550
+ ![img.png](Files/image/sql_params.png)
551
+ 如上图所示,用例中的 dependent_type 需要填写成 sqlData。
552
+ 当你的依赖类型为 sqlData 数据库的数据时,那么下方就需要再加一个 setup_sql 的参数,下方填写需要用到的sql语句
553
+
554
+ 注意case_id: 因为程序设计原因,通常情况下,我们关联的业务,会发送接口请求,但是如果我们依赖的是sql的话,
555
+ 是不需要发送请求的,因此我们如果是从数据库中提取数据作为参数的话,我们case_id 需要写self ,方便程序中去做区分
556
+
557
+ ApplyVerifyCode_01:
558
+ host: ${{host}}
559
+ url: /api/v1/merchant/apply/verifyCode
560
+ method: GET
561
+ detail: 校验已经审核通过的供应商手机号码
562
+ headers:
563
+ Content-Type: application/json;charset=UTF-8
564
+ # 请求的数据,是 params 还是 json、或者file、data
565
+ requestType: params
566
+ # 是否执行,空或者 true 都会执行
567
+ is_run:
568
+ data:
569
+ mobile: 18811111111
570
+ authCode: 123456
571
+ name: $cache{username}
572
+ # 是否有依赖业务,为空或者false则表示没有
573
+ dependence_case: True
574
+ # 依赖的数据
575
+ dependence_case_data:
576
+ - case_id: self
577
+ dependent_data:
578
+ - dependent_type: sqlData
579
+ jsonpath: $.username
580
+ set_cache: username
581
+
582
+ assert:
583
+ code:
584
+ jsonpath: $.code
585
+ type: ==
586
+ value: 200
587
+ AssertType:
588
+ applyId:
589
+ jsonpath: $.data[0].applyId
590
+ type: ==
591
+ value: $.applyId
592
+ AssertType: SQL
593
+ applyStatus:
594
+ jsonpath: $.data[0].applyStatus
595
+ type: ==
596
+ value: $.applyStatus
597
+ AssertType: SQL
598
+
599
+ sql:
600
+ - select a.apply_id as applyId, a.to_status as applyStatus, a.sub_biz_type as subBizType, a.operator_name as operatorName, a.operator_user_id as operatorUserId, b.apply_type as applyType from test_obp_midware.apply_operate_log as a inner join test_obp_midware.apply as b on a.apply_id = b.id where b.id = $json($.data[0].applyId)$ order by a.id desc limit 1;
601
+ setup_sql:
602
+ - SELECT * FROM test_obp_user.user_biz_info where user_id = '300000405'
603
+
604
+
605
+ ### 用例中需要依赖登录的token,如何设计
606
+
607
+ 首先,为了防止重复请求调用登录接口,pytest中的 conftest.py 提供了热加载机制,看上方截图中的代码,我们需要在 conftest.py 提前编写好登录的代码。
608
+
609
+
610
+ 如上方代码所示,我们会先去读取login.yaml文件中的用例,然后执行获取到响应中的token,然后 编写 Cache('work_login_init').set_caches(token),将token写入缓存中,其中 work_login_init 是缓存名称。
611
+
612
+ 编写好之后,我们会在 requestControl.py 文件中,读取缓存中的token,如果该条用例需要依赖token,则直接进行内容替换。
613
+
614
+ @pytest.fixture(scope="session", autouse=True)
615
+ def work_login_init():
616
+ """
617
+ 获取登录的cookie
618
+ :return:
619
+ """
620
+ url = "https://www.wanandroid.com/user/login"
621
+ data = {
622
+ "username": 18800000001,
623
+ "password": 123456
624
+ }
625
+ headers = {'Content-Type': 'application/x-www-form-urlencoded'}
626
+ # 请求登录接口
627
+ res = requests.post(url=url, data=data, verify=True, headers=headers).json()
628
+ token = res['response']['token']
629
+
630
+ CacheHandler.update_cache(cache_name='work_login_init', value=token)
631
+
632
+ 这里在编写用例的时候,token 填写我们所编写的缓存名称即可。
633
+ ![img.png](Files/image/img.png)
634
+
635
+ ### 用例中依赖cookie如何设计
636
+
637
+ ![img.png](Files/image/cookie.png)
638
+
639
+ 首先我们在conftest.py中编写获取cookie的方法
640
+
641
+ @pytest.fixture(scope="session", autouse=True)
642
+ def work_login_init():
643
+ """
644
+ 获取登录的cookie
645
+ :return:
646
+ """
647
+ url = "https://www.wanandroid.com/user/login"
648
+ data = {
649
+ "username": 18800000001,
650
+ "password": 123456
651
+ }
652
+ headers = {'Content-Type': 'application/x-www-form-urlencoded'}
653
+ # 请求登录接口
654
+ res = requests.post(url=url, data=data, verify=True, headers=headers)
655
+ response_cookie = res.cookies
656
+
657
+ cookies = ''
658
+ for k, v in response_cookie.items():
659
+ _cookie = k + "=" + v + ";"
660
+ # 拿到登录的cookie内容,cookie拿到的是字典类型,转换成对应的格式
661
+ cookies += _cookie
662
+ # 将登录接口中的cookie写入缓存中,其中login_cookie是缓存名称
663
+ CacheHandler.update_cache(cache_name='login_cookie', value=cookies)
664
+
665
+ 和token一样,我们如果用例的请求头中依赖cookie, cookie中的值,直接写我们存入缓存中的名称即可
666
+
667
+ headers:
668
+ Content-Type: multipart/form-data;
669
+ # 这里cookie的值,写的是存入缓存的名称
670
+ cookie: $cache{login_cookie}
671
+
672
+ ### 用例中如何生成随机数据
673
+
674
+ 比如我们有些特殊的场景,可能会涉及到一些定制化的数据,每次执行数据,需要按照指定规则随机生成。
675
+
676
+ ![img.png](Files/image/randoms.png)
677
+
678
+ 如上图所示,我们用例中的 reason 审核原因后方,需要展示审核的当前时间。那么我们首先需要封装一个获取当前时间的方法
679
+
680
+ ![img.png](Files/image/regular.png)
681
+
682
+ 那么我们就在 regularControl.py 文件中,编写 get_time 的方法。编写好之后,在用例中编写规则如下:
683
+
684
+ reason: 审核时间${{get_time()}}
685
+ 使用 " ${{函数名称()}}" 的方法,程序调用时,会生成当前时间。在regularControl.py 文件中,我还封装了一些常用的随机数,
686
+ 如随机生成男生姓名、女生姓名、身份证、邮箱、手机号码之类的,方便大家使用。
687
+ 如,随机生成邮箱,我们在用例中编写的格式为 " ${{get_email()}} " 。
688
+
689
+ 其他所需随机生成的数据,可在文件中自行添加。
690
+
691
+ ### 自动化函数传递参数
692
+
693
+ 首先同样和上方一样,创建一个随机生成的方法,改方法支持接收参数
694
+
695
+ @classmethod
696
+ def random_int(cls, min_num, max_num):
697
+ """
698
+ 随机生成指定范围的随机数
699
+ @param min_num: 最小数字
700
+ @param max_num: 最大数字
701
+ @return:
702
+ """
703
+ num = random.randint(int(min_num), int(max_num))
704
+ return num
705
+
706
+
707
+ 在用例中,假设我们需要获取一个 1-10之间的随机数,那么我们直接这样调用该数据即可
708
+
709
+ reason: {{random_int(1, 10)}}
710
+
711
+ ### 断言http响应状态码
712
+
713
+ 相信有些小伙伴在做接口测试的过程中,有部分接口是没有任何响应的,那么在没有响应数据的情况下
714
+ 我们就只能通过 http的状态码去判断这条用例是否通过,我们可以这样写
715
+
716
+ assert:
717
+ status_code: 200
718
+
719
+ 我们直接在assert下方添加一个 status_code 参数,状态码我们判断其为 200
720
+
721
+ ### 用例中添加等待时间
722
+
723
+ 程序中可以设定接口请求之后,等待时长,假设A接口依赖B接口的业务,A接口请求完时,我们需要让他等待几秒钟
724
+ 再次请求B接口,这样的话,我们可以使用sleep关键字
725
+
726
+ sleep: 3
727
+
728
+
729
+ ### 断言类型
730
+ 下放截图中,是所有断言支持的类型
731
+
732
+ ![img.png](Files/image/assert_type.png)
733
+
734
+
735
+ ### 用例中如何进行接口断言和数据库断言
736
+
737
+ 假设现在我需要测试一个报表统计的数据,该接口返回了任务的处理时长 和 处理数量。功能如下截图所示:
738
+
739
+ ![img.png](Files/image/question_coun.png)
740
+
741
+ 假设下方是我们拿到接口响应的数据内容:
742
+
743
+ {"code": 200, "times": 155.91, "counts": 9}
744
+
745
+ 这个时候,我们需要判断该接口返回的数据是否正确,就需要编写sql,对响应内容进行校验。
746
+
747
+ ![img.png](Files/image/sql.png)
748
+
749
+ 因此我们编写了如上sql,查出对应的数据,那么用例中编写规则如下,下方我们分别断言了两个内容,一个是对接口的响应code码进行断言,一个是断言数据库中的数据。
750
+
751
+
752
+ assert:
753
+ code:
754
+ jsonpath: $.code
755
+ type: ==
756
+ value: 200
757
+ # 断言接口响应时,可以为空
758
+ AssertType:
759
+ do_time:
760
+ # jsonpath 拿到接口响应的数据
761
+ jsonpath: $.times
762
+ type: ==
763
+ # sql 查出来的数据,是字典类型的,因此这里是从字段中提取查看出来的字段
764
+ value: $.do_time
765
+ # 断言sql的时候,AssertType 的值需要填写成 SQL
766
+ AssertType: SQL
767
+ question_counts:
768
+ jsonpath: $.counts
769
+ type: ==
770
+ #
771
+ value: $.question_counts
772
+ # 断言sql的时候,AssertType 的值需要填写成 SQL
773
+ AssertType: SQL
774
+ sql:
775
+ - select * from test_goods where shop_id = 515
776
+
777
+ 我们分别对用例的数据进行讲解,首先是响应断言, 编写规则如下
778
+
779
+ code:
780
+ # 通过jsonpath获取接口响应中的code {"code": 200, "times": 155.91, "counts": 9}
781
+ jsonpath: $.code
782
+ type: ==
783
+ value: 200
784
+ # 断言接口响应时,可以为空
785
+ AssertType:
786
+
787
+ 下面是对sql进行断言
788
+
789
+ question_counts:
790
+ # 断言接口响应的问题上报数量counts {"code": 200, "times": 155.91, "counts": 9}
791
+ jsonpath: $.counts
792
+ type: ==
793
+ # 查询sql,我们数据库查到的数据是一个字段,数据是这样的:{question_counts: 13, do_time: 1482.70}, 这里我们通过 jsonpath获取question_counts
794
+ value: $.question_counts
795
+ # 断言sql的时候,AssertType 的值需要填写成 SQL
796
+ AssertType: SQL
797
+ sql:
798
+ - SELECT round( sum(( UNIX_TIMESTAMP( filing_time )- UNIX_TIMESTAMP( report_time )) / 60 ) / 60, 2 ) AS do_time, count( id ) AS question_counts FROM fl_report_info WHERE state IN ( 1, 3 )
799
+
800
+ 有些细心的小伙伴会发现,我们的sql,是列表类型的。这样就意味这,我们的sql可以同时编写多条,这样会对不会编写多表联查的小伙伴比较友好,可以进行单表查询,获取我们需要的数据。
801
+
802
+ sql:
803
+ - select * from users;
804
+ - select * from goods;
805
+
806
+ ### 使用teardown功能,做数据清洗
807
+
808
+ 通常情况下,我们做自动化所有新增的数据,我们测试完成之后,都需要讲这些数据删除,程序中支持两种写法
809
+ 一种是直接调用接口进行数据删除。另外一种是直接删除数据库中的数据,建议使用第一种,直接调用业务接口删除对应的数据
810
+
811
+
812
+ 1、下面我们先来看看第一种删除方式,teardown的功能,因为需要兼容较多的场景,因此使用功能上相对也会比较复杂
813
+ 需要小伙伴们一个一个去慢慢的理解。
814
+
815
+ 下面为了方便大家对于teardown功能的理解,我会针对不同的场景进行举例:
816
+
817
+ * 假设现在我们有一个新增接口,写完之后,我们需要先调用查询接口获取到新增接口的ID,然后再进行删除
818
+ 那么此时会设计到两个场景,首先执行新增接口ID,然后再拿到响应(这里有个逻辑上的先后关系,查询接口,是先发送请求,在提取数据)
819
+ 获取到查询的ID之后,我们在执行删除,删除的话,我们是直接发送请求
820
+
821
+ 那么针对这个场景,我们就需要有个关键字去做区分,什么场景下先发送请求,什么场景下后发送请求,下面我们来看一下案例,方便大家理解
822
+
823
+ teardown:
824
+ # 查看品牌审核列表,获取品牌的apply_id
825
+ - case_id: query_apply_list_01
826
+ # 注意这里我们是先发送请求,在拿到自己响应的内容,因此我们这个字段需要写param_prepare
827
+ param_prepare:
828
+ # 因为是获取自己的响应内容,我们dependent_type需要写成 self_response
829
+ - dependent_type: self_response
830
+ # 通过jsonpath的方法,获取query_apply_list_01这个接口的响应内容
831
+ jsonpath: $.data.data.[0].applyId
832
+ # 将内容存入缓存,这个是自定义的缓存名称
833
+ set_cache: test_brand_apply_initiate_apply_01_applyId
834
+
835
+ # 支持同时存多个数据,只会发送一次请求
836
+ - dependent_type: self_response
837
+ jsonpath: $.data.data.[0].brandName
838
+ set_cache: test_brand_apply_initiate_apply_01_brandName
839
+
840
+ # 删除
841
+ - case_id: delete_01
842
+ # 删除的话,我们是直接发送请求的,因此我们这里写 send_request
843
+ send_request:
844
+ # 我们上方已经拿到了ID,并且将ID存入缓存中,因此这里依赖数据的类型为cache,直接从缓存中提取
845
+ - dependent_type: cache
846
+ # 这个是缓存名称
847
+ cache_data: test_brand_apply_initiate_apply_01_applyId
848
+ # 通过relace_key 去替换 delete_01 中的 applyID参数
849
+ replace_key: $.data.applyId
850
+
851
+ * 那么有些小伙伴会在想,同样我们以上方的接口场景为例,有些小伙伴会说,我公司的新增的接口,有直接返回ID,不需要调用查询接口
852
+ 程序中当然也支持这种场景,我们只需要这么编写
853
+
854
+ - case_id: process_apply_01
855
+ # 同样这么写 send_request
856
+ send_request:
857
+ # 这里我们从响应中获取
858
+ - dependent_type: response
859
+ # 通过jsonpath的方式,获取响应的内容
860
+ jsonpath: $.data.id
861
+ # 使用repalce_key进行替换
862
+ replace_key: $.data.applyId
863
+
864
+ * 程序中也支持从请求里面获取内容,编写规则如下
865
+
866
+ - case_id: process_apply_01
867
+ # 同样这么写 send_request
868
+ send_request:
869
+ # 这里我们从响应中获取
870
+ - dependent_type: request
871
+ # 通过jsonpath的方式,获取请求的内容
872
+ jsonpath: $.data.id
873
+ # 使用repalce_key进行替换
874
+ replace_key: $.data.applyId
875
+
876
+ ### 使用 teardown_sql 后置sql删除数据
877
+ 如一些特殊场景,业务上并没有提供删除接口,我们也可以直接通过 sql去讲对应的sql删除
878
+ teardown_sql:
879
+ - delete * from xxx
880
+ - delete * from xxx
881
+
882
+ ### 自动生成test_case层代码
883
+
884
+ 小伙伴们在编写好 yaml 用例之后,可以直接执行 caseAutomaticControl.py ,会跟你设计的测试用例,生成对应的代码。
885
+
886
+ ![img.png](Files/image/write_test_case.png)
887
+
888
+ ### 发送钉钉通知通知
889
+
890
+ ![img.png](Files/image/dingding.png)
891
+
892
+ ### 发送企业微信通知
893
+
894
+ ![img.png](Files/image/wechart.png)
895
+
896
+ ### 日志打印装饰器
897
+
898
+ ![img.png](Files/image/log.png)
899
+
900
+ 在requestControl.py中,我单独封装了一个日志装饰器,需要的小伙伴可以不用改动代码,直接使用,如果不需要,直接注释,或者改成False。控制台将不会有日志输出
901
+
902
+ ### 统计用例运行时长
903
+ ![img.png](Files/image/run_times.png)
904
+
905
+ 同样,这里封装了一个统计用例运行时长的装饰器,使用改装饰器前,需要先进行导包
906
+
907
+ from utils.logUtils.runTimeDecoratorl import execution_duration
908
+ 导入之后,调用改装饰器,装饰器中填写的用例执行时长,以毫秒为单位,如这里设置的2000ms,那么如果该用例执行大于2000ms,则会输出一条告警日志。
909
+
910
+ @execution_duration(2000)
911
+
912
+ ### 生成allure报告
913
+
914
+ 我们直接运行主程序 run.py ,运行完成之后,就可以生成漂亮的allure报告啦~
915
+
916
+ ![img.png](Files/image/allure.png)
917
+
918
+ ![img.png](Files/image/allure2.png)
919
+
920
+ ### 其他
921
+
922
+ 本框架为2.0升级版本,升级之后的功能,现在基本上都是在yaml中维护用例,无需测试人员编写代码,
923
+ 和 1.0版本的区别在于,1.0版本还需要测试人员手动编写多业务逻辑的代码,需要有一定基础编码的能力
924
+
925
+ 但是1.0版本,同样也可以自动生成代码,yaml中维护数据,对相对简单,如果偏于yaml简单维护的同学,可以切换查看1.0分支
926
+ 下方是1.0分支的操作文档:[点我查看](https://blog.csdn.net/weixin_43865008/article/details/121903028?spm=1001.2014.3001.5502)
927
+
928
+ *******************************************************
929
+
930
+ 以上便是整个框架的使用说明,这个框架属于个人业余时间开发,大家如果在使用中遇到什么问题,或者有相关建议,可以随时反馈给我,
931
+ _框架内容会随着大家的反馈,持续更新!邮箱地址:1602343211@qq.com
932
+
933
+ 如果觉得框架有帮助到你,麻烦收藏一下哦~~谢谢。:)
934
+
935
+ ## 版本更新记录
936
+ * V2.0.0(2022-04-07)
937
+ [重构] 新增多业务逻辑依赖处理,统一改成yaml文件中维护用例,无需编写代码,基于V1.0版本进行重构
938
+ * [查看更多记录点此查看](https://gitee.com/yu_xiao_qi/pytest-auto-api2/wikis/Home)
939
+
940
+ ## 赞赏
941
+
942
+ 如果这个库有帮助到你并且你很想支持库的后续开发和维护,那么你可以扫描下方二维码随意打赏我,我将不胜感激
943
+
944
+ ![img_1.png](Files/image/img_1.png) ![img_1.png](Files/image/weixin_pay.png)
945
+