Appium [开源分享] 基于 appium 的自动化测试工具,支持多进程,性能采集分析等

joko · November 27, 2016 · Last by lei replied at August 15, 2019 · 5777 hits
本帖已被设为精华帖!

简介

基于appium编写的自动化测试工具。使用方法简单,编写yaml文件格式的测试用例即可,无需改动任何一行代码。支持Android,多台设备并行,性能采集等。
开源地址:https://github.com/ztwo/Auto_Analysis

为什么要重复造轮子

  • 稳定:执行过程中会被异常打断,目前已经捕获这些异常,增加了判断
  • 直观:例如性能报告有横向对比,错误日志筛选等
  • 简单:无需改动一行代码即可运行测试
  • 扩展:代码封装清晰,比较容易扩展,增加解释器

环境要求

  • macOS,linux,windows
  • appium 1.5.0+
  • python 2.7

工具特性

执行编写yaml格式的testcase,执行后即可得到测试报告

  • 1:支持Android 4.2.2 以上
  • 2:支持多设备并行测试
  • 3:性能采集与横向对比,每个case均是独立结果。
  • 4:支持log采集与清洗
  • 5:对appium异常的一些封装,例如失败重试,需要点击才能安装等
  • 6:用例编写支持继承多重继承,大部分用例仅需写两个步骤即可

快速开始

执行效果

12

报告样式

20161123810772016-11-23pm.png

测试用例编写规范

  • 1: 需要了解yaml格式编写规范,建议使用pycharm编写,自带yaml文档检查器. yaml语法学习地址
  • 2: 用例名不可重复,会影响用例的继承

测试用例字段解释

字段 解释 演示 包含字段 是否必须
test_name 用例名 login /
test_id 用例id 0001 /
test_control_type 查找控件方式 xapth xpath, id
test_action 操作方法 click 见下表
test_control 控件 com.xx.id /
test_text 断言、输入文本 test /
test_inherit 继承用例名 login /
test_range 循环本步骤次数 2 /
test_sleep 步骤执行后,等待秒 2 /
test_wait 配合断言,等待控件秒 30 /
test_action 解释 所有字段 配合字段 辅助配合字段
click 点击 click test_control_type,test_control /
send_keys 发送文本 send_keys test_control_type,test_control,test_text /
swipe 滑动 swipe_left,swipe_right,swipe_up,swipe_down / /
assert 断言 assert test_control_type,test_control,test_text test_wait
entity 实体按键 entity_home,entity_back,entity_menu,entity_volume_up,entity_volume_down / /

完整用例范例,用例名:login

---
-
test_name: 点击跳过
test_id: 0001
test_control_type: id
test_action: click
test_control: test.joko.com.myapplication:id/button1
-
test_name: 输入帐号名
test_id: 0002
test_control_type: id
test_action: send_keys
test_control: test.joko.com.myapplication:id/editText
test_text: 199999999
-
test_name: 输入密码
test_id: 0003
test_control_type: id
test_action: send_keys
test_control: test.joko.com.myapplication:id/editText2
test_text: 9999

-
test_name: 点击登录
test_id: 0004
test_control_type: xpath
test_action: click
test_control: //android.widget.Button[contains(@text,'确定')]

-
test_name: 向上滑动页面
test_id: 0005
test_action: swipe_up
test_range: 3

-
test_name: 向下滑动页面
test_id: 0006
test_action: swipe_down
test_range: 3


主要代码分析

  • 原理:开启appium driver,解析yaml格式testcase,执行,输出报告

  • po.BasePage:封装appium driver方法


def send_key_event(self,arg):
"""
操作实体按键
:return:
"""

event_list = {'entity_home':3,'entity_back':4,'entity_menu':82,'entity_volume_up':24,'entity_volume_down':25}
if arg in event_list:
self.driver.keyevent(int(event_list[arg]))

  • po.ExecuteCase:执行case类

def get_all_case(self, path_yaml):
"""

:param path_yaml: 用例地址
:return: 返回yaml内字典,且遍历继承的信息,支持多重继承
"""


def get_case(path_yaml):
case_list = []

inherit_case_file = public.GetCase.case_yaml_file()
with open(path_yaml) as f:
for dic in yaml.load(f):
if isinstance(dic, dict):
if 'test_inherit' in dic:
inherit_case_name = dic['test_inherit']
inherit_case = inherit_case_name + '.yaml'
if inherit_case in inherit_case_file.keys():
case_list += case_list + get_case(inherit_case_file[inherit_case])

else:
case_list.append(dic)
else:
U.Logging.warn('get_case:not dic')
return case_list

return get_case(path_yaml)


def __analysis_yaml(self, path_yaml):
"""
测试用例解释器
:param path_yaml: 测试用例地址
1:每执行一条用例会记录下当前的性能


:return:
"""



  • po.integration:初始化环境
  • lib.ScreenShot:minicap截图,用于appium screen报错后,调用minicap
def phone_screen(self, width_height, filename):
"""
截图
:param width_height: 宽高
:param filename: 存储的文件名
:return:
"""


U.Logging.info('phone_screen:%s' % width_height)
self.adb.shell(
"'LD_LIBRARY_PATH=/data/local/tmp /data/local/tmp/minicap -P {}/0 -s > /data/local/tmp/{}.png'".format(
width_height, filename))
U.Logging.info('phone_screen:success')

  • lib.adbUtils:adb方法封装,几乎封装了所有常用的方法。(此处感谢testerhome某位朋友,是基于他的开源脚本扩写的,有知道的是谁的帮忙@ 下)
