自动化工具 两句命令搞定移动端 (iOS 和 Android) 真机并发自动化测试

terrychow · 2017年07月23日 · 最后由 YY 回复于 2020年12月24日 · 5430 次阅读
本帖已被设为精华帖!

一、前言

大概在 4 个月前我发布过那篇Web 应用并发自动化测试,其实在 web 之前我还做过移动端的并发自动化尝试,但遇到太多坑了,可能是之前对技术或工具的不熟悉,所以当时也没做出来,后面经过这段时间的努力,终于让我做出个小框架来同时支持在 windows 上 android 的并发自动化测试,还有在 Mac 上的 iOS 和 Android 的并发自动化测试,好吧,说正题,附上框架图


二、准备

为了能够正常运行这个小框架,还是得有一些东西支持的,列举一下大概用到的工具:
1、appium
2、robotframework
3、XQuartz

其中我要说 XQuartz 是什么,其实就是 xterm,一个在 mac 上运行的终端命令行工具,为什么用到它,因为它支持传入参数后再启动进程,这好比 windows 上的 start 命令,但由于 mac 系统本身就是不像 windows 那样有 start 命令的,所以就用到它了,比如下面这句

xterm -e /bin/bash -c 'sh run_appium_ios.sh‘

这样,xterm 就能在一个新窗口中开启一个新进程来运行 appium,那启动多个 appium 的话也就不会冲突了,下面会有具体演示

先简单说说原理和一些相关知识

首先是启动 appium,由于多台真机设备的测试,当然是要用到多个 appium,其实对于多设备用 appium 做并发自动化测试,为了解决冲突,无非是解决两个问题

a、设备 udid 向 appium 发送以识别是哪台设备要做自动化测试
b、appium 启动所占用的端口

其实 a 的话有尝试过做指定设备的自动化测试就知道,b 的话无非是 appium 用到的服务端口(默认 4723),对应还有 android 端的 bootstrap 的端口以及 iOS 端口的 webdriveragent 的转发端口,关于端口这边问题,其实 appium 1.6.5 之后都是没问题的,大家看看下面的命令

android(run_appium_ad.sh):

appium -p $1 -bp $2 -a $3

iOS(run_appium_ios.sh):

appium -p $1 --webdriveragent-port $2  -a $3

其实这两句命令就是我用来启动 appium 的 sh 脚本,往里面传参数就好,其中那个--webdriveragent-port 就是 webdriveragent 的端口转发的指定端口,比如在 iOS 端上的 webdriveragent 启动服务后默认是手机 ip:8100,那你本地就可以通过一个如 8101 的端口去映射手机的 8100 端,这样就能做到访问手机上的 webdriveragent,大家都知道 webdriveragent 在 iOS 端自动化测试中的作用吧,社区里面也有很多介绍,这里就不列举了,也顺带提一下一般 appium 是用自己目录下面的 webdirveragent 来 build 的,所以在此之前需要去里面添加证书和重命名包名,不然 build 不成功就不可行了,以及个人开发者 id 最多是 3 个设备同时 build,多了就要用企业开发者账号和证书了,这点有玩过的同学应该知道,这里就不具体说 webdriveragent 相关的操作,社区有很多帖子,多点用一下社区的搜索功能吧

三、演示及分析过程

不多说,先放图,首先是自动启动对应 android 的 appium 服务

这就是第一句命令

python run_server.py -o android

那就是说说 run_ server.py 是干嘛的

how to use it
  -h   help
  -o   the device os.likes ios,android
  -n   the num of starting appium server

它就是用来根据输入的参数来启动 appium 服务的,那参数哪里来的,大家可以去下载代码边看我说边分析,-o 是指测试设备的系统,首先在 run_server.py 中有一句

run_server.py:
divlist=get_info.get_devices(plat)

根据输入的参数,里面会去指定命令来获取当前连接到电脑的对应操作系统的设备数,来启动指定的 appium-server 的数量,比如 iOS 端的

