自动化之旅--Appium
目录:
概述
为了避免每次上线前重复的人工回归测试,保证每次上线的版本不会引起核心业务的不稳定,所以急需自动化测试来保证业务的稳定性.经过调研我尝试使用Appium进行自动化测试,原因是功能强大,跨平台而且社区也很活跃.
主流框架对比
Appium优点
- 开源
- 跨架构:Native App、Hybird App、Web App
- 跨设备:Android、iOS、Firefox OS
- 不依赖源码
- 使用任何 WebDriver 兼容的语言来编写测试用例。比如 Java, Objective-C, JavaScript with Node.js (in both callback and yield-based flavours), PHP, Python, Ruby, C#, Clojure, 或者 Perl.
- 不需要重新编译APP
如果有不清楚WebDriver的小伙伴马上在Appium架构介绍中会有说明.
Appium理念
- 你无需为了自动化,而重新编译或者修改你的应用。
- 你不必局限于某种语言或者框架来写和运行测试脚本。
- 一个移动自动化的框架不应该在接口上重复造轮子。(移动自动化的接口应该统一)
- 无论是精神上,还是名义上,都必须开源。
Appium架构
iOS: 苹果的UIAutomation
Android 4.2+: Google的UiAutomator
Android 2.3+: Google's Instrumentation. (由单独的项目Selendroid提供支持 )
Appium 1.6版本以上增加了UiAutomator2
为了满足上面跨平台,把这些三方框架封装成一套API —— WebDriver Api(客户端到服务端的协议)
事实上 WebDriver 已经成为 web 浏览器自动化的标准,也成了 W3C 的标准 —— W3C Working Draft,所以Appium在原有基础上扩充了移动自动化相关的API.
投资 WebDriver 意味着你可以押宝在一个已经成为标准的独立,自由和开放的协议。你不会被任何专利限制。
核心架构: Appium使用C/S架构,运行时候Service端会监听Client端发送的命令,接着在移动设备上执行这些命令,然后将执行结果放在 HTTP 响应中返还给客户端.
基于这架构可以做什么?
- 可以用任何实现了该客户端的语言来写测试代码
- 可以把服务端放在不同的机器上
- 可以只写测试代码,然后利用类似 saucelabs 云服务来解释命令.
下图解释了云服务的具体作用:
海量免费学习资料,软件测试交流:1140267353,还会有同行一起技术交流)
Appium 使用
服务端
安装Appium服务器
npm install -g appiumnpm install -g appium-doctorappium-doctor 复制代码
其中appium-doctor
用来检查电脑是否缺少相关依赖.当所有都是对勾表示Appium环境配置完毕,如下:
开启appium服务器:
appium --address 127.0.0.1 --port 4723 --log "/Users/mio4kon/Desktop/appium.log" --log-timestamp --local-timezone --session-override 复制代码
客户端
再次强调 Appium
支持各种语言,这里我选择JAVA.如果觉得JAVA语法不够简洁或者不熟悉,可以使用你所熟悉的语言.
创建 MAVEN/Gradle 工程:
创建工程,并加入下面依赖:
<dependency><groupId>io.appium</groupId><artifactId>java-client</artifactId><version>5.0.0-BETA2</version><exclusions><exclusion><groupId>org.seleniumhq.selenium</groupId><artifactId>selenium-java</artifactId></exclusion></exclusions></dependency><dependency><groupId>org.seleniumhq.selenium</groupId><artifactId>selenium-java</artifactId><version>3.0.1</version></dependency>
复制代码
这样Appium 客户端的依赖就引入成功了.
Capabiltiy配置:
每个Test的基类中定义setUp
方法,并设置Capabiltiy
以前其他的初始化操作:
DesiredCapabilities capabilities = new DesiredCapabilities ();
capabilities.setCapability (MobileCapabilityType.DEVICE_NAME, deviceName);
capabilities.setCapability (MobileCapabilityType.PLATFORM_NAME, platformName);
capabilities.setCapability (MobileCapabilityType.PLATFORM_VERSION, platformVersion);
capabilities.setCapability (MobileCapabilityType.APP, apkPath);
capabilities.setCapability (AndroidMobileCapabilityType.APP_PACKAGE, appPackage);
capabilities.setCapability (AndroidMobileCapabilityType.APP_ACTIVITY, appActivity);
capabilities.setCapability (MobileCapabilityType.AUTOMATION_NAME, AutomationName.ANDROID_UIAUTOMATOR2);复制代码
这里我使用的是 TestNG 中的Parameters
注释来配置参数.
TestNG 又是什么鬼? 简单来说TestNG是java的一个测试框架,类似JUnit但功能更加强大,使用也方便.
TestNG
利用TestNg的一些注释,做准备化和收尾操作.
上面的setUp
方法我就使用了BeforeClass
和Parameters
这两种注释.
@BeforeClass@Parameters({"driverName", "url", "deviceName", "platformName", "platformVersion", "apkPath", "appPackage", "appActivity"})public void setUp(String driverName, String url, String deviceName,String platformName, String platformVersion, String apkPath,String appPackage, String appActivity) throws Exception {log.i (TAG, "BeforeClass");driver = setRemoteDriver (driverName, url, deviceName, platformName, platformVersion, apkPath, appPackage, appActivity);actions = ElementActions.getInstance ().init (driver);assertActions = actions.getAssertActions ();Screenshot.getInstance ().init (driver);prepare ();}
复制代码
同样在在AfterClass
后,进行了driver
的退出.
正常情况下我们写测试用例是下面这种情况:
一个TestClass
中包含多个TestMethod
.如果每个TestMethod
都相互独立,需要重新运行APP显然非常耗时,所以这里我将每一个TestClass
相互独立,而其中的TestMethod
又相互依赖,执行顺序通过TestNG
的XML来控制.如下:
<test name="XX测试"><classes><class name="XXTest"><methods><include name="testAAA"/><include name="testBBB"/><include name="testCCC"/></methods></class></classes></test>
复制代码
但是有些情况如果需要TestMethod
也相互独立的话,可以利用AfterMethod
注释.
@AfterMethodpublic void afterMethod() {driver.resetApp ();}
复制代码
编写用例
查找元素
定位方式
查找元素可以通过很多方法(可以通过UIAutomatorViewer
获取页面的id,name等信息):
- id
- name
- className
- xpath
- uiautomator
高级定位
用
xpath
查找登录按钮:by.xpath ("//button[@name='login']") 复制代码
xpath实例教程
- 用
uiautomator
的API滚动查找:海量免费学习资料,软件测试交流:1140267353,还会有同行一起技术交流
String rule = "new UiScrollable(new UiSelector().scrollable(true)).scrollIntoView(new UiSelector().textContains(\"" + locator.value + "\"))"WebElement cl = driver.findElementByAndroidUIAutomator(rule));
复制代码
其实就是用如果用uiautomator来写:
new UiScrollable(new UiSelector().scrollable(true)).scrollIntoView(new UiSelector().textContains(value));
复制代码
uiautomator API
### 元素管理
复制代码
为了让测试用例能够方便复用,简化写用例的时间,必要的封装是不可少的. 利用 Page Object 模式将页面上的元素进行封装.这样所有 Test 只需要简单的控制页面元素即可.
- 可以使用yaml文件进行管理页面元素:
然后在BasePage中将yaml解析封装成Locator
对象.并保存到集合.
这样所有的PageObject都可以通过下面方法来定位元素.
protected Locator getLocator(String locatorName) {checkNotNull (locatorName);Page page = getPage ();List<Locator> locators = page.locators;for(Locator locator : locators) {if (locatorName.equals (locator.name)) {return locator;}}return null;}public Locator 请输入手机号 = getLocator ("请输入手机号");
public Locator 请输入验证码 = getLocator ("请输入验证码");
public Locator 发送验证码 = getLocator ("发送验证码");复制代码
TODO: 用工具生成对应page类
之所这么做是可以在用的时候直接通过IDE提示有哪些控件,但是写上述代码缺都是无聊的操作,所有我用了 freemarker 自动解析yaml来生成对应Page类,如下:
Map<String, Object> input = new HashMap<String, Object> ();input.put ("pageName", page.pageName);List<LocatorObject> genLocators = new ArrayList<> ();List<Locator> locators = page.locators;for(int i = 0; i < locators.size (); i++) {System.out.println ("生成Locator:" + locators.get (i).name);genLocators.add (new LocatorObject (locators.get (i).name, locators.get (i).name));}input.put ("locators", genLocators);Template template = cfg.getTemplate ("page-temp.ftl");Writer fileWriter = new FileWriter (new File (path, page.pageName + ".java"));try {template.process (input, fileWriter);} finally {fileWriter.close ();}
复制代码
如果不会用 freemarker
的可以搜索下相关资料.
元素交互
将交互事件,封装在ElementActions
中.使用起来非常简单:
actions.text (loginPage.请输入手机号, phone);
actions.click (loginPage.发送验证码);
actions.text (loginPage.请输入验证码, pwd);
actions.click (loginPage.登录);
复制代码
常用的交互事件:单击,连击,上下左右滑动,后退,输入文本等等.
上面元素定位其实只是封装Locator,并没有真正的查找元素,查找元素实际上是在ElementActions
中处理的.由于应用经常处理网络请求,控件有时候需要过段时间才可见,所以在查找控件时候需要给予一定的时间.
WebElement element;try {element = (new WebDriverWait (mDriver, locator.timeOutInSeconds)).until (new ExpectedCondition<WebElement> () {@Overridepublic WebElement apply(WebDriver driver) {List<WebElement> elements = getElement (locator);if (elements.size () != 0) {return elements.get (0);}return null;}});} catch (NoSuchElementException | TimeoutException e) {log.e (TAG, "超时[%4$d秒],找不到元素:[%1$s] , [By.%2$s : %3$s]", locator.name, locator.type, locator.value, locator.timeOutInSeconds);throw e;}
复制代码
断言
同样为了使用方便讲常用的断言封装,如Toast验证等.
public void validatesToast(final String msg) {checkNotNull (msg);final WebDriverWait wait = new WebDriverWait (mDriver, 10);assertNotNull (wait.until (ExpectedConditions.presenceOfElementLocated (By.xpath (String.format ("//*[@text=\'%s\']", msg)))));}复制代码
测试报告
测试报告可以直观的展示测试的成功率,截图等信息.这里选择extentreports做为测试报告的框架.
最终效果:
踩坑
findElementByName
无效.
Searching by name was deprecated over a year ago and removed from 1.5. In general, searching by accessibility id is better for a variety of reasons.
如上findElementByName
这个方法从Appium 1.5
之后删除了,但是API不经能找到并且也没提示过时.这不坑爹嘛.后来使用下面的代码才解决用name查找元素的方法.
String query = "new UiSelector().textContains" + "(\"" + locator.value + "\")";webElements = mDriver.findElementsByAndroidUIAutomator (query);
复制代码
- 据说
Appium 1.6.3
可以查找 Toast 的信息了.然后屁颠屁颠的跑去试了下网上的例子发现不好使啊.一度以为是Client版本的问题.搞了半天才发现需要加下面的代码:
capabilities.setCapability (MobileCapabilityType.AUTOMATION_NAME, AutomationName.ANDROID_UIAUTOMATOR2);
复制代码
(感觉现在的Appium文档不全而且有点乱
- 无意中发现测试的时候高德地图弹Toast报错.然后直接编译安装却不保存.猜测是不是在安装过程中Appium改了啥.看了下Service日志,竟然在安装的时候重新签名...
App not signed with debug cert.
2017-02-13 18:17:19:848 - info: [debug] [ADB] Resigning apk.
2017-02-13 18:17:23:938 - info: [debug] [ADB] Zip-aligning 'app-debug.apk'
2017-02-13 18:17:23:958 - info: [ADB] Checking whether zipalign is present
2017-02-13 18:17:23:964 - info: [ADB] Using zipalign from /Users/mio4kon/Library/Android/sdk/build-tools/25.0.2/zipalign
2017-02-13 18:17:23:968 - info: [debug] [ADB] Zip-aligning apk.
2017-02-13 18:17:24:104 - info: [AndroidDriver] Remote apk path is /data/local/tmp/463eb03788048b4a1dacfe28545ee76e.apk
复制代码
解决方法:
capabilities.setCapability (AndroidMobileCapabilityType.NO_SIGN, true);
最后感谢大家的观看,如果对自动化感兴趣请点赞关注收藏!!!
里面有自动化测试学习资料,面试宝典等等,还有测试大牛就交流。
自动化之旅--Appium相关推荐
- 美团Android自动化之旅—适配渠道包
概述 前一篇文章(美团Android自动化之旅-生成渠道包)介绍了Android中几种生成渠道包的方式,基本解决了打包慢的问题. 但是,随着渠道越来越多,不同渠道对应用的要求也不尽相同.例如,有的渠道 ...
- python docker自动化_「docker实战篇」python的docker爬虫技术-移动自动化控制工具appium工具(17)...
原创文章,欢迎转载.转载请注明:转载自 IT人故事会,谢谢! 原文链接地址: 「docker实战篇」python的docker爬虫技术-移动自动化控制工具appium工具(17) Appium是一个开 ...
- 自动化测试之路 —— Appium安装教程
阅读目录 1.目的 2.说明 3.环境准备 3.1 安装nodejs 3.2 安装JDK 3.3 安装Android SDK 4. 安装Appium 4.1 下载 4.2 安装 4.3 启动 4.4 ...
- Android自动化之旅—生成渠道包
概述 每当发新版本时,美团团购Android客户端会被分发到各个应用市场,比如豌豆荚,360手机助手等.为了统计这些市场的效果(活跃数,下单数等),需要有一种方法来唯一标识它们. 团购客户端目前通过渠 ...
- 美团Android自动化之旅—生成渠道包
每当发新版本时,美团团购Android客户端会被分发到各个应用市场,比如豌豆荚,360手机助手等.为了统计这些市场的效果(活跃数,下单数等),需要有一种方法来唯一标识它们. 团购客户端目前通过渠道号( ...
- APP自动化学习之appium认识
系列文章目录 文章目录 系列文章目录 前言 1. 安装Java 2. 安装SDK 2.1 下载 2.2 解压 2.3 脚本升级 2.4 配置环境变量 3. 安装Appium 3.使用 4. 元素定位与 ...
- APP自动化基础之appium
appium介绍 什么是appium? (官方)appium是一个开源的测试自动化框架,可以与原生的.混合的和移动的web应用程序一起使用.它使用webDriver协议驱动ios.android.wi ...
- 自动化工具之Appium工具简单介绍
背景 自动化,性能测试,接口测试,开发平台等工作,到底测试的价值在哪里,其实价值来源不断充实与为大众服务,今天简单介绍ui小工具appium攻击. 简单介绍 Appium 是一个自动化测试开源工具,支 ...
- python手机自动化截图_Python Appium自动化测试 屏幕截图
Time will tell. 在实际自动化项目运行过程中,很多时候 App 可以会出现各种异常,为了更好的定位问题,除了捕捉日志我们还需要对运行时的设备状态来进行截屏,从而达到一种 "有图 ...
最新文章
- 夯实JavaScript基础之prototype, __proto__, instanceof
- Java对异常处理或抛出之后,后面代码会不会再执行?
- VTK修炼之道50:图形基本操作进阶_网格模型的特征边 与 封闭性检测
- 【转】java单例模式的实现
- 9.数据库中的子查询
- 菜鸟linux的sed,Linux sed命令菜鸟入门
- python3学习笔记 雨痕_Python 3 学习笔记:数字和布尔
- 把一个sql where表达式转化为一个二叉树
- 两个系统交互方式有几种_创新性OriginOS系统,打造个性化交互方式,很给力
- html5抖动效果代码,JS文字抖动特效代码
- dpdk X710 VF reset
- ArcGIS 地类净面积计算工具
- GoFrame+vue的前后端分离开源项目
- 气象信息无线监测采集系统
- PMP子过程定义总结
- 想做IT行业项目管理,面向客户方向的,考ITIL和PMP哪个更好一些?
- 亲测有效sudo: /etc/sudoers is world writable sudo: no valid sudoers sources found, quitting sudo: una
- 强化学习 11 —— REINFORCE 算法推导与 tensorflow2.0 代码实现
- Java课程设计-图书借阅管理系统
- 南京计算机与软件学院,南京信息工程大学 计算机与软件学院 刘 琦