def last_update_time(self):
"""
查询当前屏幕应用安装更新时间
"""

for package in self.shell(
'dumpsys package %s' %
self.get_current_package_name()).stdout.readlines():
if 'lastUpdateTime' in package:
return package.split('=', 2)[1].strip()

def wifi_name(self):
"""
查询连接wifi名称
"""

for package in self.shell('dumpsys wifi').stdout.readlines():
if package.startswith('mWifiInfo'):
wifi_name = re.findall(r'SSID:([^"]+), BSSID', package)
if not wifi_name:
return None
else:
return wifi_name[0].strip()

  • lib.Utils:封装的一些基础方法,如创建数据库,log输出等

  • public.installApp:安装应用,且同时开启线程,监控屏幕是否有需要点击的安装按钮


def main(self):
"""
开启多线程:
线程1:安装应用
线程2:获取当前页面是否有可点击的按钮
:return:
"""

ini = U.ConfigIni()
install_file = ini.get_ini('test_install_path', 'path')
package_name = ini.get_ini('test_package_name', 'package_name')

threads = []

click_button = threading.Thread(target=self.tap_all, args=())
threads.append(click_button)
install_app = threading.Thread(
target=self.__install_app, args=(
package_name, install_file))
threads.append(install_app)
process_list = range(len(threads))

for i in process_list:
threads[i].start()
for i in process_list:
threads[i].join()

self.adb.shell('"rm -r /data/local/tmp/*.xml"')

目前缺点:

  • 1.目前不支持iOS,不支持H5,不过框架是基于appium,增加解释器即可
  • 2.测试报告样式略丑,因为样式是纯html,不会js,得慢慢改

正在完善

  • 1.对于执行过程中异常的梳理,例如低电量,其实已经实现,但会影响执行设备的性能。还需要再打磨
  • 2.错误信息的完善

开源地址:https://github.com/ztwo/Auto_Analysis

共收到 190 条回复 时间 点赞

谢谢分享

—— 来自TesterHome官方 安卓客户端

@lose 跟你框架功能差不多,综合学习一下

@joko python setup.py install 执行这个步骤失败了,怎么回事呀。

joko #4 · November 28, 2016 作者

#3楼 @Jhon 你python环境配置pip了吗?,setup的原理是调用pip安装。如果配置了还是报错。尝试手动安装库:
'pyyaml','matplotlib','Appium-Python-Client','selenium','termcolor'

pip install 库名

安装成功后,即可运行,python demo_run.py

之前的appiumbooster也是这样实现的 你们可以交流下

@seveniruby 我没安装pip。我安装试试。谢谢你的解答思寒

这个厉害,测试报告也很漂亮

#5楼 @seveniruby python demo_run.py 运行这步骤后报了这个错,是什么原因呀。?

9Floor has been deleted


图片在此

@Jhon 我跟你图片一样的结果,原因是我没开启 usb调试工具,在手机中的 开发人员选项里。开启后 还要到门口允许这个电脑usb调试,就不报这个错了。

joko #12 · November 28, 2016 作者

#10楼 @JonnyNan
#8楼 @Jhon 问题解决了吗?手机是需要开启usb调试的,不然电脑和手机无法通信

13Floor has been deleted
14Floor has been deleted
15Floor has been deleted

#5楼 @seveniruby 这个为什么没有设置为精华帖啊,目录结构比较清晰,封装也很不错,值得学习。嘿嘿,强烈建议设置为精华帖,让更多的人可以学习到。支持@joko

为什么我就不能造出如此好轮子?不开心。

@joko 我用的python3.4,调试到这步了,报这个错,还需要设置什么呢?configparser.NoSectionError: No section: 'minicap'

#12楼 @joko 昨天在忙其他事情,我现在试试,社区这么多热心人回复,好开心。。。。

#10楼 @JonnyNan 我试试看。

#12楼 @joko @JonnyNan return recv()
AttributeError: 'module' object has no attribute 'case_sun'

报这个错是什么原因呀。。。。

22Floor has been deleted
思寒_seveniruby 将本帖设为了精华贴 29 Nov 14:27

加精理由: 写的详细. 设计优秀. 期待以后继续改进造福大家.

#18楼 @a_little 目前不兼容python3,不过从报错原因来看是因为configparser没获取到minicap的绝对路径,你可以直接手动配置data/test.ini 文件。配置说明你可以看doc内的parameter_configuration.md。把里面所有的字段都给手动配置了。
#21楼 @Jhon 没访问到包,你也手动配置data/test.ini的参数信息后,然后运行po.integration.py。这是单线程的方法,可以获取到更详细的报错信息

我在windows,linux,macos上都运行测试过,所以大多错误应该是环境的问题,可以看项目里写的详细文档

建议Python新手首次运行使用pycharm,用强大的ide如同老师可以帮你处理很多事情。

#25楼 @joko 好的,下个pycharm用下,问题我再自己看看。thanks

@joko 好的。我也是用的python3,没想到是这个的原因,嘿嘿。感谢你的分享,我觉得很有创意。

写的挺好的👍

这段代码,直接随机生成端口,感觉会有冲突的问题啊,是不是应该增加一个端口检测是否占用的方法
@joko

支持分享

#29楼 @jphtmt 感谢提醒。这块暂时问题不大,因为随机到的可能较小,且假设端口已经被占用,会重新分配端口。

#10楼 @JonnyNan 请问这个问题你怎么解决的啊,我也是报这个错误

#31楼 @joko 还有,你的yaml是用ConfigParser实现的,为啥不直接用ini格式的配置文件呢

