更新

20161112 增加对 Yaml 对象库的支持

20161124 增加对分布式并发执行用例的支持,可以同时将用例运行在不同的机器设备上。

简介

这是一个 AppUi 自动化测试框架,由 webdriver 中文社区创办人土豆 (本人技术笔名) 所创建,该 APP 自动化测试框架是用 java 语言编写的,基于 selenium webdriver Appium 的开源自动化测试框架,该框架结合了 testng,selenium,webdriver,Appium,jxl,jodd-http 等工具。该框架基于页面对象模型(POM)架构,实现了关键字驱动技术,数据驱动,无需掌握多少编程知识即可编写脚本,同时实现了数据与代码分离的功能:1、元素定位信息保存在对象库文件中 2、测试用例数据可以存储在 excel 中。从而实现,页面元素位置变化,无需改动脚本,只需修改对应的元素定位信息即可。
该框架实现了检查点及用例失败自动截图功能,自动生成 html 测试报告及自动发送 html 邮件测试报告功能。
目前框架还不是特别完善,还需要写一些脚本实现自动化;学习该框架需要熟悉一定的安卓 APP 和 java 基础,后续可以考虑自动编码的实现
开源地址:http://git.oschina.net/zhengshuheng/PatatiumAppUi

主要功能

1、实现关键字驱动技术,编写用例简单

2、实现数据驱动技术,减少用例代码

3、支持元素对象库管理,页面元素信息与代码分离;支持 XML,YAML 方式管理对象库

3、支持检查点、用例断言设置

4、检查点失败截图,一个检查点失败不影响用例后续执行

5、用例失败自动截图

6、用例之间依赖少,可以自由组合测试用例执行

7、支持安卓系统常用触摸操作

8、支持 APP 控件常用操作

9、用例集执行完毕自动生成简介美观的 html 报告

10、用例执行完毕自动发送详实的 html 邮件报告,可拓展为有失败用例才发送。

11、支持分布式并发执行用例的支持,可以同时将用例运行在不同的机器设备上。

Api 文档

点击查看 API 文档

环境配置

1、JDK1.8

2、IDEA\Eclipse

3、Android SDK 具体安装参考:http://www.webdriver.org/article-52-1.html

4、Maven

5、一台安卓手机或者安卓模拟器,推荐夜神安卓模拟器,下载地址:http://www.yeshen.com/

6、Appium Server 端,下载地址:http://pan.baidu.com/s/1jIxzSfO

注意事项

工程项目编码需要设置成 UTF-8 否则会出现中文乱码情况

Demo 演示

Demo 演示视频地址:http://v.youku.com/v_show/id_XMTcxMTY1MzE0NA==.html?beta&

一、创建对象库

1、通过 Android SDK 工具 uiautomatorviewer.bat 获取 app 元素定位信息,具体使用参考:http://www.webdriver.org/article-53-1.html

2、UILibrary.xml 对象库文件编写

<?xml version="1.0" encoding="UTF-8"?>
<!--整个对象库文件的根目录管理整个项目的对象-->
<map>
    <!--管理一个页面的元素webelementinput,select,textare,a,li等标签),一个page包含多个locator对象
    Pagename:page对象名字格式org.webdriver.patatiumappui.pageObject.xxxPage;最后面那位才是真正的页面名字前面的是java对象库路径
    另外注意页面名字是头个单词大写例如主页名字定义为 org.webdriver.patatiumappui.pageObject.HomePage
    Value页面对象的URL可不填
    Desc:页面对象中文描述-->
    <page pagename="org.webdriver.patatiumappui.pageObject.StartPage" value="" desc="微信APP启动首页">
        <!--管理一个页面的元素webelementinput,select,textare,a,li等标签),一个page包含多个locator对象
        Type定位方式包含id,name,class,linktext,xpath,css等定位元素的时候灵活使用一般可以统一用xpath
        代替id,name,classlinktext的定位方式
        Timeout元素加载时间有些页面元素可能要等待一段时间才能加载过来为了查找元素的稳定性需加等待时间
        Value:元素定位信息如果是id,name,classlinktext直接把网页元素对应的这些属性值写上即可如果是xpath定位方式
        需要填写正确的xpath语法格式
        Desc:元素的描述元素的中文描述信息-->
        <locator type="id" timeout="3" value="com.tencent.mm:id/c4k"  desc="登录">登录</locator>
        <locator type="id" timeout="3" value="com.tencent.mm:id/cuh"  desc="注册">注册</locator>
    </page>
    <page pagename="org.webdriver.patatiumappui.pageObject.LoginPage" value="" desc="微信App登录页面">
       <locator type="id" timeout="3" value="com.tencent.mm:id/b6c"  desc="使用其他方式登录">使用其他方式登录</locator>
        <locator type="id" timeout="3" value="com.tencent.mm:id/b5r"  desc="账号">账号输入框</locator>
        <locator type="id" timeout="3" value="com.tencent.mm:id/b5s"  desc="密码">密码输入框</locator>
        <locator type="id" timeout="3" value="com.tencent.mm:id/b5t"  desc="登录">登录按钮</locator>
        <locator type="id" timeout="3" value="com.tencent.mm:id/avt"  desc="失败提示信息确认按钮">登录失败提示信息</locator>
        <locator type="id" timeout="3" value="com.tencent.mm:id/bim"  desc="失败提示信息确认按钮">登录失败确认按钮</locator>
    </page>