python run_server.py -o ios -n 3


就是假设当前连接到电脑的 iOS 端手机只有两台,但我还是想启动 3 个 appium 服务来应对我可能接入第三台设备,那我就多启动一个吧,当前里面也会有逻辑判断,那回上面那句命令的作用,看看源码

get_info.py:
def get_devices(auto=None):
    ADB=adb_helper.AdbHelper()
    devices=[]
    if auto in ["iOS","ios"]:
        output=os.popen("idevice_id -l").readlines()
        for idevice in output:
            idev=idevice.split('\n')[0]
            devices.append(idev)
        return devices

    output=ADB.getConnectDevices()
    #print output
    for line in output:
        if line['state'] in ["device","device\r"]:
            dev=line['uuid']
            devices.append(dev)
    return devices

这个方法就是用来根据输入的参数获取当前连接到电脑的设备数(其实就是设备列表的长度)和设备的 udid,android 的用到是之前社区一位朋友提供的 adb_helper,其实用到就是 adb devices 命令,里面做了一些过滤,更好地获取当前设备数,iOS 则用到 idevice_id -l 获取,这样的话前文提到的 udid 也已经到手了,udid 解决了,接下来就是端口问题,其实更好办

get_info.py:
aport=4723
bport=5723
wport=8101
iport=14723
def start_server():


        if plat in ["iOS","ios","Android","android"]:
            if osplat in ["Mac"]:
                if plat in ["iOS","ios"]:
                    mange_port.kill_port(wport)
                    mange_port.kill_port(iport)
                    run_app="xterm -e /bin/bash -c 'sh run_appium_ios.sh {0} {1} {2} ' &".format(iport,wport,ip)
                    iport=iport+1
                    wport=wport+1              
                else:
                    mange_port.kill_port(aport)
                    mange_port.kill_port(bport)
                    run_app="xterm -e /bin/bash -c 'sh run_appium_ad.sh {0} {1} {2}' &".format(aport,bport,ip)
                    aport=aport+1
                    bport=bport+1
            else:
                mange_port.kill_port(aport)
                mange_port.kill_port(bport)
                run_app="start run_appium.bat {0} {1} {2}".format(aport,bport,ip)
                aport=aport+1
                bport=bport+1
            os.system(run_app)


        elif plat in ["grid","Grid"]:
            mange_port.kill_port(bport)
            if osplat in ["Mac"]:
                run_app="xterm -e /bin/bash -c 'sh run_appium_grid.sh {0} {1} {2} {3} {4}' &".format(ip,aport,bport,div,conf_mac)
            else:
                run_app='start run_appium_grid.bat {0} {1} {2} {3} {4}'.format(ip,aport,bport,div,conf)
            os.system(run_app)     
            aport=aport+1
            bport=bport+1


        else:
            print "Not support this os device!"

(上面有省略部分代码),其实 android 的端口是用 4723 开始和 5723 开始,iOS 是用 14723 开始和 8101 开始,每启动一个 appium 服务就对应加 1,对于端口的使用,假设我现在要用 4723 端口,但之前有程序在占用怎么办,我现在用来一种粗暴的方法,就是把占用端口的那个进程 kill 掉,然后用来启动 appium,其实就是 mange_port.kill_port 方法,那就畅通了,所以一般不会用系统默认的端口范围(1-1024),当然,这个是可以改的,后文会提到,这里面还有个 ip 就是指当前机器的 ip,一般不是 127 那个,是真实 ip 那个,用来干嘛,其实框架是支持 android 用 selenium-gird 来做并发自动化测试的,但我不建议用这种方法,但你想用也可以,appium 和 selenium-grid 怎么用百度大把,和我之前写的那篇 web 并发测试是一样的原理,但是如果 grid 是远程的话,就要用到宿主机的真实 ip 了,所以这里启动 appium 我就不用 127 那个了,理论上也是可以的,但有长远考虑

(2017.07.)

