51Testing软件测试论坛

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

QQ登录

只需一步,快速开始

微信登录,快人一步

手机号码,快捷登录

查看: 1602|回复: 2
打印 上一主题 下一主题

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

[复制链接]
  • TA的每日心情
    郁闷
    2022-8-29 14:43
  • 签到天数: 1 天

    连续签到: 1 天

    [LV.1]测试小兵

    跳转到指定楼层
    1#
    发表于 2018-2-23 16:30:44 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
    前言

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

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

    下表给出Robotium、Uiautomator、Appium三种框架的比较。
    了解各个自动化框架的特性,结合产品自身特点,选取一个合适的框架尤为重要。


    Appium框架原理介绍

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


    从图中可以看出,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下载地址


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


    Appium元素定位和操作的api是分开的,这点与robotium框架不同,与Google新推出的iOS端功能自动
    化框架EarlGrey是类似的。关于元素定位的api需要注意:当成功定位到元素时,返回WebElement对象,
    但是若不能定位到元素,此api直接报错,而不是返回NULL。这对“判断某个控件是否存在”这样的常用
    操作经常容易出错,比如用如下代码判断登录按钮是否存在。
    1. public boolean isLoginButtonShow(){
    2.   WebElement wl = DriverManager.getInstance().findElementById(packagename
    3.                     +  ":id/login_input_account");
    4.   return wl.isDisplayed();
    5. }
    复制代码
    当登录按钮存在时,返回true,但若登录按钮不存在时,以上代码并不会返回false,而是在第2行直接崩溃。
    可通过try catch捕获异常,修改如下:
    1. public boolean isLoginButtonShow(){
    2.     try{
    3.     WebElement wl = DriverManager.getInstance().findElementById(packagename  
    4.                 +  ":id/login_input_account");
    5.          return wl.isDisplayed();
    6.   }catch (Exception e){
    7.   return false;
    8.    }
    9.   }
    复制代码
    基于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”命令行安装亲测
    一直报错,翻墙了也报错。
    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工程目录结构如下所示:

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


    8、case执行,可通过IDE和脚本两种方式执行case
    IDE方式:case名右击—>run
    脚本方式:auto_run.sh,见下方
    1. #!/bin/bash
    2. #auto_run.sh
    3. source ~/.bash_profile
    4. cd ./AppDemo
    5. gradle clean
    6. gradle build
    7. 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/*  
    8. cd ./appium
    9. java -classpath $CLASSPATH:./build/libs/appium.jar  org.junit.runner.JUnitCore   com.incito.appiumdemo.cases
    复制代码
    其中CLASSPATH需要设置为Appium Client所在路径,
    com.incito.appiumdemo.cases.PersonalCenter为case所在类,脚本的执行方式有利于自动化接入持续
    集成和平台化。
    至此基于Appium的自动化开发环境搭建完成,下一节介绍如何开发自动化case及case的分层结构设计。

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

    首先为每条case创建一个公共的基类AppiumTestBase,内含setup和teardown两个方法,以后每条case
    继承该基类即可。代码如下:
    1. public class AppiumTestBase {   
    2.   public WebDriverWait webwait;   
    3. private AndroidDriver driver;   
    4. @Before   
    5. public void setUp() throws Exception {        
    6. File classpathRoot = new File(System.getProperty("user.dir"));        
    7. File appDir = new File(classpathRoot, "apps");        
    8. File app = new File(appDir, Config.CURRENT_BANK);        
    9. 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");        
    10. capabilities.setCapability("app", app.getAbsolutePath());        
    11. capabilities.setCapability("udid", Config.DEVICE_NAME);//adb devices获得的值        
    12. driver = new AndroidDriver(new URL("http://127.0.0.1:"+Config.APPIUM_PORT+"/wd/hub"), capabilities);        
    13. webwait = new WebDriverWait(driver,10);        
    14. DriverManager.init(driver);        
    15. DriverManager.initWebWait(webwait);        
    16. driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);   
    17. }   
    18. @After   
    19. public void tearDown() throws Exception {        
    20. driver.quit();   
    21. }
    复制代码
    setup操作包含导入待测应用apk包,设置与Appium Server连接所需参数,并初始化AndroidDriver
    对象。以标版登录case为例,其需要继承AppiumTestBase,代码如下:
    1. package com.incito.appiumdemo;
    2. import org.junit.After;
    3. import org.junit.Before;
    4. import org.openqa.selenium.remote.CapabilityType;
    5. import org.openqa.selenium.remote.DesiredCapabilities;
    6. import org.openqa.selenium.support.ui.WebDriverWait;
    7. import java.io.File;
    8. import java.net.URL;
    9. import java.util.concurrent.TimeUnit;
    10. import io.appium.java_client.android.AndroidDriver;
    11. public class AccountLogin extends AppiumTestBase{   
    12. /**     
    13. * case 编号 AccountLogin_001     
    14. * ****@throws ****Exception     
    15. */   
    16. @Test   
    17. public void testAccountLogin() throws Exception {        
    18. Account.*getInstance*().gotoLoginPage();        
    19. Account.*getInstance*().doLogin();   
    20. }
    21. /**     
    22. * case 编号 AccountLogin_002     
    23. * ****@throws ****Exception     
    24. */   
    25. @Test   
    26. public void testLoginout() throws Exception {        
    27. Account.*getInstance*().gotoGestureLoginPage();        
    28. Account.*getInstance*().doGestureLogin(Config.*CURRENT_USERNAME*);        
    29. Personal.*getInstance*().doLogout();   
    30. }
    复制代码
    testAccountLogin Case中,执行了两步操作:进入登录页面;执行登录操作。这两步操作都封装在
    Account类里面。由此引入自动化case的分层设计框架,如下图:

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


    本帖子中包含更多资源

    您需要 登录 才可以下载或查看,没有帐号?(注-册)加入51Testing

    x
    分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
    收藏收藏1
    回复

    使用道具 举报

  • TA的每日心情
    郁闷
    2022-8-29 14:43
  • 签到天数: 1 天

    连续签到: 1 天

    [LV.1]测试小兵

    2#
     楼主| 发表于 2018-2-23 16:33:44 | 只看该作者

    下面以登录case为例,详细了解其分层调用关系。登录case在cases层的AccountLogin类中,其代码上
    面已经展示,回到testAccountLogin Case的操作,第二步操作为Account.getInstance().doLogin();即
    在登录页面执行登录操作,其封装在business层的Account类中,代码片段如下:
    1. public void doLogin(){   
    2. LoginUiAction.*getInstance*().enterUsername(Config.*CURRENT_USERNAME*);    LoginUiAction.*getInstance*().enterPassword(Config.*CURRENT_PASSWORD*);    LoginUiAction.*getInstance*().clickLogin();   
    3. HomeUiAction.*getInstance*().clickOnCancelGesture();   
    4. Assert.*assertTrue*(LoginUiAction.*getInstance*().isLogin());
    5. }
    复制代码
    doLogin()方法中执行了“输入用户名;输入密码;点击登录按钮;判断登录是否成功”操作,显然这几
    步操作都在UI层LoginUiAction类中。我们再查LoginUiAction.getInstance().
    enterUsername()方法中做了什么,代码片段如下:

    1. public void enterUsername(String username){   
    2. WebElement wl = DriverManager.*getInstance*().findElementById(packagename +   
    3.       ":id/login_input_account");   
    4. wl.clear();   
    5. wl.sendKeys(username);
    6. }
    复制代码
    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。


    接入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的功能自动化开发全过程。

    本帖子中包含更多资源

    您需要 登录 才可以下载或查看,没有帐号?(注-册)加入51Testing

    x
    回复 支持 反对

    使用道具 举报

    本版积分规则

    关闭

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

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

    GMT+8, 2024-11-15 00:54 , Processed in 0.077345 second(s), 23 queries .

    Powered by Discuz! X3.2

    © 2001-2024 Comsenz Inc.

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