</map>

YAML 对象库,UILibrary.yaml 编写

pages:
    - page:
       pageName: org.webdriver.patatiumappui.pageObject.StartPage
       value: "www.baidu.com"
       desc: "微信APP启动首页"
       locators:
          - {type: "id",timeout: "3",value: "com.tencent.mm:id/c72",desc: "登录",name: "登录"}
          - {type: "id",timeout: "3",value: "com.tencent.mm:id/c71",desc: "注册",name: "注册"}
    - page:
        pageName: org.webdriver.patatiumappui.pageObject.LoginPage
        value: ""
        desc: "微信App登录页面"
        locators:
          - {type: "id",timeout: "3" , value: "com.tencent.mm:id/b9i", desc: "使用其他方式登录",name: "使用其他方式登录"}
          - {type: "xpath",timeout: "3" ,value: "//android.widget.EditText[@text='QQ号/微信号/Email']", desc: "账号",name: "账号输入框"}
          - {type: "xpath",timeout: "3" ,value: "//android.widget.EditText[@NAF='1']", desc: "密码",name: "密码输入框"}
          - {type: "id",timeout: "3" ,value: "com.tencent.mm:id/b8z", desc: "登录",name: "登录按钮"}
          - {type: "id",timeout: "3" ,value: "com.tencent.mm:id/bl3", desc: "失败提示信息确认信息",name: "登录失败提示信息"}
          - {type: "id",timeout: "3" ,value: "com.tencent.mm:id/a_r", desc: "失败提示信息确认按钮",name: "登录失败确认按钮"}

编写完后,运行/src/main/java/org/webdriver/patatiumappui/PageObjectConfig/PageObjectAutoCodeForXml.java 或者/src/main/java/org/webdriver/patatiumappui/PageObjectConfig/PageObjectAutoCodeForYaml.java 文件生成对象库 java 代码

二、公共 action 封装实例(业务操作)

/**
 * Created by zhengshuheng on 2016/9/2 0002.
 */
public class LoginAction extends TestBaseCase {
    public  LoginAction(String username,String password) throws IOException {
        ElementAction action=new ElementAction();
        LoginPage loginPage=new LoginPage();
        action.click(loginPage.账号输入框());
        action.clear(loginPage.账号输入框());
        action.type(loginPage.账号输入框(),username);
        action.click(loginPage.密码输入框());
        action.clear(loginPage.密码输入框());
        action.type(loginPage.密码输入框(),password);
        action.sleep(1);
        action.click(loginPage.登录按钮());
    }
}

三、驱动数据来源实例

在 src/main/resources/data 下创建 loginData.xls 文件

四、测试用例编写

/**
 * Created by zhengshuheng on 2016/9/2 0002.
 */
public class LoginTest extends TestBaseCase {
    ElementAction action=new ElementAction();
    @BeforeClass
    public  void  beforeclass() throws IOException {
        StartPage startPage=new StartPage();
        action.click(startPage.登录());
        LoginPage loginPage=new LoginPage();
        action.sleep(2);
        action.click(loginPage.使用其他方式登录());
        action.sleep(2);
    }
    @Test(description = "登录测试")
    public  void login() throws IOException {
        //调用登录方法(需填写正确的用户名和密码)
        new LoginAction("655433", "gg");
        action.sleep(5);
        //设置检查点
        Assertion.VerityTextPresent("通讯录","验证是否登录成功!");
        //设置断言 。判断用例是否失败
        Assertion.VerityError();
    }
    //数据驱动案例--start
    @DataProvider(name="longinData")
    public Object[][] loginData()
    {
        //读取登录用例测试数据
        String filePath="src/main/resources/data/loginData.xls";
        //读取第一个sheet,第2行到第5行-第2到第4列之间的数据
        return ExcelReadUtil.case_data_excel(0, 1, 2, 1, 3,filePath);
    }
    @Test(description="登录失败用例:数据驱动例子",dataProvider = "longinData")
    public void loginFail (String userName,String password,String message) throws IOException, DocumentException {
        //调用登录方法
        new  LoginAction(userName,password);
        LoginPage loginPage=new LoginPage();
        action.sleep(4);
        log.info("登录失败信息:"+action.getText(loginPage.登录失败提示信息()));
        Assertion.VerityCationString(action.getText(loginPage.登录失败提示信息()),message,"验证是否出现预期的错误提示信息:"+message);
        action.click(loginPage.登录失败确认按钮());
        //设置断言
        Assertion.VerityError();
    }
}

