在我们学习Page Object Model之前,我们先了解一下Page Object Model(以下简称POM).

为什么要POM

用UiAutomator启动UI自动化测试不是一件困难的任务。你只需要查找元素,对元素操作就可以了。来看一个登录APP的简单的脚本。

 package com.gqou.testdemo;

 import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiObject;
import android.support.test.uiautomator.UiSelector; import org.junit.Test;
import org.junit.runner.RunWith; import static junit.framework.TestCase.assertEquals; /**
* Created by guangqian on 2016/4/22.
*/
@RunWith(AndroidJUnit4.class)
public class SimpleTest { @Test
public void 测试登录成功() throws Exception{
// 查找图标并点击启动app
UiDevice uiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
uiDevice.findObject(new UiSelector().text("TestDemo")).clickAndWaitForNewWindow();
// 输入用户名,密码并点击Login
UiObject usernameObj = uiDevice.findObject(new UiSelector().resourceId("com.gqou.testdemo:id/name_txt"));
UiObject pwdObj = uiDevice.findObject(new UiSelector().resourceId("com.gqou.testdemo:id/pwd_txt"));
UiObject loginBtn = uiDevice.findObject(new UiSelector().resourceId("com.gqou.testdemo:id/login_btn"));
UiObject welcomeTip = uiDevice.findObject(new UiSelector().resourceId("com.gqou.testdemo:id/welcome_tip")); usernameObj.click();
usernameObj.setText("username");
pwdObj.click();
pwdObj.setText("password"); loginBtn.clickAndWaitForNewWindow(); // 校验登录成功信息
assertEquals("congratulations", welcomeTip.getText());
}
}
你可以看到,我们所做的就是查找元素并为那些元素填值,点击等操作。
这是一个比较简单的脚本,脚本维护看起来也很容易。但是随着时间增长,你会编写更多的脚本代码,维护也会变得越来越困难。
脚本维护的主要面临的问题就是:比如有10份脚本使用同一个界面元素,一旦界面元素发生了变化,你需要更改10份脚本。这不仅浪费时间而且还很容易出错。
本文介绍的脚本维护比较好的方法就是针对元素的查找,操作等操作来创建一个独立的类文件。这个类文件可以被使用那些元素的所有脚本重用。将来如果界面元素发生变化,只需要修改一份类文件就可以了,不需要再去修改10份脚本文件。
这个方法就叫做Page Object Model。它可以让我们的代码更加易于阅读,维护和重用。
   

什么是POM

1. Page Object Model是一种设计模式,为界面对象创建一个对象库
2. 在这个模式下,应用的每一个界面都应该有一个相应的界面类
3. 界面类会查找界面的元素也包含对元素操作的方法
4. 方法的命名应该根据它的行为来命名,例如:如果程序等待支付网关出现在界面上,方法应该被命名类似waitForPaymentScreenDisplay().
 

POM的优点

1. POM意味着对界面上的元素的操作从原来的测试用例代码中分离出来,这样使我们的代码清晰并且易于理解。
2. 第二个好处是对象库是独立的。因此我们可以通过不同的工具使用相同的对象库来达到不同的目的。比如:我们可以集成TestNG/JUnit来做功能测试,同时也可以使用JBehave/Cucumber做验收测试。
3. 由于方法的可重用,我们的代码会变得更少,有效性更高。
4. 方法能真实的映射出用户在界面上的操作行为,比如:点击过按钮之后并跳到主界面,方法名就会类似"gotoHomePage".
 

怎么实现POM

POM的基本结构是应用的所有元素和元素的操作方法都被封装在一个类文件中,测试用例代码只需要调用这个类文件中的方法即可。
 

完整的例子:

 
第一步:打开应用app
第二步:输入用户名,密码,点击Login
第三步: 验证登录成功
 
有两个界面:登录界面,欢迎界面,所以我们要创建两个界面的类文件LoginActivity,WelcomeActivity
 

LoginActivity.java

 package com.gqou.testdemo.pages;

 import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiObject;
