har2pytest 1.0.0__py3-none-any.whl

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.
har2pytest/__init__.py ADDED
@@ -0,0 +1,36 @@
1
+ """
2
+ API工具包 - 用于从HAR文件生成API接口和测试用例
3
+
4
+ 主要功能:
5
+ 1. HAR文件解析
6
+ 2. API文件生成
7
+ 3. 测试用例生成
8
+ 4. Swagger文档更新
9
+ """
10
+
11
+ from .api_generator import APIGenerator
12
+ from .config import APIConfig
13
+ from .har_parser import HARParser
14
+ from .logger import get_logger, logger
15
+ from .swagger_handler import SwaggerHandler
16
+ from .testcase_generator import TestCaseGenerator
17
+ from .utils import (
18
+ format_headers_for_python,
19
+ format_parameter_value,
20
+ format_params_for_python,
21
+ parse_api_file,
22
+ )
23
+
24
+ __all__ = [
25
+ "APIConfig",
26
+ "HARParser",
27
+ "APIGenerator",
28
+ "TestCaseGenerator",
29
+ "SwaggerHandler",
30
+ "get_logger",
31
+ "logger",
32
+ "parse_api_file",
33
+ "format_parameter_value",
34
+ "format_headers_for_python",
35
+ "format_params_for_python",
36
+ ]
har2pytest/__main__.py ADDED
@@ -0,0 +1,294 @@
1
+ """
2
+ har2pytest 命令行入口
3
+ """
4
+
5
+ import argparse
6
+ import asyncio
7
+
8
+ from .api_generator import APIGenerator
9
+ from .config import APIConfig
10
+ from .har_generator import generate_api_files_from_har
11
+ from .har_parser import HARParser
12
+ from .logger import logger
13
+ from .swagger_handler import SwaggerHandler
14
+ from .testcase_generator import TestCaseGenerator
15
+
16
+
17
+ def main():
18
+ """
19
+ 主函数 - 支持多种命令行操作模式
20
+ """
21
+ # 初始化配置(通过 get_config 触发,会自动缓存)
22
+ APIConfig.get_config("BASE_URLS")
23
+
24
+ # 创建主解析器
25
+ parser = argparse.ArgumentParser(
26
+ prog="har2pytest",
27
+ description="har2pytest - HAR文件转pytest测试用例工具",
28
+ formatter_class=argparse.RawDescriptionHelpFormatter,
29
+ epilog="""示例用法:
30
+ # 从HAR文件生成API接口文件
31
+ har2pytest api api_request.har --output apis
32
+
33
+ # 从Swagger文档生成API接口文件
34
+ har2pytest swagger https://petstore.swagger.io/v2/api-docs
35
+
36
+ # 查看HAR文件摘要
37
+ har2pytest summary api_request.har
38
+
39
+ # 生成参数化测试用例
40
+ har2pytest testcase api_request.har --pattern list_query --mark test_4291
41
+
42
+ # 生成复杂场景测试用例
43
+ har2pytest testcase api_request.har --pattern complex_scenario --url /api/user/login --mark test_4295
44
+
45
+ # 批量生成测试用例
46
+ har2pytest testcase --pattern batch --api-files apis/mall_mobile_application --mark test_4295
47
+ """,
48
+ )
49
+
50
+ # 创建子命令解析器
51
+ subparsers = parser.add_subparsers(dest="command", help="可用命令")
52
+
53
+ # api 子命令
54
+ api_parser = subparsers.add_parser("api", help="从HAR文件生成API接口文件", description="从HAR文件生成API接口文件")
55
+ api_parser.add_argument("har_file", nargs="?", default="api_request.har", help="HAR文件路径")
56
+ api_parser.add_argument("--output", "-o", default=APIConfig.DEFAULT_API_DIR(), help="输出目录")
57
+ api_parser.add_argument("--overwrite", "-f", action="store_true", help="强制覆盖现有文件")
58
+
59
+ # summary 子命令
60
+ sum_parser = subparsers.add_parser(
61
+ "summary", help="显示HAR文件的API请求摘要", description="显示HAR文件的API请求摘要"
62
+ )
63
+ sum_parser.add_argument("har_file", help="HAR文件路径")
64
+
65
+ # testcase 子命令
66
+ tc_parser = subparsers.add_parser(
67
+ "testcase",
68
+ help="生成测试用例",
69
+ description="从HAR文件生成pytest测试用例",
70
+ formatter_class=argparse.RawDescriptionHelpFormatter,
71
+ epilog="""示例用法:
72
+ # 生成查询类参数化测试用例(不传mark)
73
+ har2pytest testcase api_request.har --pattern list_query
74
+
75
+ # 生成查询类参数化测试用例(传mark)
76
+ har2pytest testcase api_request.har --pattern list_query --mark test_4291
77
+
78
+ # 生成复杂场景测试用例(不传mark)
79
+ har2pytest testcase api_request.har --pattern complex_scenario --url /api/user/login
80
+
81
+ # 生成复杂场景测试用例(传mark)
82
+ har2pytest testcase api_request.har --pattern complex_scenario --url /api/user/login --mark test_4295
83
+ """,
84
+ )
85
+ tc_parser.add_argument("har_file", nargs="?", default=None, help="HAR文件路径(batch模式不需要)")
86
+ tc_parser.add_argument(
87
+ "--pattern",
88
+ default="list_query",
89
+ choices=["list_query", "complex_scenario", "batch"],
90
+ help="测试用例模式: list_query(查询类参数化)、complex_scenario(复杂场景) 或 batch(批量生成)",
91
+ )
92
+ tc_parser.add_argument("--mark", "-m", help="测试标记(如 test_4291)")
93
+ tc_parser.add_argument("--url", "-u", help="目标接口URL(可选,指定后只生成该接口的测试用例)")
94
+ tc_parser.add_argument("--output", "-o", default="testcases", help="输出目录")
95
+ tc_parser.add_argument("--api-dir", default="apis", help="API文件目录")
96
+ tc_parser.add_argument("--api-files", help="指定API文件集合(batch模式使用,多个文件用逗号分隔)")
97
+
98
+ # swagger 子命令
99
+ swagger_parser = subparsers.add_parser(
100
+ "swagger",
101
+ help="从Swagger文档生成API接口文件",
102
+ description="从Swagger文档生成API接口文件",
103
+ formatter_class=argparse.RawDescriptionHelpFormatter,
104
+ epilog="""示例用法:
105
+ # 从Swagger文档生成所有API文件
106
+ har2pytest swagger https://petstore.swagger.io/v2/api-docs
107
+
108
+ # 从Swagger文档生成API文件,指定输出目录
109
+ har2pytest swagger https://petstore.swagger.io/v2/api-docs --output apis
110
+
111
+ # 从Swagger文档生成API文件,强制覆盖
112
+ har2pytest swagger https://petstore.swagger.io/v2/api-docs --overwrite
113
+
114
+ # 从Swagger文档生成指定路径的API文件
115
+ har2pytest swagger https://petstore.swagger.io/v2/api-docs --path /pet/{petId}
116
+ """,
117
+ )
118
+ swagger_parser.add_argument("swagger_url", help="Swagger文档URL")
119
+ swagger_parser.add_argument("--output", "-o", default=APIConfig.DEFAULT_API_DIR(), help="输出目录")
120
+ swagger_parser.add_argument("--overwrite", "-f", action="store_true", help="强制覆盖现有文件")
121
+ swagger_parser.add_argument("--path", "-p", help="只生成指定的API路径(如 /pet/{petId})")
122
+
123
+ # 解析参数
124
+ args = parser.parse_args()
125
+
126
+ # 如果没有指定命令,默认使用 api 命令
127
+ if args.command is None:
128
+ args.command = "api"
129
+
130
+ # 执行对应的命令
131
+ if args.command == "api":
132
+ asyncio.run(handle_api(args))
133
+ elif args.command == "summary":
134
+ handle_summary(args)
135
+ elif args.command == "testcase":
136
+ asyncio.run(handle_testcase(args))
137
+ elif args.command == "swagger":
138
+ asyncio.run(handle_swagger(args))
139
+ elif args.command == "help":
140
+ parser.print_help()
141
+ else:
142
+ logger.error(f"未知命令: {args.command}")
143
+ parser.print_help()
144
+
145
+
146
+ async def handle_api(args):
147
+ """处理 api 命令"""
148
+ har_file = args.har_file
149
+ output_dir = args.output
150
+ force_overwrite = args.overwrite
151
+
152
+ logger.info(f"从HAR文件生成API接口文件: {har_file}")
153
+ logger.info(f"输出目录: {output_dir}")
154
+ logger.info(f"强制覆盖: {force_overwrite}")
155
+ logger.info("-" * 50)
156
+
157
+ api_generator = APIGenerator(output_dir)
158
+ generated_files = await generate_api_files_from_har(
159
+ har_file, force_overwrite=force_overwrite, api_generator=api_generator
160
+ )
161
+
162
+ logger.info("-" * 50)
163
+ logger.info(f"共生成 {len(generated_files)} 个API接口文件")
164
+
165
+ if generated_files:
166
+ api_generator.generate_index_file(generated_files)
167
+
168
+
169
+ def handle_summary(args):
170
+ """处理 summary 命令"""
171
+ har_file = args.har_file
172
+
173
+ parser = HARParser()
174
+ parser.print_api_summary(har_file)
175
+
176
+
177
+ async def handle_swagger(args):
178
+ """处理 swagger 命令"""
179
+ swagger_url = args.swagger_url
180
+ output_dir = args.output
181
+ force_overwrite = args.overwrite
182
+ specific_path = args.path
183
+
184
+ logger.info(f"从Swagger文档生成API接口文件: {swagger_url}")
185
+ logger.info(f"输出目录: {output_dir}")
186
+ logger.info(f"强制覆盖: {force_overwrite}")
187
+ if specific_path:
188
+ logger.info(f"只生成指定路径: {specific_path}")
189
+ logger.info("-" * 50)
190
+
191
+ api_generator = APIGenerator(output_dir)
192
+ swagger_handler = SwaggerHandler(api_generator=api_generator)
193
+ generated_files = await swagger_handler.generate_apis_from_swagger(swagger_url, force_overwrite, specific_path)
194
+
195
+ logger.info("-" * 50)
196
+ logger.info(f"共生成 {len(generated_files)} 个API接口文件")
197
+
198
+ if generated_files:
199
+ api_generator.generate_index_file(generated_files)
200
+
201
+
202
+ async def handle_testcase(args):
203
+ """处理 testcase 命令"""
204
+ har_file = args.har_file
205
+ pattern = args.pattern
206
+ task_id = args.mark
207
+ target_url = args.url
208
+ output_dir = args.output
209
+ api_dir = args.api_dir
210
+
211
+ if pattern == "list_query":
212
+ # 验证必填参数
213
+ if not har_file:
214
+ logger.error("错误: list_query 模式必须指定 HAR 文件")
215
+ logger.error("使用示例: har2pytest testcase api.har --pattern list_query --url /api/user/list")
216
+ return
217
+ if not target_url:
218
+ logger.error("错误: list_query 模式必须指定 --url 参数")
219
+ logger.error("使用示例: har2pytest testcase api.har --pattern list_query --url /api/user/list")
220
+ return
221
+
222
+ logger.info(f"生成查询类参数化测试用例: {har_file}")
223
+ logger.info(f"任务ID: {task_id}")
224
+ logger.info(f"目标接口: {target_url}")
225
+ logger.info("-" * 50)
226
+
227
+ generator = TestCaseGenerator(api_dir=api_dir, output_dir=output_dir)
228
+ test_files = generator.generate_parametrized_list_testcases(har_file, task_id, target_url)
229
+
230
+ logger.info("-" * 50)
231
+ if test_files:
232
+ logger.info(f"成功生成 {len(test_files)} 个测试用例文件:")
233
+ for test_file in test_files:
234
+ logger.info(f" - {test_file}")
235
+ else:
236
+ logger.info("生成测试用例文件失败")
237
+
238
+ elif pattern == "complex_scenario":
239
+ # 验证必填参数
240
+ if not har_file:
241
+ logger.error("错误: complex_scenario 模式必须指定 HAR 文件")
242
+ logger.error("使用示例: har2pytest testcase api.har --pattern complex_scenario --url /api/user/login")
243
+ return
244
+ if not target_url:
245
+ logger.error("错误: complex_scenario 模式必须指定 --url 参数")
246
+ logger.error("使用示例: har2pytest testcase api.har --pattern complex_scenario --url /api/user/login")
247
+ return
248
+
249
+ logger.info(f"生成复杂场景测试用例: {har_file}")
250
+ logger.info(f"任务ID: {task_id}")
251
+ logger.info(f"目标接口: {target_url}")
252
+ logger.info("-" * 50)
253
+
254
+ generator = TestCaseGenerator(api_dir=api_dir, output_dir=output_dir)
255
+ test_file = generator.generate_scenario_testcase(har_file, target_url, task_id)
256
+
257
+ logger.info("-" * 50)
258
+ if test_file:
259
+ logger.info(f"成功生成测试用例文件: {test_file.replace('\\', '/')}")
260
+ else:
261
+ logger.info("生成测试用例文件失败")
262
+
263
+ elif pattern == "batch":
264
+ # batch 模式:批量生成测试用例(直接从API文件读取参数)
265
+ api_files_arg = args.api_files
266
+ if not api_files_arg:
267
+ logger.error("错误: batch 模式必须指定 --api-files 参数")
268
+ logger.error("使用示例: har2pytest testcase --pattern batch --api-files apis/mall_mgmt_application/_mgmt_prmt_luckyActivity_luckyActivityList.py")
269
+ return
270
+
271
+ # 解析 API 文件列表(支持逗号分隔)
272
+ api_files_list = [f.strip() for f in api_files_arg.split(",")]
273
+
274
+ logger.info("批量生成测试用例(从API文件读取参数)")
275
+ logger.info(f"API文件数量: {len(api_files_list)}")
276
+ logger.info(f"任务ID: {task_id}")
277
+ logger.info("-" * 50)
278
+
279
+ generator = TestCaseGenerator(api_dir=api_dir, output_dir=output_dir)
280
+ result = await generator.generate_batch_testcases(api_files_list, task_id)
281
+
282
+ logger.info("-" * 50)
283
+ logger.info(f"总API文件数: {result['total']}")
284
+ logger.info(f"跳过(已存在): {result['skipped']}")
285
+ logger.info(f"成功生成: {result['generated']}")
286
+ logger.info(f"失败: {result['failed']}")
287
+ if result["generated_files"]:
288
+ logger.info("生成的文件:")
289
+ for f in result["generated_files"]:
290
+ logger.info(f" - {f.replace('\\', '/')}")
291
+
292
+
293
+ if __name__ == "__main__":
294
+ main()