0%

aritest自动化测试框架设计

说明

  • 基于Airtest设计的自动化测试框架

环境设置

  • AirtestIDE-win-1.2.13 请自行安装,用来调试用例
  • 此次装的python版本为 3.7.9
  • 本地电脑的adb设置为AirtestIDE中的路径

image-20220118152720452

1
2
3
4
C:\Users\Admin>adb
Android Debug Bridge version 1.0.40
Version 4986621
Installed as E:\exe\AirtestIDE\airtest\core\android\static\adb\windows\adb.exe
  • 安装依赖文件
1
2
pip install -U airtest
pip install -U pocoui
  • 本次测试机器使用雷电模拟器,真机也可以
1
2
3
4
C:\Users\Admin>adb devices
List of devices attached
emulator-5554 device

  • 安装测试apk文件
1
>adb install -g -r C:\Users\Admin\Downloads\com.jianshu.haruki_6.4.4_liqucn.com.apk
  • 在模拟器中打开手动登录
  • 复制python环境中的Lib目录的airtest下的report文件到新建文件夹下面(E:\proj\aritest)
    • 放生成的测试报告和日志文件,默认放到项目中,对项目管理非常不友好

image-20220118164513042

  • 然后新建一个log文件,用来放测试用例报告的

image-20220118164740800

代码分析

启动器

  • 启动器代码做到和用例文件分离,现在启动器支撑ios(待测试),android(已测试),web(待测试),理论上airtest支持的都支持

  • 启动器需要取配置文件进行,配置文件如下

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
[default]
# 包名
pkg = com.jianshu.haruki
# 手机名字
phone=雷电模拟器
# 设备连接名字
dev_connect=Android://127.0.0.1:5037/emulator-5554
#dev_connect=Android://127.0.0.1:5037/ZL9LC685V86DNNMN
# 用例目录
root_path=E:\proj\airtest_auto\air_case\android
# test_plan=1 表示调试用例需要配合test_module使用,0表示全部用例
test_plan=1
test_module=["我的"]
# false|true 表示是否运行用例之前,删除log文件夹,删除后会影响查看历史报告
remove_log=true
# false|true 是否开启录屏,若传true就会自动录屏,但是在模拟器上录屏失败,只使用于真机
recording=false
# android|ios|web,当填如web时,需要填写驱动文件位置
platform =android
# driver_path=E:\proj\airtest_auto\exe\chromedriver.exe
driver_path=
# 服务器信的信息,比如本地的http服务器,用来展示报告
report_host=http://172.31.105.196:8000
# 本地服务器路径,我把源代码中的report也放在里面了
local_host_path=E:\proj\aritest
# 本地服务器端口
local_host_port=8000
[mail]
# 是否启动发送邮件,传false|true
enable =false
# 收件人
recipient =["284772894@qq.com","284772895@qq.com"]
# 发件人smtp
mail_host = smtp.126.com
# 发件人
mail_user = ashikun@126.com
# 授权码
mail_pass = XXXXX
port = 465
  • 启动器代码分析
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
# 读取配置文件,进行运行函数
PATH = lambda p: os.path.abspath(
os.path.join(os.path.dirname(__file__), p)
)
path = PATH("config/setting1.ini")
data = ReadIni(path).get_ini_list()
run_case(data)



def run_case(data):
# 当平台为安卓时,检查是否连接成功
if data.get("platform", "1") == "android":
devices = attached_devices()
if not devices:
print("无可用设备")
return
elif data.get("platform", "1") == "ios":
pass
elif data.get("platform", "1") == "web":
pass
test = CustomAirtestCase(data["root_path"])
device = [data["dev_connect"]]
test.run_air(device, data)


def run_air(self, device, data):
get_data_list = get_test_case(data)
if not get_data_list:
print("无可用用例")
return
# 开启本地http服务器
HttpServer.start(data["local_host_path"], data["local_host_port"])
# 循环执行用例
for j in get_data_list:
...
# 执行用例
get_run = run(data["root_path"], j, device, local_host_path, data["recording"])

