用Appium让Android功能自动化测试飞起来

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 24.0px "Helvetica Neue"; color: #2f2f2f }
p.p2 { margin: 0.0px 0.0px 0.0px 0.0px; font: 16.0px "Helvetica Neue"; color: #2f2f2f }
p.p3 { margin: 0.0px 0.0px 0.0px 0.0px; text-align: center; font: 16.0px "Helvetica Neue"; color: #2f2f2f; min-height: 18.0px }
p.p4 { margin: 0.0px 0.0px 0.0px 0.0px; text-align: center; font: 14.0px "Helvetica Neue"; color: #969696 }
p.p5 { margin: 0.0px 0.0px 0.0px 0.0px; font: 16.0px "Helvetica Neue"; color: #3294d0 }
p.p6 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Menlo; color: #61aeee; background-color: #282c34 }
p.p7 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Menlo; color: #abb2bf; background-color: #282c34 }
p.p8 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Menlo; color: #abb2bf }
p.p9 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Menlo; color: #98c379; background-color: #282c34 }
p.p10 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Menlo; color: #c678dd; background-color: #282c34 }
p.p11 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Menlo; color: #61aeee; background-color: #f6f6f6 }
p.p12 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Menlo; color: #5c6370; background-color: #f6f6f6 }
p.p13 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Menlo; color: #abb2bf; background-color: #f6f6f6 }
p.p14 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Menlo; color: #e6c07b; background-color: #282c34 }
p.p15 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Menlo; color: #5c6370; background-color: #282c34 }
p.p16 { margin: 0.0px 0.0px 0.0px 0.0px; font: 16.0px "Helvetica Neue"; color: #4f4f4f }
p.p17 { margin: 0.0px 0.0px 0.0px 0.0px; font: 16.0px "Helvetica Neue"; color: #4f4f4f; min-height: 18.0px }
li.li2 { margin: 0.0px 0.0px 0.0px 0.0px; font: 16.0px "Helvetica Neue"; color: #2f2f2f }
span.s1 { }
span.s2 { font: 16.0px "Helvetica Neue"; color: #3294d0 }
span.s3 { color: #c678dd }
span.s4 { color: #abb2bf }
span.s5 { color: #98c379 }
span.s6 { background-color: #282c34 }
span.s7 { color: #e6c07b }
span.s8 { color: #d19a65 }
span.s9 { background-color: #f6f6f6 }
span.s10 { color: #d19a65; background-color: #f6f6f6 }
span.s11 { color: #61aeee }
span.s12 { color: #5c6370 }
ul.ul1 { list-style-type: none }

前言

做Android端功能自动化已有2年多的时间了,使用过的功能自动化框架有Robotium、Uiautomator、Appium。最近研究自动化case复用的方案,调研了Appium的自动化框架,并将其应用到银行一账通的标版中,本文详细介绍基于Appium的Android功能自动化实战经验。主要包括以下几方面内容:

  • Appium框架原理介绍
  • Appium框架常用API介绍
  • 基于Appium框架的自动化开发环境搭建
  • 自动化case开发及分层结构设计
  • 自动化测试用例书写规范及注意事项
  • 功能自动化接入持续集成方案

Android常用功能自动化框架比较

下表给出Robotium、Uiautomator、Appium三种框架的比较。

了解各个自动化框架的特性,结合产品自身特点,选取一个合适的框架尤为重要。

Paste_Image.png

Appium框架原理介绍

Appium 是一个开源、跨平台的自动化测试工具,用于测试原生和轻量移动应用,支持iOS, Android 和 FirefoxOS 平台。Appium 驱动苹果的 UIAutomation 库和 Android 的 UiAutomator 框架,使用 Selenium 的 WebDriver JSON 协议。下图是Appium在Android端的原理架构图

Paste_Image.png

从图中可以看出,Appium Client是对webdriver原生api的一些扩展和封装,它配合原生的webdriver来使用,二者缺一不可。Appium Server有两个主要功能:首先它作为一个http服务器端,接收从Appium Client发送过来的命令(可以认为是case中的具体操作)。其次,它作为bootstrap客户端,在接收Client的命令后,通过socket方式,把这些命令发给目标android机器的bootstrap来驱动Uiautomator执行自动化操作。关于Appium的工作原理,网上资料很多,不再详细介绍,可参考如下链接

http://www.2cto.com/kf/201410/347851.html

http://www.blogjava.net/qileilove/archive/2014/12/23/421659.html

Appium框架常用API介绍

Appium的API包含在Appium Client中,下表给出不同语言平台对应的Client下载地址

Paste_Image.png

下表给出Java平台的常用API,其他API可自行百度或查看Client源码

Paste_Image.png

Appium元素定位和操作的api是分开的,这点与robotium框架不同,与Google新推出的iOS端功能自动化框架EarlGrey是类似的。关于元素定位的api需要注意:当成功定位到元素时,返回WebElement对象,但是若不能定位到元素,此api直接报错,而不是返回NULL。这对“判断某个控件是否存在”这样的常用操作经常容易出错,比如用如下代码判断登录按钮是否存在。

public boolean isLoginButtonShow(){

WebElement wl = DriverManager.getInstance().findElementById(packagename

+  ":id/login_input_account");

return wl.isDisplayed();

}

当登录按钮存在时,返回true,但若登录按钮不存在时,以上代码并不会返回false,而是在第2行直接崩溃。可通过try catch捕获异常,修改如下:

public boolean isLoginButtonShow(){

try{

WebElement wl = DriverManager.getInstance().findElementById(packagename

+  ":id/login_input_account");

return wl.isDisplayed();

}catch (Exception e){

return false;

}

}

基于Appium框架的自动化开发环境搭建

万事开头难,自动化开发环境的搭建会比较麻烦。以下详细讲解如何在mac os操作系统下,搭建基于Appium的自动化开发环境。

1、Android开发环境搭建(JDK/SDK/AndroidStudio)请自行百度,所需安装包可在如下网页中下载:

http://tools.android-studio.org

Appium for mac安装可参考以下连接:

http://www.cnblogs.com/oscarxie/p/3894559.html

其中appium 的安装,建议使用dmg安装,点击下载安装包。“npm install -g appium”命令行安装亲测一直报错,FQ了也报错。

2、AndroidStudio中新建android工程AppDemo。

3、创建java module(appium):new—>new module—>java library,此java工程用来开发自动化case。

4、安装Appium Client:创建java module (selenium),libs目录中导入相关selenium包,点击下载selenium压缩包

5、appium module添加selenium依赖:file—>project structure—>modelues选中appium—>dependencies添加selenium module。

6、appium module中,新建java class,开始开发自动化case。至此AppDemo工程目录结构如下所示:

Paste_Image.png

7、启动appium server(命令行或者图形界面启动),注意,启动时Android Settings中请勾选No Reset选项,可防止每次执行case时,都重新安装app,如下所示。

Paste_Image.png

8、case执行,可通过IDE和脚本两种方式执行case

IDE方式:case名右击—>run

脚本方式:auto_run.sh,见下方

#!/bin/bash

#auto_run.sh

source ~/.bash_profile

cd ./AppDemo

gradle clean

gradle build

export CLASSPATH=$APPIUM_HOME/java-client-3.3.0.jar:$APPIUM_HOME/selenium-java-2.48.2-srcs.jar:$APPIUM_HOME/selenium-java-2.48.2.jar:$APPIUM_HOME/junit-4.12.jar:$APPIUM_HOME/hamcrest-core-1.3.jar:$APPIUM_HOME/libs/*

cd ./appium

java -classpath $CLASSPATH:./build/libs/appium.jar  org.junit.runner.JUnitCore   com.incito.appiumdemo.cases.PersonalCente

其中CLASSPATH需要设置为Appium Client所在路径,

com.incito.appiumdemo.cases.PersonalCenter为case所在类,脚本的执行方式有利于自动化接入持续集成和平台化。

至此基于Appium的自动化开发环境搭建完成,下一节介绍如何开发自动化case及case的分层结构设计。

基于Appium的自动化case开发及case分层结构设计

首先为每条case创建一个公共的基类AppiumTestBase,内含setup和teardown两个方法,以后每条case继承该基类即可。代码如下:

public class AppiumTestBase {

public WebDriverWait webwait;

private AndroidDriver driver;

@Before

public void setUp() throws Exception {

File classpathRoot = new File(System.getProperty("user.dir"));

File appDir = new File(classpathRoot, "apps");

File app = new File(appDir, Config.CURRENT_BANK);

DesiredCapabilities capabilities = new DesiredCapabilities();        capabilities.setCapability("deviceName",Config.DEVICE_NAME);        capabilities.setCapability(CapabilityType.BROWSER_NAME, "");        capabilities.setCapability(CapabilityType.VERSION, "5.0.1");        capabilities.setCapability("platformName", "android");

capabilities.setCapability("app", app.getAbsolutePath());

capabilities.setCapability("udid", Config.DEVICE_NAME);//adb devices获得的值        

driver = new AndroidDriver(new URL("http://127.0.0.1:"+Config.APPIUM_PORT+"/wd/hub"), capabilities);

webwait = new WebDriverWait(driver,10);

DriverManager.init(driver);

DriverManager.initWebWait(webwait);

driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);

}

@After

public void tearDown() throws Exception {

driver.quit();

}

setup操作包含导入待测应用apk包,设置与Appium Server连接所需参数,并初始化AndroidDriver对象。以标版登录case为例,其需要继承AppiumTestBase,代码如下:

package com.incito.appiumdemo;

import org.junit.After;

import org.junit.Before;

import org.openqa.selenium.remote.CapabilityType;

import org.openqa.selenium.remote.DesiredCapabilities;

import org.openqa.selenium.support.ui.WebDriverWait;

import java.io.File;

import java.net.URL;

import java.util.concurrent.TimeUnit;

import io.appium.java_client.android.AndroidDriver;

public class AccountLogin extends AppiumTestBase{

/**     

* case 编号 AccountLogin_001     

* ****@throws ****Exception     

*/

@Test

public void testAccountLogin() throws Exception {

Account.*getInstance*().gotoLoginPage();

Account.*getInstance*().doLogin();

}

/**     

* case 编号 AccountLogin_002     

* ****@throws ****Exception     

*/

@Test

public void testLoginout() throws Exception {

Account.*getInstance*().gotoGestureLoginPage();

Account.*getInstance*().doGestureLogin(Config.*CURRENT_USERNAME*);

Personal.*getInstance*().doLogout();

}

testAccountLogin Case中,执行了两步操作:进入登录页面;执行登录操作。这两步操作都封装在Account类里面。由此引入自动化case的分层设计框架,如下图:

Paste_Image.png

自动化开发过程中,经常遇到的一个问题是,随着产品的不断更新迭代,APP的UI会不断发生变化,自动化如何去应对这样的变化,如何降低其维护代价。case分层设计主要是基于自动化可维护性的考虑,可维护性是功能自动化最重要的评价指标之一,其直接决定了自动化是否能开展下去。试想case数量达到一定程度时,若没有采用封装、分层的设计思路,极有可能出现“牵一发而动全身”的问题。下图是标版自动化case的分层目录图。

Paste_Image.png

下面以登录case为例,详细了解其分层调用关系。登录case在cases层的AccountLogin类中,其代码上面已经展示,回到testAccountLogin Case的操作,第二步操作为Account.getInstance().doLogin();即在登录页面执行登录操作,其封装在business层的Account类中,代码片段如下:

public void doLogin(){

LoginUiAction.*getInstance*().enterUsername(Config.*CURRENT_USERNAME*);    LoginUiAction.*getInstance*().enterPassword(Config.*CURRENT_PASSWORD*);    LoginUiAction.*getInstance*().clickLogin();

HomeUiAction.*getInstance*().clickOnCancelGesture();

Assert.*assertTrue*(LoginUiAction.*getInstance*().isLogin());

}

doLogin()方法中执行了“输入用户名;输入密码;点击登录按钮;判断登录是否成功”操作,显然这几步操作都在UI层LoginUiAction类中。我们再查LoginUiAction.getInstance().

enterUsername()方法中做了什么,代码片段如下:

//输入用户名

public void enterUsername(String username){

WebElement wl = DriverManager.*getInstance*().findElementById(packagename +

":id/login_input_account");

wl.clear();

wl.sendKeys(username);

}

enterUsername()方法中,先根据id定位用户名输入框,然后清空输入框,再输入用户名,这些操作都是Appium Client中提供的API。至此演示了登录case的分层调用过程:cases—>business—>ui—>api。按照分层结构,只要业务逻辑不变,case维护任务主要放在ui层,上层无需改动,如此可极大减少case的维护代价。

在doLogin()方法中有一个“判断登录是否成功”的操作,断言操作是自动化测试用例中必不可少的一部分,下面就开始介绍自动化测试用例的书写规范。

自动化测试用例书写规范及注意事项

一条case一般需要包括如下几个要素:

  • 数据准备
  • 具体操作
  • 验证点
  • 清楚操作结果

数据准备指提前准备测试账号,假数据等;具体操作得按照业务测试同学提供的文本case来转化;验证点指自动化操作后,UI前后的变化点,比如登录后,首页会出现用户名、总资产、财富分等控件,这些都是验证点;清楚操作结果主要是基于case独立性的考虑,尽可能做到每条case是独立的,这样某条case fail了,也不会对其他case造成影响,当然这样会增加case的粒度,case稳定性会受影响,两者之间可自行平衡。

下面介绍case开发的注意事项:

  • 元素定位
    • ID(首选)
    • 文本
    • 控件类型
    • 坐标
  • UI操作需要合理的sleep
  • case独立性
  • 封装常用操作
  • 注释及case前写明操作步骤

元素定位有ID/文本/控件类型/坐标四种方式,推荐使用ID,因为只要某个控件还存在,其ID变化的可能性很小,若其位置发生了变动,case都无需维护。

下面给出查找元素ID的几种方法:uiautomatorviewer/hierarchyviewer/源码。uiautomatorviewer和hierarchyviewer工具在Android SDK中,配置好环境变量后,直接在命令行输入命令即可打开图形化工具,hierarchyviewer需要手机root,推荐使用uiautomatorviewer。如果有待测应用的源码,也可以通过源码来找ID,当然这种方式比较痛苦,但对熟悉业务及个人成长是有好处的,我最开始就是通过源码来找ID的。

对于一些奇葩的情况,元素ID/文本/控件类型都无法定位时,使用坐标定位绝对好使,但不到万不得已,尽量不用,因为用坐标定位就失去了兼容性,换个手机,case可能会执行失败。

UI操作需要合理的sleep,经常由于网络原因,UI加载需要一定时间,自动化操作过程中需要合理的sleep,sleep时间短了,case会失败,长了又浪费时间。Appium框架中引入了隐式sleep方案,在初始化代码中添加driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);即可,表示每步操作最多等待10s。

case独立性前面已介绍,封装及注释容易理解,不做过多解释。

功能自动化接入持续集成方案

功能自动化一般用于项目集中测试、回归测试、dailybuild等,我们不可能通过IDE手动来运行case,一般可借助于jenkins或平台化的方式来批量执行case。下面介绍如何将功能自动化接入jenkins。

Paste_Image.png

接入jenkins主要用到了其定时和轮询的功能,我们只要准备好构建jar(build.sh)和执行case(execCase.sh)的脚本,放入jenkins的Excute shell模块,然后配置定时或轮询的时间即可。build.sh和execCase.sh可参照第四部分介绍的auto_run.sh。具体执行过程如上图所示:jenkins触发自动化job;拉取构建站最新apk,拷贝至appium module的apps目录下;构建测试工程,生成appium.jar(build.sh);批量执行case(execCase.sh),最后jenkins会输出自动化的执行结果,但是输出结果可视化程度不好,可自行开发生成报告脚本。至此详细介绍了基于Appium的功能自动化开发全过程。

原文地址:http://www.51test.space/archives/2006

原文地址:https://www.cnblogs.com/zgq123456/p/9986317.html

时间: 2024-09-29 23:21:28

用Appium让Android功能自动化测试飞起来的相关文章

Appium做Android功能自动化测试

前言 做Android端功能自动化已有2年多的时间了,使用过的功能自动化框架有Robotium.Uiautomator.Appium.最近研究自动化case复用的方案,调研了Appium的自动化框架,并将其应用到银行一账通的标版中,本文详细介绍基于Appium的Android功能自动化实战经验.主要包括以下几方面内容: Appium框架原理介绍 Appium框架常用API介绍 基于Appium框架的自动化开发环境搭建 自动化case开发及分层结构设计 自动化测试用例书写规范及注意事项 功能自动化

Windows下部署Appium教程(Android App自动化测试框架搭建)

摘要: 1,appium是开源的移动端自动化测试框架: 2,appium可以测试原生的.混合的.以及移动端的web项目: 3,appium可以测试ios.android.firefox os: 4,appium是跨平台的,可以用在osx,windows以及linux系统上: ----------------------------------------------appium的一些基本概念---------------------------------------------- appium

Windows 下搭建 Appium + Android+python 自动化测试环境

前言 本来并不打算写这么一篇文章,但是实践下来发现网上的各种教程里大致有两个问题.一是文章有些跟不上时代,目前android开发和测试的技术更新都比较快,内容有些过期.二是细节部分不是太完整,拼拼凑凑也能完成,但对新手来说就比较痛苦.那么,我也来试着总结一下自己踩过的坑. 备注:Android自动化测试环境和开发环境并不完全相同,测试环境可以很简单粗暴,很多工具可以不用安装,比如JDK,SDK Tools,测试脚本用C#,Python都可以完成:但是开发环境一般都是需要JDK和不少编译工具. 实

功能自动化测试工具 Selenium 各个浏览器以及Android设备驱动方法

SeleniumTest https://github.com/WeikiForNtt/SeleniumTest.git 这几天在做Selenium的测试,各个浏览器都做了下调查,共享一下所得 (1),Selenium具体是个什么东西,自己去百度,官网http://docs.seleniumhq.org/,如果打不开,要开VPN访问. (2),Selenium对Web浏览器驱动 (2-1),根目录下有个Selenium总结.xlsx文件,供参照,有一些配置时候的注意点 (2-2),drivers

android常用自动化测试框架

目录: Monkey MonkeyRunner Instrumentation UiAutomator Espresso Selendroid Robotium Athrun Appium Monkey Android SDK自带的测试工具,在测试过程中会向系统发送伪随机的用户事件流(如按键输入.触摸屏输入.手势输入等),实现对正在开发的应用程序进行压力测试,也有日志输出.实际上该工具只能为程序做一些压力测试,由于测试事件和数据都是随机的,不能自定义,所以有很大的局限性. $~: android

Android集成讯飞SDK实现语音拨号、语音导航、语音启动应用

转载请注明出处:周木水的CSDN博客 http://blog.csdn.net/zhoumushui 科大讯飞语音SDK的语义分析还是挺强大的,可使我们的应用更加强大. 上篇博文介绍了讯飞SDK的一些简单功能: Android 使用讯飞语音SDK 今天来看看对语义分析结果JSON的解析并处理: 实现语音拨号 首先,我们看看"打电话给张三"这句话在服务器分析之后,传给我们的JSON是什么样的: { "semantic": { "slots": {

appium简明教程(6)——启动appium及android模拟器

一般情况下,我们都从命令行启动appium. windows下,dos命令窗口输入 appium 如果该命令报错,那么请重装appium npm install -g appium 如果安装出错,请自行更换npm源. npm -g --registry http://registry.cnpmjs.org install appium 然后请打开android的模拟器,如果没有请新建一个虚拟设备 下面的代码以启动android原生的计算器程序为例 ruby篇 require 'appium_li

老李分享:android app自动化测试工具合集

老李分享:android app自动化测试工具合集 poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣,请大家咨询qq:908821478,咨询电话010-84505200.我们从2016年8月开始不断升级测试开发工程师就业培训的班的课程,不断新增和优化课程内容,为了和当下企业的实际情况,提高学员的实战水平,在2016年稳定课程主题框架,做到每半年升级一版. 安卓应用自动化测试工具之一 - PerfectoMob

python专项测试——Android App自动化测试框架

1 为什么需要框架?   代码混乱,难阅读: 重复编码,效率低:需求变化,难维护: 一 自动化实例 1 准备测试的app:准备测试环境:实现脚本: 2 测试app:只有登录功能    测试环境: Appium(Android/IOS); Android SDK; Appium-Python-Client; Selenium(Appium-Python-Client继承于Selenium);  UIAutomatorViewer Pycharm 3 实现脚本 在Pycharm中编写脚本: 用UIA