在我们学习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. struts 文件上传下载

    上传 1.编写上传action类 UploadAction.java package jxf.b_upload; import java.io.File; import java.io.IOExcep ...

  2. Nginx的反向代理

    先通过简单的图来说明一下正向代理和反向代理吧~ 正向代理 代理其实就是一个中介,A和B本来可以直连,中间插入一个C,C就是中介.刚开始的时候,代理多数是帮助内网client访问外网server用的(比 ...

  3. CodeFirst 的编程方式

    第一步:创建控制台项目第二步:添加新建项目→Ado.Net空实体模型第三步:添加实体:Customer,添加几个必要的测试字段第四步:添加实体之间的联系第五步:根据模型生成数据库脚本,并执行sql脚本 ...

  4. 网站开发常用jQuery插件总结(五)滚动条插件nanoscroller

    网站在展示信息时,如果信息量过大,解决方法主要有三种.1.分页,将信息分页显示.2.整页显示,但是页面过长,影响浏览体验.3.使用滚动条,而默认滚动条样式太单一,用户体验不友好.所以我们需要美化滚动条 ...

  5. cenots 下的 lamp(备份与恢复)

    用 putty连接数据库: mysql -uroot -p密码 create database yourdb DEFAULT CHARACTER SET utf8 COLLATE utf8_chine ...

  6. dom三个事件

    1,页面加载后 window.onload=function(){}; 2,页面(关闭)卸载后触发 window.onunload=function(){}; 3,页面关闭前触发 window.onb ...

  7. js data日期初始化的5种方法new Date()

    var objDate=new Date([arguments list]); 参数形式有以下5种: 1)new Date("month dd,yyyy hh:mm:ss"); 2 ...

  8. Mock相关收集

    MockMVC+Mockito http://www.cnblogs.com/syxchina/p/4150879.html Spring中使用Mockito http://www.cnblogs.c ...

  9. (转载)在状态栏即时显示Hint

    在状态栏即时显示Hint(所有窗口,包括子窗口控件的hint) 在主窗体中放入一个ApplicationEvents控件.添加如下代码.其中Items[***]中的***代表状态栏的各个子panel, ...

  10. Omnithreadlibary学习(3)-IOmniTask异步执行SendMessage

    在任务中发送消息, 可以是函数或者对象方法 TOmniTaskMessageEvent = procedure(const task: IOmniTaskControl; const msg: TOm ...