好吧,接下来就演示一下怎么执行并发自动化测试的,我演示的时候用的是两台 iOS 设备和两台 Android 设备,也看过 web 并发那篇也知道,其实在用例上面也要做一些手脚,如下图
在 robot 上用 appium,第一个关键字无疑是 open application,那需要传入的参数主要有两个,一个是 appium 服务的地址,一个就是 udid,这样,设备和 appium 就能对应起来,默认是设备列表第一台设备指向第一个 appium(4723)服务,后面就加 1 继续指向直到所有设备都有指定的 appium 为止,这一块其实是用例执行的时候设置的,对于设备的顺序,也说一下,一般是最后连接到电脑的那台设备就是设备列表的第一台设备,以此类推吧,好用例设置的图

android:

iOS:

当然之前做并发自动化就是用到 robot 的用例标签功能来做分发了,所以也标记上

搞定了之后,就是执行自动化测试了,那第二句命令来了
android:

执行情况:

iOS:

执行情况:

第二句命令:
android:

python robot_mutil_dev.py -s /Volumes/sd_card/lunkr_test_git/AutoTest_Mutil  -t test2,test1 -o android

iOS:

python robot_mutil_dev.py -s /Volumes/sd_card/lunkr_test_git/AutoTest_Mutil  -t tag1,tag2 -o iOS

原理和之前 web 那篇是一样的,就是把参数补全

how to use it
-h   help
-s   the testsuite or testcase path
-t   taglist,likes "tag1,tag2", split by ,
-o   the device os.likes ios,android
-r   the remoteurl,use for gird

当然,你想 android 和 iOS 一起玩也是可以的

那也说说 robot_mutil_dev.py 的代码,拿 iOS 的那部分来说吧:

elif testos in ["iOS","ios"]:
    i=0
    divlist=get_info.get_devices("iOS")
    for tag in taglist:
      wdport=wdhost+str(iport)+"/wd/hub"
      #print wdport
      booll=check_server.check(ipaddr,iport)
      if booll==0:
        print "the appium server by {0} is not start,please check it".format(wdport)
        sys.exit(0)
      cmd='pybot -i {0} -o ./resultDir_ios/output-{0}.xml -l ./resultDir_ios/log-{0}.html -r ./resultDir_ios/report-{0}.html --variable remote_url:{2} --variable udid:{3} {1}'.format(tag,testsuite,wdport,divlist[i])
      p=multiprocessing.Process(target=run,args=(cmd,))
      lprocess.append(p)
      iport=iport+1
      i=i+1

wdhost 就是 appium-server 的地址,iport 就是 14723 开始的那个,在执行用例之前,通过 check_server.check 方法来检查 appium 有没有启动,没启动就不跑退出,这里怎么判断,看看 check_server.check 的代码:

#coding=utf-8
import os 
import sys
import requests
import time 

def check(ip,port):
    flag=1
    ct=0
    while(flag and ct<10):
        try:
            r = requests.get(url='http://{0}:{1}/favicon.ico'.format(ip,port))
            if r.status_code==200:
                print "the appium respone code is {0}".format(r.status_code)
                flag=0
                return 1
            else:
                ct=ct+1
                print "the appium respone code is {0}".format(r.status_code)
                print "the code is not equels 200 ,it would something wrong,please check it,,time:{0} ".format(ct)            
                time.sleep(3)
        except:
            ct=ct+1
            print "appium server is not start by port:{0},try to check again now ,time:{1}".format(port,ct)
            time.sleep(3)

    if ct==10:
         return 0