五、Testng.xml 配置

tesng.xml 需配置 app 主包名,主类名,SDK 版本,Device Name 等信息
Device Name:在 cmd 命令下通过 adb devices 获取

App 主包名,主类名等在 Appium Server GUI 获取

App 安装包 apk 文件放在项目根目录下 apps 目录里,tesng.xml 需指定运行 apk 文件名

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Suite" >
    <parameter name="driverName" value="AndroidDriver" />   <!--driver驱动安卓IOS-->
    <parameter name="nodeURL" value="127.0.0.1:4723" /> <!--appium-server 地址-->
    <parameter name="appName" value="weixin_861.apk" />  <!--app包名字-->
    <parameter name="platformName" value="Android" /> <!--app运行平台:安卓IOS-->
    <parameter name="deviceName" value="127.0.0.1:62001" /> <!--手机或者虚拟机设备名字-->
    <parameter name="sdkVersion" value="6.0" /><!--安卓,IOS SDK版本-->
    <parameter name="appMainPackage" value="com.tencent.mm" /><!--app主包名-->
    <parameter name="appActivity" value="com.tencent.mm.ui.LauncherUI" /> <!--app 主类名-->
    <parameter name="UserName" value="" /> <!-- 系统登录用户名-->
    <parameter name="PassWord" value="" />  <!-- 系统登录密码-->
    <parameter name="smtpUserName" value="" />  <!-- 测试报告邮件发送smtp身份证验证-->
    <parameter name="smtpPassWord" value="" />  <!-- 测试报告邮件发送smtp身份证验证-->
    <parameter name="smtpHost" value="" />  <!-- 测试报告邮件发送smtp主机地址-->
    <parameter name="smtpPort" value="" />  <!-- 测试报告邮件发送smtp主机端口-->
    <parameter name="mailTitle" value="Webdriver中文社区-自动化测试报告" />  <!-- 测试报告邮件发送邮件标题-->
    <parameter name="logUrl" value="" />  <!-- 测试报告邮件发送用例运行日志url-->
    <parameter name="reportUrl" value="" />  <!-- 测试报告邮件发送完整测试报告url-->
    <parameter name="recipients" value="" /> <!-- 测试报告邮件发送收件人多个用,号隔开-->
    <parameter name="reportTitle" value="Webdriver中文社区-自动化测试报告" />  <!--测试报告标题-->

    <listeners><!-- 监听器设置-->
        <listener class-name="org.webdriver.patatiumappui.utils.TestListener"/>
        <listener class-name="org.webdriver.patatiumappui.utils.TestReport"/>
    </listeners>
    <test name="登录测试">
        <classes>
            <class name="LoginTest">
                <methods>
                    <include name="login"/>
                </methods>
            </class>
        </classes>
    </test>
    <test name="登录失败测试:数据驱动">
        <classes>
            <class name="LoginTest">
                <methods>
                    <include name="loginFail"/>
                </methods>
            </class>
        </classes>
    </test>
</suite> <!-- Suite -->