..
# 生成测试用例的详情报告,注意这里修改了lib目录下的report.py中源代码,主要为了达到通过服务器ip访问测试报告
rpt = report.LogToHtml(get_run["script"], get_run["log"], data["report_host"]+"/report", log_host=
data["report_host"] + "/log/" + log_date + "/" + get_run["log_host_path"])
rpt.report("log_template.html", output_file=get_run["output_file"])
# self。results主要记录测试用例结果,通过解析summary_template.html生成测试报告
result = {"result": get_run["is_success"], "start_date": st_date,"end_date": end_date, "sum_time": sum_time,"log": s_log, "name": s_name}
modules.append(j["module"])
self.results["data"].append(result)
  • from airtest.report import report 里面的report.py文件修改,实际文件目录如图:

image-20220120112555007

  • report.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
class LogToHtml(object):
scale = 0.5
# 这里的log_host是我新增的日志文件服务器地址,这样新增一个字段,不影响到其他代码逻辑

def __init__(self, script_root, log_root="", static_root="", export_dir=None, script_name="", logfile=None, lang="en", plugins=None, log_host=None):
...
self.log_host = log_host # shikun 2022-1-19

# 这个函数,主要生成log.html文件中的图片展示
def _translate_screen(self, step, code):
...
for item in step["__children__"]:
if item["data"]["name"] == "try_log_screen":
snapshot = item["data"].get("ret", None)
if isinstance(snapshot, six.text_type):
src = snapshot
elif isinstance(snapshot, dict):
src = snapshot['screen']
screen['resolution'] = snapshot['resolution']
else:
continue
if self.export_dir: # all relative path
screen['_filepath'] = os.path.join(DEFAULT_LOG_DIR, src)
else:
screen['_filepath'] = os.path.abspath(os.path.join(self.log_root, src))

# 修改了这里逻辑, screen['src']展示的图片路径就Log.html中img src中的路径
if self.log_host:
screen['_filepath'] = self.log_host + "/" + src
screen['src'] = screen['_filepath']
# 根据模板文件生成测试报告,这里主要对视频文件路径进行处理
def report(self, template_name=HTML_TPL, output_file=HTML_FILE, record_list=None):
....
if not record_list:
record_list = [f for f in os.listdir(self.log_root) if f.endswith(".mp4")]
# 源代码时这样,我多加了个log_host
# data = self.report_data(output_file=output_file, record_list=record_list)
# shikun-2121-1-19
data = self.report_data(output_file=output_file, record_list=record_list, log_host=self.log_host)

# log_host 为我新增
def report_data(self, output_file=None, record_list=None, log_host=None):
...
if record_list:
records = [os.path.join(DEFAULT_LOG_DIR, f) if self.export_dir
else os.path.abspath(os.path.join(self.log_root, f)) for f in record_list]
# 对视频路径进行处理
if log_host:
records = []
for i in record_list:
records.append(log_host + "/" + i)

  • 运行runner5.py

image-20220120113714163

  • 通过http服务查看运行结果

image-20220120113910981

image-20220120113940586

image-20220120114713093

  • 实际上http服务,定位到的就是在配置文件中的:local_host_path=E:\proj\aritest
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
E:\proj\aritest>dir log\2022-01-20-10-56-21
驱动器 E 中的卷是 软件盘
卷的序列号是 240F-1787

E:\proj\aritest\log\2022-01-20-10-56-21 的目录

2022/01/20 10:58 <DIR> .
2022/01/20 10:58 <DIR> ..
2022/01/20 10:58 2,803 summary_2022-01-20-10-58-33.html
2022/01/20 10:58 1,568 summary_template.html
2022/01/20 10:57 <DIR> 他的
2022/01/20 10:57 <DIR> 我的
2 个文件 4,371 字节
4 个目录 19,213,107,200 可用字节

E:\proj\aritest>dir report
驱动器 E 中的卷是 软件盘
卷的序列号是 240F-1787

E:\proj\aritest\report 的目录

2022/01/18 16:43 <DIR> .
2022/01/18 16:43 <DIR> ..
2022/01/18 16:42 <DIR> css
2022/01/18 16:42 <DIR> fonts
2022/01/18 16:42 <DIR> image
2022/01/18 16:42 <DIR> js
2021/05/21 10:28 10,634 log_template.html
2021/08/16 10:43 21,860 report.py
2021/06/23 16:53 22,405 test.py
2018/08/28 11:39 0 __init__.py
4 个文件 54,899 字节
6 个目录 19,213,107,200 可用字节
  • 修改好的report.py文件已经放在项目跟目录,可以覆盖到各自目录即可

其他