其实就是请求一下 appium 存不存在,favicon.ico 是一张草莓🍓图片,一般 appium 启动起来之后访问它返回 200 就正常了,那就可以用来判断 appium 的启动情况了,一般会检查 10 次,每 3 秒一次,因为用 jenkins 来做构建的时候也要判断一下 run_server.py 启动的 appium 成不成功,启动不成功还用跑个鬼并发自动化,所以还是得检查的,然后就是用 --variable 来把 appium 的地址和 udid 传入到测试用例当中,那就能执行并发自动化测试,对于并发,这里现在是用多进程的方法,之前 web 那篇是用多线程的,为什么这里用多进程呢,我在 mac 上面跑并发的时候一开始是用多线程尝试的,但是多线程启动之后,第二个线程不知道为什么总是要等第一个线程执行完之后才会去执行,就 mac 上面会这样,真的,我后面换成用多进程就没事了,可能和系统的资源分配有关系吧,毕竟进程间的资源是独立的,所以后面考虑到兼容用,就直接用多进程了,然后下面就是执行的代码

for p in lprocess:
       p.daemon = True
       p.start()

   for p in lprocess:
       p.join()

   if testos=='None':
      pass
   elif osplat!="Windows":
       sleep(2)
       if testos in ["iOS","ios"]:
         os.system(u"rebot --output ./resultDir_ios/output.xml  -l ./resultDir_ios/log.html -r ./resultDir_ios/report.html --merge ./resultDir_ios/output-*.xml")
       elif testos in ["Android","android"]:
         os.system(u"rebot --output ./resultDir_ad/output.xml  -l ./resultDir_ad/log.html -r ./resultDir_ad/report.html --merge ./resultDir_ad/output-*.xml")
       else:
          os.system(u"rebot --output ./resultDir/output.xml  -l ./resultDir/log.html -r ./resultDir/report.html --merge ./resultDir/output-*.xml")
   else:
       sleep(2)
       if testos in ["Android","android"]:
         os.system(u"rebot --output .\\resultDir_ad\\output.xml  -l .\\resultDir_ad\\log.html -r .\\resultDir_ad\\report.html --merge .\\resultDir_ad\\output-*.xml")
       else:  
         os.system(u"rebot --output .\\resultDir\\output.xml  -l .\\resultDir\\log.html -r .\\resultDir\\report.html --merge .\\resultDir\\output-*.xml")
   sleep(2)
   print "Test Finish"

同样的,等待所有的进程都执行完成后,就会通过 robot 的合并测试报告的方法将多个进程执行的自动化测试报告合并起来,有一些注意事项像图片的可以看Web 应用并发自动化测试,这里就不在多说了,就这样,两句命令其实就可以搞定移动端的并发自动化测试了,小框架还会根据不同的操作系统适配不同的命令,目前测试是支持 mac 和 win7,win10 我还没试,理论上是 ok 的,win7 上可以执行 android 的并发自动化测试

四、亮点和坑

坑:
1、刚才提到的端口问题,是通过 kill 掉占用的进程来释放端口,其实我一开始是想通过跳过端口的方法的,但是跳过的之后,就得找一个地方存着对应设备和对应的 appium 服务端口,而两个脚本之间是没什么关联的,我本来也可以写个配置文件来将它们关联起来,配置文件就可以对应 udid 和 appium,但这样显然有点麻烦,我还想过拔出设备的时候要不要自动 kill 掉对应的 appium 服务,那又回到上面的问题了,其实就是缺个管理平台
2、在执行并发自动化的时候,android 这边有低概率会出现安装程序包失败,其实就是刚好包被占用的问题,这边的话注意调度就用,或者把程序把分开不同地方放就好了
亮点:
1、这个是我在调试中无意发现的,就是我现在已经启动来 appium 服务,我现在只用两个 iphone 测试,其中一台我不想用了,换成 ipad,再执行自动化测试的时候无需再做任何操作,只要保证 appium 服务正常,设备连接正常,就是可以直接运行并发自动化测试了,这个亮点简单的说就是可以随意的更换测试设备而且无需做大量操作,当然 appium 服务不够怎么办,刚才提到我是会 kill 掉进程的,在运行一次第一句命令就好了

我还打算接入 macaca 的,因为之前就是写了 macaca 的 rf 库,原理是一样的,就是启动的命令差异,或者还有一些坑,后面慢慢在看吧