分布式并发执行用例,同时将用例运行在不同设备上的 testng.xml 配置如下

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Suite" parallel="tests" thread-count="2">
    <parameter name="driverName" value="AndroidDriver" />   <!--driver驱动安卓IOS-->
    <parameter name="nodeURL" value="127.0.0.1:4723" /> <!--appium-server 地址-->
    <parameter name="appName" value="weixin_861.apk" />  <!--app包名字-->
    <parameter name="platformName" value="Android" /> <!--app运行平台:安卓IOS-->
    <parameter name="deviceId" value="127.0.0.1:62001" /> <!--手机或者虚拟机设备Id通过adb device获取-->
    <parameter name="deviceName" value="127.0.0.1:62001" /> <!--手机或者虚拟机设备名字自定义设备名字-->
    <parameter name="sdkVersion" value="6.0" /><!--安卓,IOS SDK版本-->
    <parameter name="appMainPackage" value="com.tencent.mm" /><!--app主包名-->
    <parameter name="appActivity" value="com.tencent.mm.ui.LauncherUI" /> <!--app 主类名-->
    <parameter name="UserName" value="" /> <!-- 系统登录用户名-->
    <parameter name="PassWord" value="" />  <!-- 系统登录密码-->
    <parameter name="smtpUserName" value="" />  <!-- 测试报告邮件发送smtp身份证验证-->
    <parameter name="smtpPassWord" value="" />  <!-- 测试报告邮件发送smtp身份证验证-->
    <parameter name="smtpHost" value="" />  <!-- 测试报告邮件发送smtp主机地址-->
    <parameter name="smtpPort" value="" />  <!-- 测试报告邮件发送smtp主机端口-->
    <parameter name="mailTitle" value="Webdriver中文社区-自动化测试报告" />  <!-- 测试报告邮件发送邮件标题-->
    <parameter name="logUrl" value="" />  <!-- 测试报告邮件发送用例运行日志url-->
    <parameter name="reportUrl" value="" />  <!-- 测试报告邮件发送完整测试报告url-->
    <parameter name="recipients" value="" /> <!-- 测试报告邮件发送收件人多个用,号隔开-->
    <parameter name="reportTitle" value="Webdriver中文社区-自动化测试报告" />  <!--测试报告标题-->

    <listeners><!-- 监听器设置-->
        <listener class-name="org.webdriver.patatiumappui.utils.TestListener"/>
        <listener class-name="org.webdriver.patatiumappui.utils.TestReport"/>
    </listeners>
    <test name="登录测试1-设备1">
        <parameter name="nodeURL" value="127.0.0.1:4725" /> <!--appium-server 地址-->
        <parameter name="deviceId" value="127.0.0.1:62001" /> <!--手机或者虚拟机设备Id通过adb device获取-->
        <parameter name="deviceName" value="127.0.0.1:62001" /> <!--手机或者虚拟机设备名字自定义设备名字-->
        <classes>
            <class name="LoginTest">
                <methods>
                    <include name="login"/>
                </methods>
            </class>
        </classes>
    </test>
    <test name="登录测试2-设备2">
        <parameter name="nodeURL" value="127.0.0.1:4726" /> <!--appium-server 地址-->
        <parameter name="deviceId" value="127.0.0.1:62025" /> <!--手机或者虚拟机设备Id通过adb device获取-->
        <parameter name="deviceName" value="127.0.0.1:62025" /> <!--手机或者虚拟机设备名字自定义设备名字-->
        <classes>
            <class name="LoginTest">
                <methods>
                    <include name="login"/>
                </methods>
            </class>
        </classes>
    </test>
    <test name="登录测试3-设备3">
        <parameter name="nodeURL" value="127.0.0.1:4727" /> <!--appium-server 地址-->
        <parameter name="deviceId" value="127.0.0.1:62026" /> <!--手机或者虚拟机设备Id通过adb device获取-->
        <parameter name="deviceName" value="127.0.0.1:62026" /> <!--手机或者虚拟机设备名字自定义设备名字-->
        <classes>
            <class name="LoginTest">
                <methods>
                    <include name="login"/>
                </methods>
            </class>
        </classes>
    </test>
    <!--<test name="登录失败测试:数据驱动">-->
        <!--<classes>-->
            <!--<class name="LoginTest">-->
                <!--<methods>-->
                    <!--<include name="loginFail"/>-->
                <!--</methods>-->
            <!--</class>-->
        <!--</classes>-->
    <!--</test>-->
</suite> <!-- Suite -->

六、执行用例

IDE:在 IDE 集成开发环境下右键 testng.xml 使用 testng 运行

Maven:执行 mvn clean ;mvn test 命令

Jenkins:1、checkout 项目代码 2、指定 pom.xml 文件 3、执行 mvn clean ;mvn test 命令

七、查看测试报告及日志文件

用例执行完毕,会自动发送邮件报告及生成测试报告文件;用例失败会自动截图并将其展示在报告中,也可以将用例失败堆栈信息显示到报表中

测试报告文件生成在项目根目录下 test-out 目录下 report.html 文件

报告展示如下:点击查看在线测试报告



License

GPL V2.0


↙↙↙阅读原文可查看相关链接,并与作者交流