import android.support.test.uiautomator.UiSelector; /**
* Created by guangqian on 2016/4/22.
*/
public class LoginActivity { UiDevice uiDevice;
UiObject mUserName;
UiObject mPasswd;
UiObject mLogin; public LoginActivity(UiDevice uiDevice){
this.uiDevice = uiDevice;
mUserName = this.uiDevice.findObject(new UiSelector().resourceId("com.gqou.testdemo:id/name_txt"));
mPasswd = this.uiDevice.findObject(new UiSelector().resourceId("com.gqou.testdemo:id/pwd_txt"));
mLogin = this.uiDevice.findObject(new UiSelector().resourceId("com.gqou.testdemo:id/login_btn"));
} /**
* 输入用户名
* @param userName
* @throws Exception
*/
private void setmUserName(String userName) throws Exception{
mUserName.click();
mUserName.setText(userName);
} /**
* 输入密码
* @param pwd
* @throws Exception
*/
private void setmPasswd(String pwd) throws Exception{
mPasswd.click();
mPasswd.setText(pwd);
} /**
* 点击登录按钮
* @throws Exception
*/
private void clickLogin()throws Exception{
mLogin.clickAndWaitForNewWindow();
} /**
* 封装登录App操作
* @param username
* @param pwd
* @throws Exception
*/
public void loginApp(String username, String pwd) throws Exception{
this.setmUserName(username);
this.setmPasswd(pwd);
this.clickLogin();
}
}

WelcomeActivity.java

 package com.gqou.testdemo.pages;

 import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiObject;
import android.support.test.uiautomator.UiSelector; /**
* Created by guangqian on 2016/4/22.
*/
public class WelcomeActivity {
UiDevice uiDevice;
UiObject welcomeTip; public WelcomeActivity(UiDevice uiDevice){
this.uiDevice = uiDevice;
welcomeTip = this.uiDevice.findObject(new UiSelector().resourceId("com.gqou.testdemo:id/welcome_tip"));
} /**
* 获取欢迎提示语内容
* @return
* @throws Exception
*/
public String getWelcomeTip() throws Exception{
return welcomeTip.getText();
} }

POMForLoginTest.java

 package com.gqou.testdemo.testcases;

 import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiSelector; import com.gqou.testdemo.pages.LoginActivity;
import com.gqou.testdemo.pages.WelcomeActivity; import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith; import static junit.framework.TestCase.assertEquals;
/**
* Created by guangqian on 2016/4/22.
*/
@RunWith(AndroidJUnit4.class)
public class POMForLoginTest { public static UiDevice uiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
private static LoginActivity objLogin;
private static WelcomeActivity objWelcome; @Before
public void setUp() throws Exception {
// 打开应用
uiDevice.findObject(new UiSelector().text("TestDemo")).clickAndWaitForNewWindow();
// 创建界面实例对象
objLogin = new LoginActivity(uiDevice);
objWelcome = new WelcomeActivity(uiDevice); } @Test
public void 测试App登录成功() throws Exception {
// 登录app
objLogin.loginApp("Tom", "123456");
// 获取主界面提示语
String tips = objWelcome.getWelcomeTip();
// 判断提示语是否为预期
assertEquals("congratulations", tips);
}
}

Good Luck!

水平有限,欢迎各位大牛点评,多谢支持!

 
 
 

