Python v3.7.0
项目结构为:

直接贴代码,注释写的很详细了。
#!/usr/bin/env python
# -*- coding:utf8 -*-
'''
@File : mc_launcher.py
@Author: Rethink
@Date : 2019/8/1 18:33
@Desc : Custom Airtest launcher
'''
import io
import os
import shutil
import sys
from argparse import *
import airtest.report.report as report
import jinja2
from airtest.cli.runner import AirtestCase, run_script
# 自定义启动器
class McAirtestCase(AirtestCase):
"""
airtest.cli.runner 源代码 : https://airtest.readthedocs.io/zh_CN/latest/_modules/airtest/cli/runner.html#AirtestCase
"""
def setUp(self):
super(McAirtestCase, self).setUp()
def tearDown(self):
super(McAirtestCase, self).tearDown()
def run_airtest(self, suite_dir, device=''):
"""
批量运行多个脚本,并生成聚合报告
:param suite_dir: 脚本根目录
:param device: 设备标识
"""
# 用于存放脚本运行结果
air_results = []
# 日志存放路径:suite_dir/log
air_log = os.path.join(suite_dir, 'log')
if os.path.isdir(air_log):
shutil.rmtree(air_log)
else:
os.makedirs(air_log)
print(str(air_log) + '>>> is created')
# 各项目日志存放路径:suite_dir/log/项目名称.log
air_scripts = self._find_all_scripts(suite_dir)
for script in air_scripts:
log = os.path.join(suite_dir, 'log', script.replace('.air', '.log'))
if os.path.isdir(log):
shutil.rmtree(log)
else:
os.makedirs(log)
print(str(log) + '>>> is created')
# 运行脚本
output_file = os.path.join(log, 'log.html')
args = Namespace(device=device, log=log, recording=None, script=script)
try:
run_script(args, AirtestCase)
except:
pass
finally:
# Convert log to html display
rpt = report.LogToHtml(script_root=script, log_root=log, script_name=script.replace(".air", ".py"))
rpt.report("log_template.html", output_file=output_file)
result = {}
result["name"] = script.replace('.air', '')
result["result"] = rpt.test_result
air_results.append(result)
# 生成聚合报告
env = jinja2.Environment(
loader=jinja2.FileSystemLoader(suite_dir),
extensions=(),
autoescape=True,
)
template = env.get_template("summary_template.html", suite_dir)
html = template.render({"results": air_results})
output_file = os.path.join(suite_dir, "summary.html")
with io.open(output_file, 'w', encoding="utf-8") as f:
f.write(html)
def _find_all_scripts(self, suite_dir='') -> list:
"""
find all script in suite_dir
:param suite_dir:
:return: list
"""
air_scripts = []
if not suite_dir:
suite_dir = os.getcwd()
collects = os.listdir(suite_dir)
for collect in collects:
collect_path = os.path.join(suite_dir, collect)
if not os.path.isdir(collect_path):
pass
else:
if collect.endswith('.air'):
air_scripts.append(collect)
else:
deep_scripts = self._find_all_scripts(collect_path) # 递归遍历
air_scripts += deep_scripts
return air_scripts
if __name__ == '__main__':
# ap = runner_parser()
# args = ap.parse_args()
# run_script(args, McAirtestCase)
try:
suite_dir = sys.argv[1]
except IndexError:
suite_dir = os.getcwd()
finally:
test = McAirtestCase()
test.run_airtest(suite_dir)
sys.exit(0)
其中summary_template.html
的内容为:
<!DOCTYPE html>
<html>
<head>
<title>Airtest Project Results Report</title>
<style>
.fail {
color: red;
width: 7emem;
text-align: center;
}
.success {
color: green;
width: 7emem;
text-align: center;
}
.details-col-elapsed {
width: 7em;
text-align: center;
}
.details-col-msg {
width: 7em;
text-align: center;
background-color:#ccc;
}
</style>
</head>
<body>
<div>
<div><h2>Test Statistics</h2></div>
<table width="800" border="thin" cellspacing="0" cellpadding="0">
<tr width="600">
<th width="300" class='details-col-msg'>模块名称</th>
<th class='details-col-msg'>执行结果</th>
</tr>
{% for r in results %}
<tr width="600">
<td class='details-col-elapsed'><a href="log/{{r.name}}.log/log.html" target="view_window">{{r.name}}</a></td>
<td class="{{'success' if r.result else 'fail'}}">{{"成功" if r.result else "失败"}}</td>
</tr>
{% endfor %}
</table>
</div>
</body>
</html>
以命令行的形式,运行mc_launcher.py
, 运行结束后,会生成一个聚合报告文件:summary.html
,其内容如下:


网友评论