51Testing软件测试论坛

 找回密码
 (注-册)加入51Testing

QQ登录

只需一步,快速开始

微信登录,快人一步

手机号码,快捷登录

查看: 2131|回复: 1
打印 上一主题 下一主题

[转贴] 搭建UI自动化测试框架(Appium)

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2019-4-8 14:11:25 | 只看该作者 回帖奖励 |正序浏览 |阅读模式
  1. 对测试人员来说,总有很多重复的手工测试工作,枯燥无味且没有成就感。要是能用机器来代替部分重复劳动,解放双手去做别的重要的事情该多好。
复制代码


最接近模拟手工操作的,是UI自动化测试。虽然不如接口测试那么稳定,不如单元测试那么精准。但也能解放下双手,提高效率。

对测试人员来说,很多回归测试,并不能发现啥问题,但不去测,又不放心。万一出现bug了呢?
 很多人会怀疑UI自动化测试的成果。你写了那么久,跑起来也没见找到bug。
 不能单盯着bug数量的多少,对质量保障来说,没有发现bug也是个成果。
 测试了,但是没有bug,不能说明没有成绩,说明质量是有保证的。
这些任务可以交给UI自动化测试去完成。跑的次数越多,节约的人工成本越多。

好了,言归正传,我们来谈谈UI automation 框架的搭建。
搭建框架前,我们先考虑几个问题:

产品特性:产品是否是框架式的,几个产品是否复用一套框架?(一般内容为主的产品,都采用框架式的编码,app只是个载体,如果这样,几个产品可以共用一套测试框架)

可行性: 产品是否长期迭代?是否已经稳定?对于短期项目,写脚本没什么意义。可能你脚本还没写完,产品都退市了,一点意义都没有。
如果产品还不稳定,不停地改结构,那样脚本维护成本也很大,也没啥意义。
产品是否适合用UI automation来跑?原生比例占多大?元素是否好定位?
如果可行性不考虑清楚,后面的风险就比较大,脚本设计和维护的成本也比较高。

复用性:如果有个新的项目,你的框架小改是不是也能用在新项目上?如果一个框架都复用性很差,那么它是失败的。

组织结构:Case 如何组织? 如何展示报告?异常处理怎么处理等等,都是心里要有数的。

扩展性: 是否兼容 Android, IOS? phone, tablet? 是否可以多机一起跑?是否可以监控性能?

资源:包括时间资源,人手,公司的支持度。还有检查多少功能点?写多大规模?啥时候写?都要考虑清楚。



本人就以Appium为例,结合自己的实践,谈谈mobile的UI automation框架搭建。

先普及下基础知识
现在appium 用的是 appium desktop



现在谈谈appium里面的几个角色和关系:

Devices 和sever, driver 是一对一的关系,有几个devices,就要起几个server, driver


Build 和 driver, device 是一对多的关系, 一个build 和一个device 组合成一个driver, 可以跑在多台devices上。


Server  和 driver 是一对一关系,通过port, bp来映射关系和通行。


Device 和 case是多对多关系,为了简单,我们把case放suite 里面,组成一对一关系。


从上可以看出,Devices是关键,可以把参数都绑定在device上。
代码可以这么写:
  1. def get_devices_version(device):
  2.    cmd = "adb -s {} shell getprop ro.build.version.release".format(device)
  3.    result = run_command_on_shell(cmd)[0]
  4.    return result

  5. def get_devices_name(device):
  6.    cmd = "adb -s {} shell getprop ro.product.model".format(device)
  7.    result = run_command_on_shell(cmd)[0]
  8.    return result

  9. def list_devices():
  10.    cmd = "adb devices"
  11.    result = run_command_on_shell(cmd)
  12.    print(result)
  13.    return result

  14. def get_devices_info():
  15.    current = list_devices()
  16.    devices = []
  17.    j = 0
  18.    port= 4723
  19.    bootstrap = 5000
  20.    for i in current[1:]:
  21.        if i != "":
  22.            each_device = {}
  23.            nPos = i.index("\t")
  24.            dev = i[:nPos]
  25.            each_device["id"] = dev
  26.            each_device["version"] = get_devices_version(dev)
  27.            each_device["name"] = get_devices_name(dev)
  28.            each_device["port"]= port + j
  29.            each_device["bootstrap"] = bootstrap + j
  30.            each_device["username"]= YAML().get_users()[j]
  31.            devices.append(each_device)
  32.            j = j + 1
  33.    return devices
复制代码


不管接入多少台设备,都能获取。(当然是同一平台。不能IOS,Android混插,phone,tablet混合)

看看server,可以这么写:
  1. CMD = 'appium -a {} -p {} --bootstrap-port {} --session-override --command-timeout 600 -U {} >{} '

  2. def close_appium_server():
  3.    kill_progress_by_name("node")

  4. def start_appium_server(device):
  5.    host = "0.0.0.0"
  6.    port = device['port']
  7.    bootstrap_port = device['bootstrap']
  8.    udid = device['id']
  9.    appium_log = log_dir + "/" + "server.log"

  10.    cmd = CMD.format(host,port,bootstrap_port,udid,appium_log)
  11.    run_command_on_shell(cmd)
复制代码

现在开始组合driver了。
  1. def Base(device):
  2.    capabilities = YAML().get_appium_config()

  3.    if PLATFORM == 'Android':
  4.        capabilities['app'] = AppPath.get_app_filename(build_path)
  5.        capabilities['platformVersion'] = device["version"]
  6.        capabilities['deviceName'] = device["name"]
  7.        capabilities['udid'] = device["id"]
  8.        driver = webdriver.Remote('http://localhost:{}/wd/hub'.format(device['port']), capabilities)
复制代码


Case这块,你想怎么组织,就怎么组织了,个人推荐用pageobject模式。
好了,大功告成,调用起来试试。
  1. if __name__ == '__main__':
  2.    close_appium_server()
  3.    check_folder(log_dir)
  4.    jenkins = Jenkins(build_path)
  5.    jenkins.download_build()
  6.    get_devices_info()

  7.    if get_devices_info():
  8.        pool = Pool(len(get_devices_info()))
  9.        pool.map(start_appium_server,get_devices_info())
  10.        pool.close()
  11.        pool.join()

  12.        pool2 = Pool(len(get_devices_info()))
  13.        pool2.map(login,get_devices_info())
  14.        pool2.close()
  15.        pool2.join()
复制代码

大体就是这样子。UI测试就是不大稳定,尤其是xpath用得比较多的时候,还有就是系统的各种弹出框的处理等。都是比较棘手的。
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1
回复

使用道具 举报

本版积分规则

关闭

站长推荐上一条 /1 下一条

小黑屋|手机版|Archiver|51Testing软件测试网 ( 沪ICP备05003035号 关于我们

GMT+8, 2024-11-18 14:43 , Processed in 0.067122 second(s), 23 queries .

Powered by Discuz! X3.2

© 2001-2024 Comsenz Inc.

快速回复 返回顶部 返回列表