五、最后说说

上面的坑那里提到,我就是缺个管理平台,其实现在在我脑海里是有这个平台的 demo 的,就是一个支持 ios 和 android 执行并发自动化和专项测试等测试管理的 stf 管理平台,说到这里,对于测试方案或测试技术的设计,我提一句 “用产品的思维去做测试”,你要做一个测试方案或一个测试工具,首先你要知道这个工具的目标用户是谁,要解决用户什么问题,最后能带来什么价值,测试人员就是测试工具的用户,测试工具或方案就是用来解决测试人员在测试工作效率或者流程管理上的问题,能够带来降低测试成本和提升产品质量的价值,贴近业务,把握痛点,按照这种思路来开发测试工具、框架或方案,一般都会比较高可用。接下来的时间将花在这个管理平台上面了,我还用 Axure RP 画了个小 demo,但是要做这个平台不容易啊,我还得慢慢补充自己的技术知识和业务知识了,在 IT 这个行业混,总得弄一个能为自己代言的作品吧,嗯,这就是我接下来要做的,之前的一些技术方案,都是几天就做出来的,所以其实压根没有解决过什么根本问题,比如 mock,我见过真正的 mock 平台之后,我都不敢说我会写 mock 服务器,还是静态代码扫描,diffy 校验,docker 微服务架构自动编排,还有后面的移动端无线技术,iOS11 和 xocde9 都已经支持无线调试了,客户端无线自动化测试是必然的,还有团队在倡导的测试工程化,现在的这个,估计花 1 年甚至几年都不知道搞不搞得定,好好加油吧,说了那么多次,现在缺的就是深度,这是要一点一滴地积累吧,好吧,最后,大家如果拿去用的话,用的过程中有问题,或者是有 bug 可以在这里反馈,也可以直接到 github 上面提,谢谢大家来,欢迎大神指导,欢迎大家提建议

附录:

github 地址:
并发框架
MacacaLibrary

设计思路可以看:
浅谈测试工程化 - 以并发自动化框架为例

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 68 条回复 时间 点赞
terrychow 回复

大神,请问一个问题。IOS 环境下,如果 WDA 被重新编译了,必选要手动在手机上进行信任,不然也没有办法执行起来。如果 WDA 在执行过程中被重新编译了,我们还需要手工去信任新编译的 WDA,这样对测试效率影响比较大呢?有好的解决方案么

大神 git 地址了?

--webdriveragent-port 在启动命令新增这个指定端口就可以实现多 iOS 设备并发吗

仅楼主可见
simple [精彩盘点] TesterHome 社区 2018 年 度精华帖 中提及了此贴 01月07日 12:08
sharon 回复

这样子,在控制逻辑上,一个 appium 服务节点对应一台 udid,在这个控制好的情况下, 那空闲的判断只要看 appium 是否空闲就好,判断空闲的方法是查一下 appium 上面存不存在 session

terrychow 回复

大神,请问一下具体如何判断 udid 是否空闲呢?用的是 appium,android

simple 专栏文章:[精华帖] 社区历年精华帖分类归总 中提及了此贴 12月13日 14:44
仅楼主可见

大神,不好意思再打扰一下,最后一个问题是,并发运行的过程在最后的关闭应用(close application)这一步经常出现这个错误,请大神帮忙看一下:

==============================================================================
[ WARN ] Keyword 'Capture Page Screenshot' could not be run on failure: WebDriverException: Message: A session is either terminated or not started
case1 | FAIL |
Teardown failed:
WebDriverException: Message: An unknown server-side error occurred while processing the command. Original error: Can't stop process; it's not currently running (cmd: 'D:\Sorfware\Android SDK\android-sdk-windows\platform-tools\adb.exe')

terrychow 回复

谢谢大神的回复。我这个问题我猜测了下 是因为我在 TestSuite 的 Test Setup 设置了 打开应用(open application)导致这个测试集合下面的所有用例 都用的是用一个 udid。请问您是在 每个测试用例 单独设置 open application 吗?