#33楼 @jphtmt yaml并不是用ConfigParser实现的,这两个不能混为一谈。
在本工具内:ini作为信息配置管理与路径管理,yaml作为testcase的管理。

这个的区别是:ini有更好的索引,天生适合作为配置文件。yaml的优势在于支持多种数据格式,适合与语言直接粘合

#10楼 @JonnyNan AttributeError: 'module' object has no attribute 'case_sun' 我也报这个错误,单独运行integration.py没有报错。你的这个报错解决了吗?

求指教,没有接触过自动化测试工具,如何入门appium,网上很多资料都是互相转载的甚至都没经过亲身验证,实际帮助不大,想请教有经验的人指点一下,如何制定学习策略

37Floor has been deleted

@Jhon hello,你用python3跑通了吗,我调试了下 现在这列报错,@joko请问有解决方案吗?

joko #39 · November 30, 2016 作者

#38楼 @a_little python3我还没开始兼容呢,所以会报错,近期会兼容python3

@joko 好呢,多谢分享呀,百度了这个错是python2和3的编码不同引起的,试着解决还没果


这个报错跟我安装的appium版本有关系么。 我的版本是1.4.16 !!!请大神指教,!!在线等

#41楼 @liruiyu
#41楼 @liruiyu 我和你一样的错误呀。。。。

#38楼 @a_little 没呢,我和41楼,一样的错误。。。。。。。

joko #44 · December 01, 2016 作者

#42楼 @Jhon
#41楼 @liruiyu 你们的python环境是多少?电脑环境是什么?

#44楼 @joko 请教一个问题,测试报告你的报错是通过链接来查看,如果我想把报错日志信息直接显示到html中,这个有没有什么好方法,跑完通过过滤日志这种方法不是很好,能有其他的方法,比如类似监听什么的,可以把对应用例的报错或者执行日志单独过滤出来么?类似testng那样

#45楼 @Tank007 你好
问题1:
可以直接显示在html上,启动测试的时候同时启动个线程读logcat,发现关键字,就把那段日志存到html即可,目前没做的原因是因为我目前还不会js,做不出那种开关按钮的效果。不然错误日志都展示的话,样式太丑

问题2:目前你看到的是每个测试用例是单独的日志,linux上和macos处理的都比较完美,windows目前还没找到完美的解决办法

joko #47 · December 01, 2016 作者

#43楼 @Jhon
#41楼 @liruiyu
#35楼 @sunkuan2007
如果你们都是python2.7的话,重新git下我最新的提交,我换了一种多进程的启动方法。看看还会不会报错

我想问下你的“执行过程中会被异常打断,目前已经捕获这些异常,增加了判断”这个是怎么实现的

先顶后看。😃

@joko 我也想知道你的异常怎么捕捉的,比如三台手机,有两台手机闪退了,如何捕捉到这两台闪退手机的日志信息并且在不影响到框架的正常运行的?

#24楼 @seveniruby 提个问题 :本篇标题太长 首页看不出是精华 钻石没了

#48楼 @410637312
#50楼 @lose
设计框架的时候需要考虑到这些,用的是单例模式,每个线程不会互相影响。关于错误的捕捉:

1.来看代码,解释器方法包裹了一个错误捕捉器。用来捕获执行成错误的原因


def e():
"""
捕获用例执行函数异常安装
:return: True|AssertionError|AttributeError
"""


def E(func):
def wrapper(*args, **kwargs):
error_msg = True
try:
return func(*args, **kwargs)
except AssertionError as e:
U.Logging.warn(traceback.format_exc())
U.Logging.error(e)
error_msg = 'Assertion error'
except AttributeError as e:
U.Logging.warn(traceback.format_exc())
U.Logging.error(e)
error_msg = 'Attribute Error'
except Exception as e:
error_msg = traceback.format_exc()
U.Logging.error(e)
finally:
return error_msg

return wrapper

return E

@e()
def __analysis_yaml(self, path_yaml):
pass

2.错误日志的捕捉

  • 1:应用启动时在后台记录log
  • 2:任务结束时分析log,过滤exception

def logcat(self, log_path):
return self.adb('logcat -v time > %s&' % (log_path))

class Anl:
def __init__(self, all_result_path):
self.all_result_path = all_result_path

@U.l()
def __log_file(self, all_path_result, the_suffix_name):
"""

:return: 日志列表
"""

return GetFilePath.all_file_path(
all_path_result, the_suffix_name).values()

def analyze(self, log_file):
"""
过滤Exception到log文件夹内
:param log_file: log的路径
:return:
"""

errorId = 0
go_on_id = 0
log_filter_name = os.path.split(log_file)[1].split('.')[0]
with open(self.all_result_path + '/log/{}filter.log'.format(log_filter_name), 'w') as s:

with open(log_file) as f:
for line in f:
if 'Exception' in line:
go_on_id = 1
s.write('#' + '-' * 40 + '\n')
s.write(line)
errorId = line.split('(')[1].split(')')[0].strip()
elif go_on_id == 1:
if errorId in line:
s.write(line)
else:
go_on_id = 0

def main(self):
"""
获取log,生成filter log
:return:
"""

for log_file in self.__log_file(self.all_result_path, '.log'):
self.analyze(log_file)


这样执行过程中的异常和错误的异常均能捕捉,查看报告即可

#52楼 @joko 太强大了,看你的代码才是真正的高手写的,够我消化好长时间了。。。。

厉害了