Page Object 模式编写UiAutomator脚本的更多相关文章

  1. 转 Page Object模式

    Page Object模式是Selenium中的一种测试设计模式,主要是将每一个页面设计为一个Class,其中包含页面中需要测试的元素(按钮,输入框,标题 等),这样在Selenium测试页面中可以通 ...

  2. UI自动化测试的Page Object模式

    在UI级的自动化测试框架中,当页面样式改变或者页面元素属性改变,那么代码也要随之进行修改,如何做到高效快速的修改代码来适应这些改变呢,这个时候可以引入Page Object模式,也是页面对象设计模式. ...

  3. 【C#|.NET】从细节出发(三) 逻辑层事务和page object模式

    一. 业务逻辑层的事务问题 如果你的程序分层清晰并且系统禁用复杂存储过程,那么在DA中的职责比较单一.程序的逻辑通过BLL调用各种不同模块的DA来实现数据操作.如果当需要不同模块在一个事务的时候,问题 ...

  4. selenium page object模式

    页面对象模式将测试代码和被测试页面的元素及操作进行分离,以降低页面元素的变化对测试代码的影响.每个被测试的页面都会被定义一个类,类中会定位元素和操作. 如果不使用page object模式,则相同的操 ...

  5. 浅析selenium的page object模式

    selenium目前比较流行的设计模式就是page object,那么到底什么是page object呢,简单来说,就是把页面作为对象,在使用中传递页面对象,来使用页面对象中相应的成员或者方法,能更好 ...

  6. python+selenium自动化软件测试(第7章):Page Object模式

    什么是Page ObjectModel模式Page Objects是selenium的一种测试设计模式,主要将每个页面看作是一个class.class的内容主要包括属性和方法,属性不难理解,就是这个页 ...

  7. 使用page object模式抓取几个主要城市的pm2.5并从小到大排序后写入txt文档

    #coding=utf-8from time import sleepimport unittestfrom selenium import webdriverfrom selenium.webdri ...

  8. python selenium-8 Page Object模式

    封装空间操作为一个接口使用,而不是直接在页面中查找 from selenium import webdriver from selenium.webdriver.common.by import By ...

  9. web自动化中的page object模式

    一. 原理 将页面的元素定位和元素行为封装成一个page类,实现页面对象和测试用例分离 类的属性:元素定位 类的行为:元素的操作 测试用例:调用所需页面对象中的行为,组成测试用例 二. 好处 1. 当 ...

随机推荐

  1. 【制作镜像Win*】文件准备

    mkdir /var/image-createcd /var/image-create/ 在物理机上: wget http://10.254.3.75/images/libvirt/libvirt.x ...

  2. .net开发人员等级

    .net 开发人员的瓶颈和职业发展 现在社会比前几年浮躁了,越来越多的人抱怨薪水低,高薪工作不好找; 诚然这有CPI的压力,可是也有很多人没有认清自己的职业发展. 很多.net程序员个各种纠结,想拿高 ...

  3. freemaker小练习

    public class TestFreemaker extends HttpServlet{    // 负责管理FreeMarker模板的Configuration实例      private ...

  4. ellang 中进程异步通信中的信箱与保序

    erlang 进程通讯中 执行到 receive 语句时 如果信箱没有消息可以匹配时会暂停等待消息. go() -> register(echo, spawn(test_pid,loop,[]) ...

  5. GCC --verbose选项, -lpthread 和-pthread的区别

    verbose的意思是冗长的,繁杂的.顾名思义,gcc --verbose 的意思就是打印出编译连接时的详细信息. 参考stackoverflow中的文章结合自己机器的信息给出分析(其实也就是翻译了一 ...

  6. Netty源码阅读(一) ServerBootstrap启动

    Netty源码阅读(一) ServerBootstrap启动 转自我的Github Netty是由JBOSS提供的一个java开源框架.Netty提供异步的.事件驱动的网络应用程序框架和工具,用以快速 ...

  7. PHP异常处理

    一.异常处理——可以有效地控制多条出现错误或异常的代码 基本语法如下: try{ //可能出现异常的代码 } catch(Exception $e){ //对异常处理 //1.自己处理 //2.不作处 ...

  8. yii2源码学习笔记(十四)

    Module类是模块和应用类的基类. yiisoft\yii2\base\Module.php <?php /** * @link http://www.yiiframework.com/ * ...

  9. __construct()和__initialize()

    ThinkPHP中的__initialize()和类的构造函数__construct()网上有很多关于__initialize()的说法和用法,总感觉不对头,所以自己测试了一下.将结果和大家分享.不对 ...

  10. Linux下high CPU分析心得【非原创】

    非原创,搬运至此以作笔记, 原地址:http://www.cnitblog.com/houcy/archive/2012/11/28/86801.html 1.用top命令查看哪个进程占用CPU高ga ...