赞!!!先收藏,有时间试试

看看 appium 的日志,检查一下分配的测试用例对应设备的 udid 是不是没替换哈,链路是用例上这个点要配好,然后脚本会读取设备列表分发到不同的 appium 然后执行用例

大神,我用两台 android 手机,基本上按照您上面的照着做了,但是运行的时候,两个 appium server 都连到了同一个手机上了(两个 appium server 都有反应,但只有一个手机在运行),请问是怎么回事呢

tomweng 回复

用 robot_mutil_test.py 吧,版本有更新的,AutoTest_Mutil 是个目录名字而已

请问一下大神,python robot_mutil_dev.py -s /Volumes/sd_card/lunkr_test_git/AutoTest_Mutil -t test2,test1 -o android 这一个命令中的 robot_mutil_dev.py 在您的 github 上找不到这个文件,另外 AutoTest_Mutil 这个又是什么呢?

这个我也感兴趣 有时间仔细看看 学习学习

哪一台设备是两个方法,简单的,设备的 udid 排序是最后一台连接电脑的设备会显示在第一行,所以连接顺序的话自己控制好就行,第二种没去做过滤,所以先不讲了,是可以在一大段设备管理信息里面找到的,空不空闲,如果是 appium 的话你检查一下 session,看看有没有对应 udid 的 session 是启动中的,http 请求,如果有就是正在运行的,没有就是空闲的,试试吧

59楼 已删除

@terrychow LZ 这两天我拼命的整 iOS 并发测试,想向 LZ 请教一下😳

通过iOS:idevice_id –l获取到 Mac 链接的设备 UDID,但是如何自动获取哪一个设备的 UDID 呢?又如何知道该设备此时空闲呢?

57楼 已删除
ssx 回复

个人信息那里有

楼主微信多少!!可以说下嘛

你的问题我也遇到过,估计你有可能比较多用 xpath 定位吧,每台手机上同一个应用的 xpath 是有所差异的,我之前在 iPad 上定位的元素在 iphone 上定位不了的,对于 xpath 的定位,我用自底而上的方法,就是用最深的那一层先匹配,因为这层上必定匹配到的,然后一层层上来,这是为了降低查询效率,最后匹配到这几台机器都能识别到的 xpath 路径,对于滞后的问题,涉及网络层和硬件层,我只能说可以优化,因为这可能要去优化 wda,adb 等支撑模块

在运行四台以上真机并发测试的时候,总是发现除了两三台正常跑以外其他机器总会发生打开应用滞后或者干脆识别不到元素的情况,求解

terrychow 浅谈测试工程化 - 以并发自动化框架为例 中提及了此贴 08月12日 22:21

(2017.08.05 更新)
1、修复在 windows 上执行的 bug
2、增加-d 参数,可选择从第 n 台设备开始执行自动化测试,配合-p 和-sp 参数使用
3、已支持 ios,android,web,api 的并发自动化
脚本化的框架应该到此为止了,接下来会转入对平台的研究、无线连接和空闲机器调度策略上

玄月指光 回复

检查一下真机设备的模拟事件开关开启了没,没有的话是跑不了自动化的,第二个,windows 上跑还有个小 bug,今天再更新一个班

在 Android 真机 测试时,报这个错误,(selenium.common.exceptions.WebDriverException: Message: An unknown server-side error occurred while processing the command. Original error: Could not find a connected Android device.
)如何处理?,在 PC 端用 adb devices 查看 是连接的

(2017.8.1 更新)
1、支持 web 端结合 sele-grid 的并发自动化测试,结合 docker 使用,具体请参考Web 应用并发自动化测试,具体命令:

python robot_mutil_test.py -s /Volumes/sd_card/lunkr_test_git/Web_AutoTest_Mutil -o web -r http://127.0.0.1:4444/wd/hub -t local,node1,node2