想请教大家一个问题,appium在做安卓app自动化测试时,点击h5页面js弹框按钮,执行的时候没有效果也不报错,为什么呢
代码是这样写的:driver.findElementByXPath("//android.view.View[contains(@content-desc,'返回修改')]").click();
通过inspector获取的元素内容如下

就连点击坐标也没有用

好好学习

怎么一直停在这里不运行了呢。Appium Server要开启么。

@joko 你好,请问这个路径中的{ }大括号用意是什么呀,百度了半天无解,只好来咨询你,看起来是多选的意思,在这个路径下的多个文件,是这样的意思吗?minicap_path = /Users/joko/Documents/Auto_Analysis/data/minicap/bin/{}/minicap

安装后后报错,为什么呢

#57楼 @JeffLiu 不用手动开启appium的,你的电脑是什么系统,win10?

#58楼 @a_little {}是Python .format()方法用于拼接字符串,不相同手机所需的minicap包均不相同,所以查到手机信息后用这个来替换路径

#59楼 @xiaocong168 你这个报错是因为手机版本是4.1.2,获取不到手机的resource-id,需要手4.2.2以上的手机

安装测试的apk后就一直不动了

joko #62 · December 06, 2016 作者

#61楼 @xiaocong168
#57楼 @JeffLiu

这个问题都是因为appium没起来,你们要是方便的话重新拉取下github最新的提交,我在这块加了写log,用于分析问题

#62楼 @joko 我安装的是通过下载的window客户端版本的appium 运行demo_run时候 需要手动打开appium吗?

joko #64 · December 06, 2016 作者

#63楼 @xiaocong168 不需要手动打开,代码里已经用命令方式开启,我在最新的提交里加了启动的日志,你再失败的话,把日志贴出来看看

