/AppUIAutomation

App UI automation framework based on Appium 1.8.1

Primary LanguageJava

App UI Automation Framework

一个基于Appium 1.8.1、TestNG,Page Object模式开发的UI自动化测试框架

本人对公司和个人提供APP UI自动化培训,有意者请加QQ 40690263

介绍文档 (doc目录)

  • Framework-Introduction.pptx
  • Introduction-about-the-example.pptx

基本功能

  • 每秒生成一次截图
  • 生成Android/iOS log文件
  • 用例执行失败自动重试,且重试次数可配置
  • 用例执行失败时自动截图
  • 生成测试报告(NGReport)
  • 通过xml配置待执行的测试用例
  • 通过yml指定待执行测试的设备及Appium端口
  • 支持自定义配置项

设计目标

  • 用一套代码执行Android/iOS测试用例
  • Test case层的代码高度利用,只需要考虑业务逻辑,无需关心系统平台及如何查找元素
以下代码在iOSAndroid上均可运行

    //打开我的朋友圈
    public void showMyMoment(){
        //打开微信主页面,点击"我"
        WeiXinMainPage.verify()
                .clickMeButton();

        //校验"我"页面,打开"朋友圈"
        WeiXinMePage.verify()
                .clickMoment();

        //校验"朋友圈页面",下划一段距离,然后打开带图片的朋友圈
        WeiXinMomentPage.verify()
                .scroll()
                .clickMyMoment();

        Driver.sleep(10);
    }

设计理念

  • 应用Page Object模式提高UI页面操作代码的复用度
  • 用Driver类封装所有用到的Appium API, 框架中其它类只通过Driver调用Appium的方法,这种作法会有以下两点好处:
  •  一、屏蔽对Appium API的依赖,如果Appium的某个API官方废弃了,只需修改Driver类封装的相应方法即可
    
  •  二、如果将Appium换成Macaca或其它框架,除了改动Driver类 其它类无需改动
    
  • 在Driver中用findElementById等封装对iOS和Android的元素查找,提高代码的复用,尽可能的避免iOS与Android因查找元素方式不同而写相似的代码
  • 该框架适用于同一个APP, Android和iOS UI结构基本一致的情况

一些原则

  • Page类的构造函数用Verify代替
  • Page类的构造函数用findElementByID等函数能过检查页面关键元素来判断当前页面是不否为期望的Page
  • 依照SRP原则,Page类内的函数 只返回当前类实例(this)或void, 不返回其它页面的对象,确保每个Page的单一职责且不依赖于任何其它Page
//朋友圈的Page类
public class WeiXinMomentPage extends BasePage {

    //能过静态方法返回页面实例
    public static WeiXinMomentPage verify(){
        if( !Util.isAndroid() ) {
            //默认情况下写的Page类是Android的UI
            //若Android与iOS UI上有差异,需继承Android的Page类再写个iOS Page
            return new WeiXinMomentPageiOS();
        }

        return new WeiXinMomentPage();
    }

    //不允许调用构造函数
    protected WeiXinMomentPage(){
        Driver.findElementByText(getRes("MOMENT_PAGE_ME_TEXT"));
    }
    
    //所有成员函数只返回this或void,确保每个Page类的独立性,不依赖于任何其它Page类
    public WeiXinMomentPage scroll(){
        Driver.scrollUp();

        return this;
    }
    
    public WeiXinMomentPage clickMyMoment(){
        MobileElement elem = Driver.findElemByIdWithoutException (getRes("MY_POST_PAGE_MOMENT_PIC_ID"));

        if(elem == null){
            elem = Driver.findElementById(getRes("MY_POST_PAGE_MOMENT_ARTICLE_ID"));
        }

        elem.click();

        return this;
    }
}

  • Driver : 封装所有用到的Appium方法。作用屏蔽对Appium的依赖、提供更方便的函数。
  • BasePage : 所有Page类的基类
  • BaseTest : 所有Test类的基类
  • ConfigUtil : 读取config.yml配置文件
  • ResourceUtil : 读取*.RES.yml资源配置文件
  • Util : 工具类,提供一些通用方法
  • PageUtil : 封装进入某个页面的方法,方便复杂test case的编写
  • TestListener : 监听测试结果,用例执行失败时截图

配置文件

  • Config.yml 运行测试时的一些配置项 如包名,重试次数等等。 详见Config.ym内的注释

资源文件(具体使用方法见demo)

  • 为每个元素新建一个便于辨识的名字,用这个名字统一Android/iOS待查找元素, 然后将不同系统找中该名字的元素对应的值写入相应的RES.yml中
  • AndroidRES.yml 写入Android元素查找时需要用到的值
  • IOSRES.yml 写入iOS元素查找时需要用到的值
AndroidRES.yml

MAIN_PAGE_WEIXIN_TEXT: '微信'
MAIN_PAGE_CONTACT_TEXT: '通讯录'
MAIN_PAGE_DISCOVER_TEXT: '发现'
MAIN_PAGE_ME_TEXT: '我'

ME_PAGE_MY_POST_TEXT: '相册'
MOMENT_PAGE_ME_TEXT: '我的相册'

MY_POST_PAGE_MOMENT_PIC_ID: 'com.tencent.mm:id/dep'
MY_POST_PAGE_MOMENT_ARTICLE_ID: 'com.tencent.mm:id/yk'
IOSRES.yml

MAIN_PAGE_WEIXIN_TEXT: '微信'
MAIN_PAGE_CONTACT_TEXT: '通讯录'
MAIN_PAGE_DISCOVER_TEXT: '发现'
MAIN_PAGE_ME_TEXT: '我'

ME_PAGE_MY_POST_TEXT: '相册'
MOMENT_PAGE_ME_TEXT: '我'

MY_POST_PAGE_MOMENT_PIC_ID: 'visible == true AND type == "XCUIElementTypeStaticText" AND name CONTAINS ""'

测试用例集

  • 框架通过读取 task目录下的xml 运行指定的测试用例
在任务的xml中有四个值需要配置
1. port : Appium 端口   
2. udid : 设备ID
3. wdaPort : iOS设备运行的时的WDA port
4. class : 待运行的测试类

测试执行时输入的xml样例

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">

<suite name="TestSuite">
    <listeners>
        <listener class-name="framework.TestListener" />
    </listeners>

    <test name="com.run.Performance">
        <parameter name = "port" value = "4723"/>     
        <parameter name = "udid" value = "SJE0217B29005225"/>
        <parameter name = "wdaPort" value = "8001"/>
        <classes>
            <class name="testcase.weclass.WCPerformanceTestCPU"/>
            <class name="testcase.weclass.WCPerformanceTestBattery"/>
        </classes>
    </test>
</suite>

如何运行demo

  • demo实现的功能:打开微信(若未登录微信,请先手动登录),然后打开朋友圈,查看第一个朋友圈(带图片的)
  • 启动Appium,然后运行以下命令
  • 方式一 : 右键单击demo.xml ,选择运行, 然后会生成test class文件, 然后将工程打成Jar包(mvn package),然后运行命令 java -jar target/UIAutomation-1.0-fat-tests.jar task/demo.xml
  • 方式2 : IDEA中 右键单击demo.xml ,选择运行。见下图

参考文档