forked from linuxdeepin/youqu
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmanage.py
486 lines (465 loc) · 20.4 KB
/
manage.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
#!/usr/bin/env python3
# _*_ coding:utf-8 _*_
# SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
# SPDX-License-Identifier: GPL-2.0-only
# pylint: disable=C0114
# pylint: disable=wrong-import-position
import os
import sys
import traceback
from argparse import ArgumentParser
os.environ["DISPLAY"] = ":0"
from setting.globalconfig import SystemPath
for i in SystemPath:
if i.value in sys.path:
continue
sys.path.append(i.value)
from setting.globalconfig import GlobalConfig
from src.startapp import StartApp
from src import logger
from src.pms.pms2csv import Pms2Csv
from src.rtk._base import SubCmd
from src.rtk._base import Args
from src.rtk.local_runner import LocalRunner
from src.rtk.remote_runner import RemoteRunner
from src.depends.cfonts import say
from src.pms.send2pms import Send2Pms
# pylint: disable=too-many-instance-attributes,broad-except
class Manage:
"""执行器"""
__author__ = "[email protected]"
# pylint: disable=too-many-arguments,too-many-locals,too-many-statements
def __init__(
self,
app=None,
keywords=None,
tags=None,
rerun=None,
record_failed_case=None,
clean=None,
report_formats=None,
max_fail=None,
log_level=None,
timeout=None,
resolution=None,
debug=None,
noskip=None,
ifixed=None,
send_pms=None,
task_id=None,
trigger=None,
case_file=None,
branch=None,
deb_path=None,
pms_user=None,
pms_password=None,
suite_id=None,
pms_info_file=None,
top=None,
lastfailed=None,
duringfail=None,
repeat=None,
project_name=None,
build_location=None,
line=None,
client=None,
send_code=None,
build_env=None,
client_password=None,
parallel=None,
autostart=None,
pyid2csv=None,
export_csv_file=None,
pms2csv=None,
pms_link_csv=None,
send2task=None,
):
self.default_app = app
self.default_keywords = keywords
self.default_tags = tags
self.default_rerun = rerun
self.default_record_failed_case = record_failed_case
self.default_clean = clean
self.default_report_formats = report_formats
self.default_max_fail = max_fail
self.default_log_level = log_level
self.default_timeout = timeout
self.default_resolution = resolution
self.default_debug = debug
self.default_noskip = noskip
self.default_ifixed = ifixed
self.default_send_pms = send_pms
self.default_task_id = task_id
self.default_trigger = trigger
self.default_case_file = case_file
self.default_branch = branch
self.default_deb_path = deb_path
self.default_pms_user = pms_user
self.default_pms_password = pms_password
self.default_suite_id = suite_id
self.default_pms_info_file = pms_info_file
self.default_top = top
self.default_lastfailed = lastfailed
self.default_duringfail = duringfail
self.default_repeat = repeat
self.default_project_name = project_name
self.default_build_location = build_location
self.default_line = line
self.default_client = client
self.default_send_code = send_code
self.default_build_env = build_env
self.default_client_password = client_password
self.default_parallel = parallel
self.default_autostart = autostart
self.default_pyid2csv = pyid2csv
self.default_export_csv_file = export_csv_file
self.default_pms2csv = pms2csv
self.default_pms_link_csv = pms_link_csv
self.default_send2task = send2task
say(GlobalConfig.PROJECT_NAME)
version_font = "slick"
if "(unreleased)" in GlobalConfig.current_tag:
say(GlobalConfig.current_tag.strip("(unreleased)"), font=version_font, space=False)
say("unreleased", font=version_font, space=False)
else:
say(GlobalConfig.current_tag, font=version_font, space=False)
say(f"Code: \033[0;32m{GlobalConfig.GITHUB_URL}\033[0m", font="console", space=False)
say(f"Docs: \033[0;32m{GlobalConfig.DOCS_URL}\033[0m", font="console", space=False)
say(f"PyPI: \033[0;32m{GlobalConfig.PyPI_URL}\033[0m", font="console", space=False)
say("=" * 60, font="console", space=False)
logger(GlobalConfig.LOG_LEVEL)
self.cmd_args = sys.argv[1:]
parser = ArgumentParser(epilog=self.__author__)
subparsers = parser.add_subparsers(help="子命令")
sub_parser_remote = subparsers.add_parser(SubCmd.remote.value)
sub_parser_run = subparsers.add_parser(SubCmd.run.value)
sub_parser_pms = subparsers.add_parser(SubCmd.pmsctl.value)
sub_parser_csv = subparsers.add_parser(SubCmd.csvctl.value)
help_tip = (
f"\033[0;32mmanage.py\033[0m 支持 \033[0;32m{[i.value for i in SubCmd]}\033[0m 命令, "
"\n您需要传入一个命令,可以使用 \033[0;32m-h\033[0m或\033[0;32m--help\033[0m 查看每个命令参数的详细使用说明,"
"\n比如: \033[0;32myouqu manage.py run -h\033[0m \n"
)
if not self.cmd_args:
print(help_tip)
sys.exit(1)
if self.cmd_args[0] == SubCmd.remote.value:
remote_kwargs = self.remote_runner(parser, sub_parser_remote)
RemoteRunner(**remote_kwargs).remote_run()
elif self.cmd_args[0] == SubCmd.run.value:
_local_kwargs, _ = self.local_runner(parser, sub_parser_run)
LocalRunner(**_local_kwargs).local_run()
elif self.cmd_args[0] == SubCmd.pmsctl.value:
self.pms_control(parser, sub_parser_pms)
elif self.cmd_args[0] == SubCmd.csvctl.value:
self.csv_control(parser, sub_parser_csv)
elif self.cmd_args[0] == SubCmd.startapp.value:
start_config_log = f"{SubCmd.startapp.value} 后面直接加工程名称,工程名称以 'autotest_' 开头"
try:
if self.cmd_args[1] in ("-h", "--help"):
print(start_config_log)
sys.exit(0)
self.start_app(self.cmd_args[1])
except IndexError:
logger.error(f"参数异常: {start_config_log}")
elif self.cmd_args[0] in ["-h", "--help"]:
print(help_tip)
else:
print(f"参数异常 \033[0;31m{self.cmd_args}\033[0m!\n{help_tip}")
def remote_runner(self, parser, sub_parser_remote):
"""远程执行"""
sub_parser_remote.add_argument(
"-c", "--clients", default="",
help=(
"远程机器的user@ip:password,多个机器用'/'连接,"
"如果password不传入,默认取setting/remote.ini中CLIENT_PASSWORD的值,"
"比如: [email protected]:1 或 [email protected]"
)
)
sub_parser_remote.add_argument(
"-s", "--send_code", action='store_const', const=True, default=False,
help="发送代码到测试机(不含report目录)"
)
sub_parser_remote.add_argument(
"-e", "--build_env", action='store_const', const=True, default=False,
help="搭建测试环境,如果为yes,不管send_code是否为yes都会发送代码到测试机."
)
sub_parser_remote.add_argument(
"-cp", "--client_password", default="", help="测试机密码(全局)"
)
sub_parser_remote.add_argument(
"-y", "--parallel", default="",
help=(
"yes:表示所有测试机并行跑,执行相同的测试用例;"
"no:表示测试机分布式执行,服务端会根据收集到的测试用例自动分配给各个测试机执行。"
)
)
local_kwargs, args = self.local_runner(parser, sub_parser_remote)
remote_kwargs = {
Args.clients.value: args.clients or self.default_client,
Args.send_code.value: args.send_code or self.default_send_code,
Args.build_env.value: args.build_env or self.default_build_env,
Args.client_password.value: args.client_password or self.default_client_password,
Args.parallel.value: args.parallel or self.default_parallel,
}
_remote_kwargs = {
"remote_kwargs": remote_kwargs,
"local_kwargs": local_kwargs,
}
return _remote_kwargs
def local_runner(self, parser, sub_parser_run):
"""本地执行"""
sub_parser_run.add_argument(
"-a", "--app", default="",
help="应用名称:deepin-music 或 autotest_deepin_music 或 apps/autotest_deepin_music"
)
sub_parser_run.add_argument(
"-k", "--keywords", default="", help="用例的关键词,支持and/or/not逻辑组合"
)
sub_parser_run.add_argument(
"-t", "--tags", default="", help="用例的标签,支持and/or/not逻辑组合"
)
sub_parser_run.add_argument(
"--rerun", default="", help="失败重跑次数"
)
sub_parser_run.add_argument(
"--record_failed_case", default="", help="失败录屏从第几次失败开始录制视频"
)
sub_parser_run.add_argument(
"--clean", choices=["yes", ""], default="",
help="清理环境"
)
sub_parser_run.add_argument(
"--report_formats", default="", help="测试报告格式"
)
sub_parser_run.add_argument(
"--max_fail", default="", help="最大失败率"
)
sub_parser_run.add_argument(
"--log_level", default="", help="日志输出级别"
)
sub_parser_run.add_argument(
"--timeout", default="", help="单条用例超时时间"
)
sub_parser_run.add_argument(
"--resolution", default="", help="检查分辨率"
)
sub_parser_run.add_argument(
"--debug", default="", help="调试模式"
)
sub_parser_run.add_argument(
"--noskip", choices=["yes", ""], default="",
help="csv文件里面标记了skip跳过的用例不生效"
)
sub_parser_run.add_argument(
"--ifixed", choices=["yes", ""], default="",
help="fixed不生效,仅通过skip跳过用例"
)
sub_parser_run.add_argument(
"--send_pms", choices=["", "async", "finish"], default="",
help="数据回填"
)
sub_parser_run.add_argument(
"--task_id", default="", help="测试单ID"
)
sub_parser_run.add_argument(
"--trigger", choices=["", "auto", "hand"], default="",
help="触发者"
)
sub_parser_run.add_argument(
"-f", "--case_file", default="", help="根据文件执行用例"
)
sub_parser_run.add_argument(
"--deb_path", default="", help="需要安装deb包的本地路径"
)
sub_parser_run.add_argument(
"-u", "--pms_user", default="", help="pms 用户名"
)
sub_parser_run.add_argument(
"-p", "--pms_password", default="", help="pms 密码"
)
sub_parser_run.add_argument(
"--suite_id", default="", help="pms 测试套ID"
)
sub_parser_run.add_argument(
"--pms_info_file", default="", help="pms 信息文件"
)
sub_parser_run.add_argument(
"--top", default="", help="过程中记录top命令中的值"
)
sub_parser_run.add_argument(
"--lastfailed", action='store_const', const=True, default=False,
help="仅执行上次失败用例"
)
sub_parser_run.add_argument(
"--duringfail", action='store_const', const=True, default=False,
help="测试过程中立即显示报错"
)
sub_parser_run.add_argument(
"--repeat", default="", help="指定用例执行次数"
)
sub_parser_run.add_argument(
"--project_name", default="", help="工程名称(写入json文件)"
)
sub_parser_run.add_argument(
"--build_location", default="", help="构建地区(写入json文件)"
)
sub_parser_run.add_argument(
"--line", default="", help="执行的业务线(写入json文件)"
)
sub_parser_run.add_argument(
"--autostart", default="", help="重启类场景开启letmego执行方案"
)
args = parser.parse_args()
local_kwargs = {
Args.app_name.value: args.app or self.default_app,
Args.keywords.value: args.keywords or self.default_keywords,
Args.tags.value: args.tags or self.default_tags,
Args.reruns.value: args.rerun or self.default_rerun,
Args.record_failed_case.value: args.record_failed_case or self.default_record_failed_case,
Args.clean.value: args.clean or self.default_clean,
Args.report_formats.value: args.report_formats
or self.default_report_formats,
Args.max_fail.value: args.max_fail or self.default_max_fail,
Args.log_level.value: args.log_level or self.default_log_level,
Args.timeout.value: args.timeout or self.default_timeout,
Args.debug.value: args.debug or self.default_debug,
Args.noskip.value: args.noskip or self.default_noskip,
Args.ifixed.value: args.ifixed or self.default_ifixed,
Args.send_pms.value: args.send_pms or self.default_send_pms,
Args.task_id.value: args.task_id or self.default_task_id,
Args.trigger.value: args.trigger or self.default_trigger,
Args.resolution.value: args.resolution or self.default_resolution,
Args.case_file.value: args.case_file or self.default_case_file,
Args.deb_path.value: args.deb_path or self.default_deb_path,
Args.pms_user.value: args.pms_user or self.default_pms_user,
Args.pms_password.value: args.pms_password or self.default_pms_password,
Args.suite_id.value: args.suite_id or self.default_suite_id,
Args.pms_info_file.value: args.pms_info_file or self.default_pms_info_file,
Args.top.value: args.top or self.default_top,
Args.lastfailed.value: args.lastfailed or self.default_lastfailed,
Args.duringfail.value: args.duringfail or self.default_duringfail,
Args.repeat.value: args.repeat or self.default_repeat,
Args.project_name.value: args.project_name or self.default_project_name,
Args.build_location.value: args.build_location or self.default_build_location,
Args.line.value: args.line or self.default_line,
Args.autostart.value: args.autostart or self.default_autostart,
}
if local_kwargs.get(Args.autostart.value) or GlobalConfig.AUTOSTART:
import letmego
letmego.conf.setting.PASSWORD = GlobalConfig.PASSWORD
letmego.register_autostart_service(
user=GlobalConfig.USERNAME,
working_directory=GlobalConfig.ROOT_DIR,
cmd=f"pipenv run python manage.py {' '.join(self.cmd_args)}"
)
return local_kwargs, args
def pms_control(self, parser=None, sub_parser_pms=None):
"""pms相关功能命令行参数"""
sub_parser_pms.add_argument(
"-a", "--app", default="",
help="应用名称:deepin-music 或 autotest_deepin_music 或 apps/autotest_deepin_music"
)
sub_parser_pms.add_argument(
"-u", "--pms_user", default="", help="pms 用户名"
)
sub_parser_pms.add_argument(
"-p", "--pms_password", default="", help="pms 密码"
)
sub_parser_pms.add_argument(
"-plc", "--pms_link_csv", default="",
help="pms 和 csv 的映射关系,比如:music:81/album:82,多个配置使用'/'分隔"
)
sub_parser_pms.add_argument(
"-p2c", "--pms2csv", action='store_const', const=True, default=False,
help="从PMS爬取用例标签到csv文件"
)
sub_parser_pms.add_argument(
"--send2task",
choices=["yes", ""],
default="", help="回填数据到pms测试单"
)
sub_parser_pms.add_argument(
"--task_id", default="", help="测试单ID"
)
sub_parser_pms.add_argument(
"--trigger", choices=["auto", "hand", ""], default="",
help="触发者"
)
args = parser.parse_args()
pms_kwargs = {
Args.app_name.value: args.app or self.default_app,
Args.pms_user.value: args.pms_user or self.default_pms_user,
Args.pms_password.value: args.pms_password or self.default_pms_password,
Args.pms2csv.value: args.pms2csv or self.default_pms2csv,
Args.pms_link_csv.value: args.pms_link_csv or self.default_pms_link_csv,
Args.send2task.value: args.send2task or self.default_send2task,
Args.task_id.value: args.task_id or GlobalConfig.TASK_ID,
Args.trigger.value: args.trigger or GlobalConfig.TRIGGER,
}
if pms_kwargs.get(Args.pms2csv.value):
Pms2Csv(
app_name=pms_kwargs.get(Args.app_name.value),
user=pms_kwargs.get(Args.pms_user.value) or GlobalConfig.PMS_USER,
password=pms_kwargs.get(Args.pms_password.value) or GlobalConfig.PMS_PASSWORD,
pms_link_csv=pms_kwargs.get(Args.pms_link_csv.value),
).write_new_csv()
elif (
pms_kwargs.get(Args.send2task.value)
and pms_kwargs.get(Args.task_id.value)
and pms_kwargs.get(Args.trigger.value) == "hand"
):
Send2Pms().send2pms(
Send2Pms.case_res_path(pms_kwargs.get(Args.task_id.value)),
Send2Pms.data_send_result_csv(pms_kwargs.get(Args.trigger.value))
)
@staticmethod
def start_app(startapp=None):
"""新建app工程"""
if startapp:
start = StartApp(startapp)
start.copy_template_to_apps()
start.rewrite()
def csv_control(self, parser=None, sub_parser_csv=None):
"""csv相关功能命令参数"""
sub_parser_csv.add_argument(
"-a", "--app", default="",
help="应用名称:deepin-music 或 autotest_deepin_music 或 apps/autotest_deepin_music"
)
sub_parser_csv.add_argument(
"-k", "--keywords", default="", help="用例的关键词"
)
sub_parser_csv.add_argument(
"-t", "--tags", default="", help="用例的标签"
)
sub_parser_csv.add_argument(
"-p2c", "--pyid2csv", action='store_const', const=True, default=False,
help="将用例py文件的case id同步到对应的csv文件中"
)
sub_parser_csv.add_argument(
"-ec", "--export_csv_file", default="", help="导出csv文件名称,比如:case_list.csv"
)
args = parser.parse_args()
csv_kwargs = {
Args.app_name.value: args.app or self.default_app,
Args.keywords.value: args.keywords or self.default_keywords,
Args.tags.value: args.tags or self.default_tags,
Args.pyid2csv.value: args.pyid2csv or self.default_pyid2csv or GlobalConfig.PY_ID_TO_CSV,
Args.export_csv_file.value: args.export_csv_file or self.default_export_csv_file,
"collection_only": True
}
if csv_kwargs.get(Args.pyid2csv.value) or GlobalConfig.PY_ID_TO_CSV:
from src.csvctl import CsvControl
_csv = CsvControl(csv_kwargs.get(Args.app_name.value))
_csv.delete_mark_in_csv_if_not_exists_py()
_csv.async_mark_to_csv()
else:
logger.error(
f"需要传递一些有用参数或配置项:{Args.pyid2csv.value} 或 {Args.export_csv_file.value}"
",您可以使用 -h 或 --help 查看支持的参数"
)
if __name__ == "__main__":
try:
Manage()
except Exception as exc:
traceback.print_exception(*sys.exc_info())