#64楼 @joko 刚刚在git新下载的源码,终端mx5pro,执行demo_run,安装好apk后就不能继续了,请问这个报错是什么原因呢,日志一直是:
[34m2016-12-06 15:36:20 [Debug]:[0m

@joko ,我和61#一样的错。已安装你的最新版了。日志也没记录啥呀。Appium server还是不能启动。

joko #67 · December 06, 2016 作者

#66楼 @JeffLiu
#65楼 @a_little

稍等,我正在看这个问题,今天应该能解决,原因是windows启动进程的方法有问题,linux和macos我测了没问题

joko #68 · December 06, 2016 作者

#65楼 @a_little
你方便留下联系方式吗,我远程看看异常状态,刚才楼下的朋友问题是因为appium配置问题,我远程连接看了下,异常已经解决了


appium启动确实有问题

joko #70 · December 06, 2016 作者

#69楼 @cissy 你这是win10吗?你拉取最新的提交,我这边已经尝试修复了问题,win7上测试没问题
#65楼 @a_little

#70楼 @joko 是win10,今天早上拉了最新的代码,这个问题修复了,windows上坑太多。

@joko ,
Run 程序会抛出这个异常。能简单介绍下运行原理么。

我是mac环境,按照教程运行的很顺利,但是在最后生成报告的时候,没有html,其他的截图什么的都有,唯独没有html,请问是怎么回事呢?在demo运行的最后,报了这么堆异常:
Exception in thread Thread-1:
Traceback (most recent call last):
File "/usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.py", line 801, in bootstrap_inner
self.run()
File "/Users/shiwei/Desktop/Auto_Analysis/run.py", line 30, in run
a.case_start()
File "/Users/shiwei/Desktop/Auto_Analysis/po/integration.py", line 147, in case_start
self.analysis(yaml_name, yaml_path)
File "/Users/shiwei/Desktop/Auto_Analysis/po/integration.py", line 126, in analysis
return s.main()
File "/Users/shiwei/Desktop/Auto_Analysis/po/ExecuteCase.py", line 313, in main
self.
save_android_result()
File "/Users/shiwei/Desktop/Auto_Analysis/lib/Utils.py", line 125, in wrapper
t = func(*args, **kwargs)
File "/Users/shiwei/Desktop/Auto_Analysis/po/ExecuteCase.py", line 131, in save_android_result
r.main()
File "/Users/shiwei/Desktop/Auto_Analysis/public/GenerateReports.py", line 131, in main
self.
device_info(),
File "/Users/shiwei/Desktop/Auto_Analysis/lib/Utils.py", line 125, in wrapper
t = func(*args, **kwargs)
File "/Users/shiwei/Desktop/Auto_Analysis/public/GenerateReports.py", line 65, in __device_info
return 'device_name:' + self.adb.get_device_name(), 'disk:' + self.adb.get_disk(), \
TypeError: cannot concatenate 'str' and 'NoneType' objects

复制的log不太好认,这是截图

我照着错误提示,把return的参数类型强转成str就不报错了,html出来了

joko #76 · December 07, 2016 作者

#72楼 @JeffLiu 这个错误是我自定义的报错,原因是因为执行测试的手机,未安装上测试app,尝试4次没成功后就会报错,你提供下你的电脑系统,和你的手机品牌与型号,我看看能不能找到 不能安装的问题。或者你尝试手动adb install 试试

#74楼 @gmjdadk 问题修复了,你拉下提交,应该是某些手机wifi状态问题导致

#76楼 @joko 恩恩是的,我看了下是因为返回的设备信息没有类型,我都强转成str后,html顺利的出来了

#76楼 @joko 请问高手,这套框架未来会支持IOS吗?

#76楼 @joko app是否安装成功的判断应该是有bug,从手机上看是安装成功了,但log提示安装失败,用你自带的app是没有这个问题的,换成测试用的app就会出现。

报告简洁明了,确实不错,我更想了解的是工具的实用性和内涵:

1.UI频繁变动,如何解决维护成本问题;

2.性能图的cpu和memory能给前端性能分析带来哪些有用的价值;

3.日志能否记录下有助于开发定位问题的上下文(logcat的错误关键字过滤,只用exception吗);

#78楼 @gmjdadk 未来会支持,短期之内(二个月)不会支持

#79楼 @cissy 帮忙贴一下安装那块的日志,我看下

#80楼 @quqing

1:书写用例的方式已经极低了压缩撰写用力的的成本。

  • 例如原始用例:登录-发照片-注销
  • 需要变更为:登录-发作业-发照片-注销

在用例层只需变更用例的继承名即可。

2:cpu与内存我觉得是报告里最有价值的东西,横向对比可分析出迭代后相同模块的性能异常问题,通过性能异常可深入追查代码层面异常,举个实际的例子:本次此用例业务内优化了加载的方案,从用户无法明显感知,所以就要从性能入手,确认优化效果

3.关于日志过滤只有exception,大部分异常其实只能通过debug日志才看出,目前没有有效的方式处理,之后可能会增加关键词过滤

#81楼 @joko 今天自己解决了,看了下你的代码和doc下的说明,之前的问题是没有修改appium_parameter.yaml。😃

@joko ,执行python demo_run.py 这个, 是如何运行Appium的。运行Appium时候,是怎么调用testCase并输出报告的。Python小白,没看明白,望楼主指点一二。

今天又遇到了另一个问题,我用命令行运行一点问题没有,换成pycharm运行,总是获取不到手机设备[Error]:the computer is not connected to any devices 我打断点也看不出什么,好郁闷

#84楼 @gmjdadk
然后我把deviceID直接写死尝试继续运行,又报了新的错误

真无奈了,命令行运行特顺利,换成pycharm一个问题接着一个问题

@gmjdadk @joko 下了最新的代码,还是报这个错误

@joko 如果使用id定位找到的是一个元素组,想点击其中一个,testcase应该怎么写呢?不考虑xpath

#84楼 @gmjdadk 遇到同样的问题,一开始我以为是脚本不支持识别模拟器,后来换成真机 还是提示没有连接的设备

#88楼 @a_little 换成命令行直接运行试试,我命令行一点问题都没有,换成pycharm各种问题,就算你写死一个设备,后面在启动appium的时候依然会报nodejs的错,我已经放弃了,就命令行吧

#85楼 @gmjdadk 检查下adb环境配置,看看pycharm访问的adb是否与命令行相同

#88楼 @a_little 与楼上相同,检查下adb配置,用os.system执行下adb devices,看看设备链接状态

#86楼 @NJ-zero 好的,我再看看,可能取设置属于的时候还是有问题

在win7系统执行到下面就报错了。求教!

我这两天调试了一下,似乎是pycharm的fork问题,所有的subprocess.Popen都创建不了子进程,无奈放弃,只能用命令行运行了

稍微修改了下html的生成代码

请问不执行testcase中全部用例,执行其中几个或一个时,要怎么改

install_info = self.adb.install_app(app_file_path).stdout.readlines();
print ("hehehehehehehhehe" + install_info[-1]);
if 'Success' in install_info[-1].strip():

请教楼主在之前的代码里,针对某些机型,上述代码会报错,但是把stdout改成stderr就不会错了,
还有一个问题就是,拉取了最新代码之后

return 'device_name:' + str(self.adb.get_device_name()), 'disk:' + str(self.adb.get_disk()), \
'wifi_name:' + str(self.adb.wifi_name()), 'system_version:' + str(self.adb.get_android_version()), \
'resolution:' + str(self.adb.get_screen_resolution())

这一段还是会报错,我就把没有加str转换的都加上了,就没有错了
@joko 多谢解答

@gmjdadk 多谢~ ,解决了我的问题,命令行可以正常执行!

#92楼 @gmjdadk 换linux把。html改的很好看,你要有兴趣可以提交一下,我来合并。

#93楼 @jaylin 1.用用例文件夹区分 。2:需要改动下遍历用例的方法,增加一些过滤关键字

#94楼 @aya 1.这块代码我重写了,改成检测是否存在,你可以更新下。我也发现好像7.0获取不到信息。2.第二段报错的原因猜测是某些设备获取不到某个值,或者值的类型有问题。用str包裹一下就好。主分支我目前也这么改了,谢谢

@joko 请问python3.5能用吗?

厚着脸皮问一下前辈,没有选择webdriver中自带get_screenshot_as_png() ,而使用minicap的考虑是哪里呢?

#97楼 @zzzzz33001 不能用,目前只能运行在python2.7

#98楼 @Esaylove 已经用到,默认截图就是driver自带的方法。minicap是备选方案,我在调试的过程中发现会偶发报错,报错后会调用minicap,第三顺位是 adb shell /system/bin/screencap -p /sdcard/temp.png

请问一下,用例是随机执行的吗

#96楼 @joko 好的,我整理一下html的代码,现在写的有点乱😅

你好,直接运行你的demo_run会报错,重装失败,类似这种:[Error]:Reinstalling com.wuba.zhuanzhuan P4M0215416001124
不知道和appium版本有没有关系,我的是1.4.16...

执行一次脚本 为什么会反复执行用例呢

#102楼 @zlx_lizzy 安装app失败了,检查下手机安装时是不是有一些弹窗,选择确认。目前仅封装了一些常见手机弹窗的处理

#103楼 @xiaocong168 demo自带了两个用例,第二个用例继承上一个用例(每次执行完毕后会初始化环境)

#104楼 @joko 作为潜水党,首先感谢分享,发现一些问题,没有关闭adb和cmd进程,导致运行结束后还是不断写入log日志,自己运行后执行taskkill /f /im cmd.exe

#105楼 @automation 感谢回复,linux和macos做了处理,原因是因为linux和macos启动后会有独立的logcat进程,但windows不是(目前观察来看是这样),所以没办法单独关闭单独logcat的进程。windows这部分模块没想好怎么处理

目前遇到的问题是,运行demo脚本会自动打开APPIUM但是不会自动启动server,然后也无法继续执行下一步。关闭appium就会报错。配置应该都OK的啊,APPIUM版本1.4.16 win10 64位系统。appium是手动安装的,环境变量也都设置了,就是图中的情况,貌似是侦测不到设备?APPIUM也没有自动开启服务。

备注: 使用RF+APPIUM的方式是可以跑起来并运行一些RF上的case的。

#107楼 @mexth
已经解决,使用命令行重新安装appium后可以正常跑了

@joke 什么时候兼容python 3,期待大神多发帖,多分享

@joko ,
设置这minicap_path,minitouch_path,minicapso_path有什么用么。是用到STF了么。

joko #111 · December 20, 2016 作者

#110楼 @JeffLiu 没用到stf,用的是stf 里minicap截图

HI @joko 感觉这里是不是有个逻辑问题
device_list = po.integration.get_device_info() 拼装当前历史已存在的test_info and test_device信息
capublic.GetDevice.set_device_yaml()是获取当前设备信息并保存到yaml

run_deviced时候应该是当前最新的设备信息

不知道我理解对不对?

大神们,在win7系统执行报错,求教!
appium :1.4.16
python :2.7
device:nexus 6P
Android:7.1.1

#113楼 @slideplustest 运行appium-doctor检查下环境有没有问题

#114楼 @xiaocong168 还是不行,appium-doctor 运行结果图如下,不知道怎么搞了😓

#112楼 @xiaocong168 你好~感谢反馈。这块逻辑的确不严谨,我已经修改,晚些时候提交一下,谢谢!

#113楼 @slideplustest 错误提示里写的是unicodeIME安装失败,这个是appium的输入法,执行的时候看下手机,点下按住确认

#116楼 @joko Hi joko 谢谢你的提示! 感觉不是unicodeIME安装失败的原因,重新运行了下,从提示上看是说这个apk已存在, 我手动 -r强行安装完成后,运行还是说Failure [INSTALL_FAILED_ALREADY_EXISTS: 完成错误截图如下:

看到还有一个错误的信息:"message":"A new session could not be created. 不知道跟这个是不是有关系,我再查下看看。
另外我执行后,设备上没有出现需要确认的弹窗,只是安装了unlock/appium settings/Auto Analysis,不知道得到这样的结果对不对,有点懵~😇

#3楼 @Jhon 这个功能试了很久都不知道怎么用

#96楼 @joko 楼主,我运行你的脚本,不知道为啥运行不起来,可以加你QQ吗?

厉害!

学习了。

—— 来自TesterHome官方 安卓客户端

想问下你的多设备并行是怎么做的

—— 来自TesterHome官方 安卓客户端

123Floor has been deleted

如果前面的测试执行没有通过不会对后面的操作产生影响吗?

@joko 请教个问题
login.yaml --登陆用例

other.yaml --其他业务用例

logout.yaml -退出用例

以上三个用例在同一个文件夹下,其中other.yaml前面继承login.yaml,后面继承logout.yaml
运行时会执行login.yaml 和 logout.yaml 一次,在other.yaml又会再再次运行

针对这个场景其实我主要目的是重点"其他业务用例",对于login和logout只是一个初始化和退出的过程,在执行other.yaml业务场景时运行一次即可。

这里是不是可以调整下,可以更灵活的组织用例呢?

#122楼 @potato 你好,只处理下多进程执行资源占用问题,查找device,分配端口,剩下直接开启多进程执行代码即可。没有特别的处理

#124楼 @yang_young 每个用例执行完毕后,会初始化环境(清除应用数据),不过如果服务端数据在上一用例有变更,目前框架层面没给解决,需要你独立出两套用例,或者你加个脚本,通过接口清理数据

#125楼 @xiaocong168 明白你的意思。以用例层面实现单元测试内的setup 与 tearDown,目前用例组织形式仅实现了setup。按照目前框架已经实现的功能,你的用例应该这么写,other继承login,logout继承other。最近我会实现tearDown方法,到时候就能初始化话就和销毁环境了,不会向现在这么复杂。实现完我@ 你

#126楼 @joko setup 与 tearDown你那里写好了么?我试着写了一个自己方案,在用例文件夹里建立setup.yaml tearDown.yaml
case_start()时候过滤这两个文件

test_case_yaml_temp = public.GetCase.case_yaml_file()
test_case_yaml_temp.pop('setup.yaml')
test_case_yaml_temp.pop('tearDown.yaml')
test_case_yaml = test_case_yaml_temp.items()
然后在get_all_case再拼装setup和tearDown步骤,这样用一个流程下来也没问题,不知道还有没有更好的方案呢?

这个很好,如果做成excel格式,然后一个固定格式,如点击,然后你需要选择resID,在填写ID是多少,这样直接可以让测试小白用了。

在项目中实践了下,项目中或多或少都会用到if esle这样的逻辑,符合条件才执行某些分支,能把这个加上就更好了.
或者在用例中在加个一个标记 比如test_xxx:True 如果为True,这个步骤执行结果不影响下面其他步骤执行

@joko 请教一个问题,你调试过IOS的多进程么?多台设备都是使用WDA的8100这一关端口么,还是用不同的端口?

131Floor has been deleted
132Floor has been deleted
133Floor has been deleted
134Floor has been deleted
135Floor has been deleted
136Floor has been deleted

厉害了,今天试了一下,很简易实用,特别是用例编写这块。作为伸手党,在此表示感谢了😙

感謝,期待兼容Python3的版本~😃

139Floor has been deleted

@joko 执行Demo报错,list index out of range 数组越界了。。

@joko 谢谢你的工具,你的demo可以运行,可是当我换了自己的包,报错:2017-02-16 20:49:24 [Error]:Failed to start appium :Message: An unknown server-side error occurred while processing the command. Original error: Error occured while starting App. Original error: Permission to start activity denied.

2017-02-16 20:49:24 [Error]:Try restarting the appium :5DYTG6DIVWEQT849,Trying the 1 frequency
是什么原因呢???

#141楼 @chenxin appium无法启动,看下你配置的参数是否都正常,看test_info.ini

#140楼 @648981864 这个是取屏幕分辨率报错了,你是什么机型?

#136楼 @121miao 你运行环境是什么?setup失败,可以手动安装setup里的那几个依赖库

#142楼 @joko 1080P的分辨率,公司自研机😀

#142楼 @joko 谢谢回复,已经解决了,是我一个activity写错了

楼主你好,请问case执行的顺序是怎么样的? 现在有个场景是这样的,我执行了部分case之后,其中一条case是退出当前的app,需要重启app?

146Floor has been deleted

楼主大大你好,想问下,如果我所有的testcase全写好了,但是运行的时候有部分case不想执行应该如何操作,你的执行顺序如何控制,目前只是通过继承关系。

joko #148 · February 22, 2017 作者

#147楼 @yxrs89 顺序执行和取消执行,目前均没有控制,需要加的逻辑太多。最近在加其他方面,后期会增加选择方便的控制台

joko 回复

@joko 谢谢joke兄,不过你能把框架开源给大家已经十分受尊敬。支持你!

@joko joke兄想请问下,如果在你现在代码基础上,什么不做修改,如果我testcase建了多个目录,目录中有多个case那么我的执行顺序什么样的,遍历顺序按字母顺序来还是什么。不怕见笑我对python刚入门,有的还不能完全看懂。。

paul 回复

你好,改造GetFilePath.py内的函数即可实现。没现实顺序执行的原因:遍历的路径加入字典后,变为了无序状态,所以未顺序执行,你可以改造下这个函数

@joke 好的,谢谢啦,我周末已经改造好了。用起来还是很方便的

eddyyzx 回复

我最近也遇到了这个问题,请问有知道怎么写吗? 感谢回复

马克一个 感谢楼主啊

155Floor has been deleted

@121miao 多台手机一起执行啊

157Floor has been deleted

@121miao 他用的字典,你改为OrderedDict 有序字典,至少就可以按字母顺序执行了。具体需求你可以根据你所需要的执行顺序更改GetFilePath.py这个文件哈

@joke @yxrs89 帮看下这是什么原因引起的?

同样实现了js版本的自动化测试工具sptt,设计理念和本文大同小异,对此有兴趣的同学可以联系我哈

@FFMS 根据提示啊 没有找到ConfigParser 模块

162Floor has been deleted
龙十 回复

这个模块是楼主的代码库中安装的 ? 还是python内置?

FFMS 回复

你自己加载一下这个模块就知道了

@121miao 应该不是bug,作者用了一个修饰器来捕获异常,默认作者返回了true,当不出现任何异常的时候,当遍历yaml文件中每一步操作时,如果遇到异常或者AssertionError和AttributeError时会捕获到,并返回出去。
作者只是给了一个整体框架,1个月前我还从未学过python,就在作者的这套框架上边学边做边改,带着问题去查,能学到不少东西。

166Floor has been deleted
joko #167 · March 24, 2017 作者

你好,你的问题是装饰器捕获了异常,但在报告结果内未展示异常显示的是true?

请问你是用的什么工具共享的屏幕呀?

请问你是用的什么工具共享的屏幕呀?啊

170Floor has been deleted
joko #171 · March 24, 2017 作者

不能用操作层来判断用例的状态,需要用断言来验证,一个完整的用例是需要有断言存在。

172Floor has been deleted
joko 回复

方便加个QQ或者微信吗 @joko

joko #174 · March 24, 2017 作者 1 个赞

问题1:你说的找不到控件指的是:业务条件不允许使用以控件断言,还是因为业务的变动,此控件不存在?第一种:目前只支持控制属性断言,如果想增加新的可以在ExecuteCase.py内增加方法。第二种:如果相关控件的消失,或者控件文本变化,用例会执行失败的

问题2:问题我在上一个回复回答过了。用例的操作不能作为成功失败的验证,验证需要断言。举个实际例子:1:输入帐号,2:输入密码,3:登录,4:验证登录页面。操作和断言是两个事情。不过如果你确实有操作失败就报错的需要,可以改下代码:BasePage.py->find_element,把这个函数的try去掉即可

175Floor has been deleted

@joko

问题:

  • 是否支持模拟器?
  • result内无test_report报告~
  • 问题截图:

你好,本人小白 请问有长按、双击、点击拖拽这些test_action吗?

@joko 请问大大这个报错是怎么回事?如何解决 谢谢

joko #179 · April 17, 2017 作者 1 个赞
Jason1227 回复

selenium新版问题,退回老版本即可:https://github.com/appium/python-client/issues/162

joko #180 · April 17, 2017 作者
Kz 回复

目前不支持,你改造一下即可,加一些test_action

请问#61的问题怎么解决?appium不能自动启动

@xiaocong168 请问你#61的错误是怎么解决的

@joko 为什么最多同时连接6个手机?有这个限制的作用是?

你好,运行过程中经常会卡住,没有报错,没有超时,比如上一步骤执行成功之后,然后就没有日志输出,感觉像终端都一起卡死了一样不清楚什么问题,关闭终端重新打开又不卡了,或者又在其他步骤后面不动了,这种可能是什么原因呀

请问您现在还在维护吗

您好,请问这里面比如有3个相同id的控件,这种以数组形式存在的id如何输入呢

joko #187 · May 17, 2017 作者
龙十 回复

没限制连接数啊

joko #188 · May 17, 2017 作者
深蓝 回复

维护,端午节有时间我更新一下,class name的实现方式。卡住的问题你方便的话我日志发我邮箱,邮箱在setup.py里

joko #189 · May 17, 2017 作者
LambooZ 回复

卡住的问题我得查查,这块之前为了避免windwos一个bug,特意这么实现的。如果方便你把日志发我邮箱

joko 回复

好的十分感谢

191Floor has been deleted

@joko 请教下,我执行demo_run.py,server不会自动启动,而且我手动启动server后,python脚本也一直不执行,什么输出都没有。谢谢了呢

找到原因了,是因为我有appium的快捷方式,代码里执行appium命令的时候会把客户端启动,但是不是launch server导致程序无法继续。后来删了快捷方式,命令执行就正确了。

小王子 回复


因为adb shell dumpsys display | grep PhysicalDisplayInf 出来的数据为空,我也遇到这个问题,把PhysicalDisplayInf改为DisplayDeviceInfo就ok了

@joko 最近在看你的框架,发现多设备并行执行的时候,怎么处理不同的账号登录类似这样的场景??

196Floor has been deleted


@joko 请问一下,没有跑起来,出现了这个异常

jierong01 回复

感谢,问题已经找到,我把Utils.py里面的cmd方法中的close_fds=True,改成了False,可以跑起来了,不过不知道会不会有什么不好的影响

hello,还是我,看了你的源码,发现你获取性能指标类似cpu,men是每执行一个action,就是一个动作才去获取一次的,是这样吗,如果改成sleep (1)然后获取,然后累计的数据量可能比较大,这样生成性能的折线图片是否会有问题尼??

joko #200 · September 27, 2017 作者
jierong01 回复

是每一个步骤获取一次,每次获取一个数值,加sleep并不会获取累计的数据,没什么影响。不过别这么做,操作后立即获取得到的数据比较能反应性能状态,等待1秒后,可能已经回落

joko 回复

有个疑问:获取性能数据,是每一个步骤获取一次??还是我设置一个循环,让他间隔一段时间来获取比较好尼??

joko #202 · September 27, 2017 作者
jierong01 回复

没有最好,适合自己的场景才是好的。一个步骤采集一次已经可以满足大部分场景了

你好,请问这个抓取的性能指标是通过什么接口做到的,能都详细介绍下

小马 python appium UI 自动化测试框架讨论 中提及了此贴 01 Feb 10:48

@joko 看了你的源码,真乃大神也, 进程 线程 装饰器 形参 位参。。。。 adb封装一句搞定。
logging 使用出神入化。。。 代码规范完全符合google工程级标准。
求继续维护,支持h5 支持ios 和 支持设备管理 等其它功能

@joko @harsayer 代码写的确实厉害,看着也是一种享受!同楼上,求继续维护。

207Floor has been deleted


楼主你好,我被这个问题困扰好久了,找答案也没找到可靠的,请问你有解决的办法吗😭

青灰云 回复

你这个198楼已经给出方法了

万分感谢啊,楼主,哈哈哈

@joko 不知道你还会不会回帖,我遇到了这个问题。运行时直接卡在这里不运行了,有时候可以运行成功但是会一直提示找不到dump.xml这个文件



这些文件夹只有关闭运行的时候才能生成,并不是实时生成的,不知道什么原因

楼主,能留个联系方式嘛。。。有点问题请教

你好,请问yaml里面怎么设置多个检查点?

@joko 楼主好,我这边遇到用例中的测试步骤总是执行完第一个就不会再往下执行的情况,比如截图中的首页列表页滑动2用例执行完后就不再执行首页列表页滑动3了,麻烦帮忙看下。我使用的是我们自己的app

楼主,我写的动态申请权限自动点击,点击完第一个允许后,点击第二个允许就一直不执行,没收到这个命令,不知为什么

王志国 回复

我遇到和你一样的问题,请问你解决了吗?

楼主,vivo手机用adb安装的时候,需要确认才能安装,你在adb安装的时候,调用self.uidump()获取页面的xml文件,但是adb install的时候用adb shell uiautomator dump是不能同时使用的,所以无法获取到安装确认页面,一直提示“2019-08-15 15:34:33 [Success]:installApp:element, return:None”,所以一直装不成功


还想教下楼主,button5 = 'vivo:id/vivo_adb_install_ok_button'这个button的id是如何获取的呀?

需要 Sign In 后方可回复, 如果你还没有账号请点击这里 Sign Up