2、修复部分在 windows 上执行的 bug
3、修改 github 路径:https://github.com/wqzhou0208/rf_mutil_test

雨落天涯 回复

appium 运行过程中有做这一步,判断模拟器里面有没有 webdriveragent,有的话就直接启动,没有的话就 build 进去再启动,你可以看看日志,具体哪里命令我忘了,我之前也试过直接掉 webdrvieragent,看日志有,一般 build:

cd  /usr/local/lib/node_modules/appium/node_modules/appium-xcuitest-driver/WebDriverAgent
xcodebuild -project WebDriverAgent.xcodeproj -scheme WebDriverAgentRunner -destination 'id=真机的udid 或 模拟器的名称还是id(要看看才记得)' test
terrychow 回复

有命令能一块把设备或者模拟器中的 webDriver 安装启动呢?

45楼 已删除
雨落天涯 回复

是啊,前文也提到要用 1.6.5 及以后支持的

terrychow 回复

我用的是 1.6.4 呢

雨落天涯 回复

你用的是什么版本 1.6.5 可以,如果不支持的话我怎么跑起来

41楼 已删除

appium -p $1 --webdriveragent-port $2 -a $3 --platform-name iOS --automation-name XCUITest
--webdriveragent-port 这个参数不支持吧
http://appium.io/slate/en/master/?ruby#server-flags

39楼 已删除
38楼 已删除
沙子 回复

前者的话还没试,框架主要用于真机并发,后者的话我自己试过直接拔出,秒级干掉设备 udid,如果有这个坑的话我试试看有什么场景会这样子

获取 iOS 的设备 udid,用idevice_id -l 获取到的应该是所有连过电脑的 iOS 设备的 udid 吧 可能还有模拟器的,拔掉其中某个设备后可能还能获取到这个设备的 udid, 有没有这样的问题?

terrychow 回复

受教了👍

terrychow 回复

算是找不到太好的方法的时候的一个临时方案,后续做成分布式的时候再找其他的方式吧!

小弥勒 回复

apk 的坑我也遇到,你这种处理是个办法,顺序初始化也还好吧,只要不是后线程要等前线程结束后再初始化就应该没大问题

terrychow 回复

Ios 不清楚,android 多线程并发遇到的问题出在实例化 driver 的位置,在同时调用 adb 的时候同时处理一个 apk 文件时出错,现在的解决方法是实例化 driver 的时候加了一个线程锁,appium server 同时启动,但是 driver 顺序初始化!

小弥勒 回复

再提个点,并发用多进程,尽量不要用多线程,多线程在 Mac 会被前线程阻塞,我还在了解是什么原因,进程就没事

terrychow 回复

OK,谢谢大神,一会儿重新检查代码

小弥勒 回复

保证 wdabuild 是成功的,第二个看是用的端口,包括 appium 服务和 wda 转发的对不对得上设备

terrychow 回复

Udid 唯一,appium 端口是随机取系统闲置端口,不存在端口的问题,按照当前的设备实例化线程,android 就没有问题,iOS 就是不行,我查了好像 appium 就不支持 ios 多设备并行,所以看到你这跑起来了就特别感兴趣,不清楚我的在哪个位置出错了!

(2017.7.27 更新)
1、新增一个脚本连接启动服务和测试执行,一句命令即可搞定整个并发自动化流程,但考虑到有其他接入,只在 wqzhou 分支更新,未在 master 更新
2、新增参数-p 和-sp,为起始的服务端口和转发端口,以其开始 +1 启动
3、去除对 grid 方式的支持
命令如下:

how to use it
-h   help
-s   the testsuite or testcase path
-t   taglist,likes "tag1,tag2", split by ,
-o   the device os.likes ios,android
-p   server port
-sp  second server port
-n   the num of start server
python one_step_mutil.py -s /Volumes/sd_card/lunkr_test_git/iOS_AutoTest_Mutil -t tag1,tag2 -o ios -p 14000 -sp 15000 -n 2

运行例示:

小弥勒 回复

就是两个问题:1、udid 分发的 appium 是否唯一,2、appium 所占用的端口

之前也这样搞过,android 这样没问题,但是 ios 多设备好像不行,也是这种设计当时,针对每一个 ios 设备起一个 appiumserver ,只能跑起来一个,所以不知道我的那个哪儿有问题了!

(2017.07.26 更新)假如再次执行 run_server.py 启动 appium 服务时,本来已经存在了如占用 4723 端口的 appium,考虑到没必要去 kill 掉已启动好的 appium,所以做了跳过处理,同时也把设备列表的顺序换过来,改成按连接电脑的顺序排序,这样做有什么好处,看下图

就是刚好遇到已经有设备在运行,你又想再插入多一台设备而不影响另外的设备的执行,就这么做了,当然接下来也会把启动服务和执行用例的起始端口作参数化,方便分批启动服务和分批运行

Jay_ 回复

大神有何高见,看看说说我能不能优化一下

不好,简单的事复杂化了

有兴趣的话一起弄,其实既然 ios 的实时同屏已经可以实现的话,对应操作方面可以利用 wd 作为连接的中间件,而且比较利好的是 xcode9 和 ios11 之后的无线技术,所以说实现一个 ios 版的 stf 技术上也已经不是什么大难题了,关键是有没有人去做,不过首先把 stf 研究好先,还要花很多时间慢慢研究呢

😂 最近也在搞类似这个,不过我是 java testng ,所以 mac 下 iOS 没整出来并发执行
然后你说的管理平台,我也有类似的想法,stf 也搭起来了,但是整个想法还是比较模糊

许伟栋 回复

是可以啊,本来一个窗口就可以多个进程在里面运行,用例的并行就是这么实现的,但是,你把全部的 appium 都放到一个窗口的话,调试看日志什么的或许有点麻烦吧

非多窗口启动 appium 服务的话应该也可以实现并行,我记得可以写多个 testng 配置文件,这两者有什么区别?

adonisjph 回复

我一开始就是用-U 做的,但后面觉得没必要,你可以看看我后面的解释或截图,还有我今晚再加个功能,不用-U 的形式会更加灵活

有个疑问,获取到的 udid,是在哪里用到的,在用例里吗,不是应该直接在启动 appium 服务时通过-U 的参数指定吗

adonisjph 回复

好,现在 java 和 python 切来切去有点乱,我去改一下


这里可以不用定义 t 的值的,去掉没关系,range 的话会从 0 至 num-1

adonisjph 回复

设备相关的当然可以这么做,我里面那个 adb_helper 完全可以支持,就想多了点看看有没有其他朋友会输入自己特定的参数,刚好你提醒了我一下

terrychow 回复

直接通过 adb 命令获取相关设备的参数然后传入到你的代码里比较好吧,如果手动输入的话,比较麻烦感觉

adonisjph 回复

像你这种需求的话,我这边可以看看是否加多一个 capabilities 的输入,能解决一些特定需求参数的问题

adonisjph 回复

其实不用的,最关键就是 udid,当然,需要操作系统的话还是可以填一下,当标签,我连 devicename 都是随机字符串,仅可能的简化操作,还是看具体需求吧,就是 udid 不能缺

还有个问题,我记得 appium 的话是要指定相应机子的安卓系统版本的吧,代码里没看到有这个操作呀

adonisjph 回复

不用,这个问题我之前还问过别人,后面自己试过了是不用 root 的

无线测试的话,安卓好像得有 root 权限才可以

很棒,学习了,谢谢楼主 share!

思寒_seveniruby 将本帖设为了精华贴 07月24日 23:47
CC 回复

有兴趣的话拿去试一下,有 bug 和我提一下哈。刚好在收集需求,想做个平台

看起来还不错,赞

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

thanksdanny 回复

有问题的话给我提 issue 哈,谢谢

学习了!我也试试先!!

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册