文章出处 http://blog.csdn.net/niubitianping/article/details/52612211

一、为什么需要封装?

封装的本意就是为了方便、简洁。

二、Android的显式等待封装

1. AndroidDriverWait.java

package com.example.base;/** * Created by LITP on 2016/9/8. */ import org.openqa.selenium.NotFoundException; import org.openqa.selenium.TimeoutException; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebDriverException; import org.openqa.selenium.remote.RemoteWebDriver; import org.openqa.selenium.support.ui.Clock; import org.openqa.selenium.support.ui.FluentWait; import org.openqa.selenium.support.ui.Sleeper; import org.openqa.selenium.support.ui.SystemClock; import java.util.concurrent.TimeUnit; import io.appium.java_client.android.AndroidDriver; public class AndroidDriverWait extends FluentWait<AndroidDriver> { public final static long DEFAULT_SLEEP_TIMEOUT = 500; private final WebDriver driver; public AndroidDriverWait(AndroidDriver driver, long timeOutInSeconds) { this(driver, new SystemClock(), Sleeper.SYSTEM_SLEEPER, timeOutInSeconds, DEFAULT_SLEEP_TIMEOUT); } public AndroidDriverWait(AndroidDriver driver, long timeOutInSeconds, long sleepInMillis) { this(driver, new SystemClock(), Sleeper.SYSTEM_SLEEPER, timeOutInSeconds, sleepInMillis); } public AndroidDriverWait(AndroidDriver driver, Clock clock, Sleeper sleeper, long timeOutInSeconds, long sleepTimeOut) { super(driver, clock, sleeper); withTimeout(timeOutInSeconds, TimeUnit.SECONDS); pollingEvery(sleepTimeOut, TimeUnit.MILLISECONDS); ignoring(NotFoundException.class); this.driver = driver; } @Override protected RuntimeException timeoutException(String message, Throwable lastException) { TimeoutException ex = new TimeoutException(message, lastException); ex.addInfo(WebDriverException.DRIVER_INFO, driver.getClass().getName()); if (driver instanceof RemoteWebDriver) { RemoteWebDriver remote = (RemoteWebDriver) driver; if (remote.getSessionId() != null) { ex.addInfo(WebDriverException.SESSION_ID, remote.getSessionId().toString()); } if (remote.getCapabilities() != null) { ex.addInfo("Capabilities", remote.getCapabilities().toString()); } } throw ex; } } 

2.ExpectedCondition.java

接口

package com.example.base;import com.google.common.base.Function;import io.appium.java_client.android.AndroidDriver;/*** Created by LITP on 2016/9/8.*/
public interface ExpectedCondition<T> extends Function<AndroidDriver, T> {}

3. 使用

 /*** 显示等待,等待Id对应的控件出现time秒,一出现马上返回,time秒不出现也返回*/public AndroidElement waitAuto(By by, int time) {try { return new AndroidDriverWait(driver, time) .until(new ExpectedCondition<AndroidElement>() { @Override public AndroidElement apply(AndroidDriver androidDriver) { return (AndroidElement) androidDriver.findElements(by); } }); } catch (TimeoutException e) { Assert.fail("查找元素超时!! " + time + " 秒之后还没找到元素 [" + by.toString() + "]", e); return null; } }

三、Assert断言的封装

封装了 出现错误输出了异常信息但不终止程序的运行,会继续往下执行。

1.Assertion.java

package com.example.base;import org.testng.Assert;import java.util.ArrayList;
import java.util.List;/** * Created by LITP on 2016/9/21. */ public class Assertion { public static boolean flag = true; //是否有错误 public static List<Error> errors = new ArrayList<>(); //错误集合 /** * 验证值是否相等 * @param actual 第一个值 * @param expected 要对比的值 */ public static void verifyEquals(Object actual, Object expected){ try{ Assert.assertEquals(actual, expected); }catch(Error e){ errors.add(e); flag = false; } } /** * 验证值是否相等 * @param actual 第一个值 * @param expected 要对比的值 * @param message 出错时候的提示消息 */ public static void verifyEquals(Object actual, Object expected, String message){ try{ Assert.assertEquals(actual, expected, message); }catch(Error e){ errors.add(e); flag = false; } } } 

2.AssertionListener.java

package com.example.base;import org.testng.ITestResult;
import org.testng.TestListenerAdapter;import java.util.ArrayList;
import java.util.Arrays; import java.util.List; import static javafx.scene.input.KeyCode.T; /** * Created by LITP on 2016/9/21. */ public class AssertionListener extends TestListenerAdapter { /** * 测试方法开始的时候回调 * @param result */ @Override public void onTestStart(ITestResult result) { Assertion.flag = true; Assertion.errors.clear(); } /** * 测试终止时候回调 * @param tr */ @Override public void onTestFailure(ITestResult tr) { this.handleAssertion(tr); } /** * Test跳过 的时候执行 * @param tr */ @Override public void onTestSkipped(ITestResult tr) { this.handleAssertion(tr); } /** * Test运行完毕时候执行 * @param tr */ @Override public void onTestSuccess(ITestResult tr) { this.handleAssertion(tr); } private int index = 0; //错误行号 /** * 处理断言,每个Test执行完毕回调 * @param tr 测试结果 */ private void handleAssertion(ITestResult tr){ if(!Assertion.flag){ //为假,就是断言出错了就执行下面的 //获取异常 Throwable throwable = tr.getThrowable(); if(throwable==null){ throwable = new Throwable(); } //获取异常堆栈信息 StackTraceElement[] traces = throwable.getStackTrace(); //创建要输出的所有堆栈信息 StackTraceElement[] alltrace = new StackTraceElement[0]; //循环获取断言的异常信息, for (Error e : Assertion.errors) { //获取错误的堆栈数组信息 StackTraceElement[] errorTraces = e.getStackTrace(); // StackTraceElement[] et = getKeyStackTrace(tr, errorTraces); //设置异常信息堆栈内容 StackTraceElement[] message = handleMess(e.getMessage(),tr); //行号初始化为0 index = 0; //堆栈信息合并 alltrace = merge(alltrace, message); alltrace = merge(alltrace, et); } //如果异常信息不为空 if(traces!=null){ traces = getKeyStackTrace(tr, traces); alltrace = merge(alltrace, traces); } //保存异常信息 throwable.setStackTrace(alltrace); tr.setThrowable(throwable); //清空 Assertion.flag = true; Assertion.errors.clear(); //输出异常信息 tr.setStatus(ITestResult.FAILURE); } } /** * 获取堆栈信息 * @param tr * @param stackTraceElements * @return */ private StackTraceElement[] getKeyStackTrace(ITestResult tr, StackTraceElement[] stackTraceElements){ List<StackTraceElement> ets = new ArrayList<>(); //循环获取信息 for (StackTraceElement stackTraceElement : stackTraceElements) { //返回测试类的堆栈信息 if(stackTraceElement.getClassName().equals(tr.getTestClass().getName())){ ets.add(stackTraceElement); index = stackTraceElement.getLineNumber(); //错误行号 } } return ets.toArray(new StackTraceElement[ets.size()]); } /** * 合并两个堆栈信息 * @param traces1 第一个 * @param traces2 * @return */ private StackTraceElement[] merge(StackTraceElement[] traces1, StackTraceElement[] traces2){ StackTraceElement[] result = Arrays.copyOf(traces1, traces1.length + traces2.length); System.arraycopy(traces2, 0, result, traces1.length, traces2.length); return result; } /** * 处理消息提示内容 * @param mess 报错信息 * @param tr 结果描述 * @return */ private StackTraceElement[] handleMess(String mess,ITestResult tr){ String message = "\n报错信息: "+mess; String method = "\n报错方法名:"+tr.getMethod().getMethodName(); String className = "\n报错类:"+tr.getTestClass().getRealClass().getSimpleName(); return new StackTraceElement[]{ new StackTraceElement(message, //内容 method, //方法名 className+"\n报错行号", //文件名 index)}; } }

四、Appium java的封装

1. Builder.java

构建器,在每个用例上都可以很方便设置app的属性

package com.example.base;/*** Created by LITP on 2016/9/7.*/
public class Builder { String deviceName = BaseAppium.deviceName; String platformVersion = BaseAppium.platformVersion; String path = System.getProperty("user.dir") + "/src/main/java/apps/"; String appPath = BaseAppium.appPath; String appPackage = BaseAppium.appPackage; String noReset = BaseAppium.noReset; String noSign = BaseAppium.noSign; String unicodeKeyboard = BaseAppium.unicodeKeyboard; String resetKeyboard = BaseAppium.resetKeyboard; String appActivity = BaseAppium.appActivity; public Builder setAppPath(String appPath) { this.appPath = path + appPath; return this; } public Builder setDeviceName(String deviceName) { this.deviceName = deviceName; return this; } public Builder setPlatformVersion(String platformVersion) { this.platformVersion = platformVersion; return this; } public Builder setApp(String appPath) { this.appPath = appPath; return this; } public Builder setAppPackage(String appPackage) { this.appPackage = appPackage; return this; } public Builder setNoReset(String noReset) { this.noReset = noReset; return this; } public Builder setNoSign(String noSign) { this.noSign = noSign; return this; } public Builder setUnicodeKeyboard(String unicodeKeyboard) { this.unicodeKeyboard = unicodeKeyboard; return this; } public Builder setResetKeyboard(String resetKeyboard) { this.resetKeyboard = resetKeyboard; return this; } public Builder setAppActivity(String appActivity) { this.appActivity = appActivity; return this; } public BaseAppium build() { return new BaseAppium(this); } }

2. BaseAppium.java

父类,里面封装了一堆方法,只管用,传id、name那些就行了。当然这只是一部分,仅供参考,可以自己修改添加。这个封装没有利用po模式,仅供参考,接下来的文章继续优化封装。

package com.example.base;import org.apache.http.util.TextUtils;
import org.openqa.selenium.By;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.TimeoutException; import org.openqa.selenium.remote.DesiredCapabilities; import org.testng.Assert; import org.testng.annotations.AfterTest; import org.testng.annotations.BeforeSuite; import org.testng.annotations.Listeners; import java.io.File; import java.net.MalformedURLException; import java.net.URL; import java.util.List; import java.util.concurrent.TimeUnit; import io.appium.java_client.MultiTouchAction; import io.appium.java_client.TouchAction; import io.appium.java_client.android.AndroidDriver; import io.appium.java_client.android.AndroidElement; /** * Created by LITP on 2016/9/7. */ @Listeners({com.example.base.AssertionListener.class}) public class BaseAppium { //调试设备名字 public static String deviceName = "minote"; //调试设备系统版本 public static String platformVersion = "4.4.2"; //app路径 public static String appPath = System.getProperty("user.dir") + "/src/main/java/apps/shouhu2.2.3.apk"; //包名 public static String appPackage = "com.minstone.mdoctor"; //是否需要重新安装 public static String noReset = "True"; //是否不重新签名 public static String noSign = "True"; //是否使用unicode输入法,真是支持中文 public static String unicodeKeyboard = "True"; //是否祸福默认呢输入法 public static String resetKeyboard = "True"; //要启动的Activity public static String appActivity = appPackage + ".activity.login.WelcomeActivity"; public AndroidDriver<AndroidElement> driver = null; //单个触摸操作类 TouchAction touchAction; //多个触摸操作时间 MultiTouchAction multiTouchAction; private static int WAIT_TIME = 10; //默认的等待控件时间 private static int SWIPE_DEFAULT_PERCENT = 5; //默认滑动比例 //构造方法 public BaseAppium() { this(new Builder()); } public BaseAppium(Builder builder) { print("基类初始化!"); appActivity = builder.appActivity; appPackage = builder.appPackage; appPath = builder.appPath; deviceName = builder.deviceName; noReset = builder.noReset; noSign = builder.noSign; unicodeKeyboard = builder.unicodeKeyboard; resetKeyboard = builder.resetKeyboard; } /** * appium启动参数 * * @throws MalformedURLException */ @BeforeSuite public void beforeSuite() throws MalformedURLException { DesiredCapabilities capabilities = new DesiredCapabilities(); capabilities.setCapability("deviceName", deviceName); capabilities.setCapability("platformVersion", platformVersion); capabilities.setCapability("app", new File(appPath).getAbsolutePath()); capabilities.setCapability("appPackage", appPackage); //支持中文 capabilities.setCapability("unicodeKeyboard", unicodeKeyboard); //运行完毕之后,变回系统的输入法 capabilities.setCapability("resetKeyboard", resetKeyboard); //不重复安装 capabilities.setCapability("noReset", noReset); //不重新签名 capabilities.setCapability("noSign", noSign); //打开的activity capabilities.setCapability("appActivity", appActivity); //启动Driver driver = new AndroidDriver<>(new URL("http://127.0.0.1:4723/wd/hub"), capabilities); } @AfterTest public void afterTest() { //结束这次测试 driver.quit(); } public boolean isIdElementExist(String id) { return isIdElementExist(id, false); } /** * 根据id判断当前界面是否存在并显示这个控件 * * @param id 要查找的id * @param isShow 是否判断控件显示 * @return 返回对应的控件 */ public boolean isIdElementExist(String id, boolean isShow) { AndroidElement ae; try { if (driver != null) { ae = driver.findElementById(appPackage + ":id/" + id); if (isShow) { return ae.isDisplayed(); } else { return ae != null; } } else { print("driver为空"); } } catch (NoSuchElementException e) { print("找不到控件" + e.getMessage()); } return false; } /** * 选择当前界面的有这个文字的控件 * * @param name * @param hasShow 是否显示 * @return */ public boolean isNameElementExist(String name, boolean hasShow) { try { AndroidElement ae = driver.findElement(By.name(name)); if (hasShow) { return ae.isDisplayed(); } else return ae != null; } catch (NoSuchElementException e) { return false; } } public boolean isNameElementExist(String name) { return isNameElementExist(name, false); } /** * 判断控件时候存在 * * @param by By * @param timeout 等待的事件 * @return */ public boolean isElementExist(By by, int timeout) { try { waitAuto(by, timeout); return true; } catch (Exception e) { return false; } } /** * 根据id获取当前界面的一个控件 * * @param id 要查找的id * @return 返回对应的控件 */ public AndroidElement findById(String id) { try { if (driver != null) { return driver.findElementById(appPackage + ":id/" + id); } else { print("driver为空"); } } catch (NoSuchElementException e) { print("找不到控件" + e.getMessage()); } return null; } /** * 选择当前界面的有这个文字的控件 * * @param name 内容 * @return 找到的控件 */ public AndroidElement findByName(String name) { return driver.findElement(By.name(name)); } /** * 根据id获取当前界面的一个控件 * * @param name 要查找的控件的类名 * @return 返回对应的控件 */ public AndroidElement findByClassName(String name) { try { if (driver != null) { return driver.findElementByClassName(name); } else { print("dricer为空"); } } catch (NoSuchElementException e) { print("找不到控件" + e.getMessage()); } return null; } /** * 打印字符 * * @param str 要打印的字符 */ public <T> void print(T str) { if (!TextUtils.isEmpty(String.valueOf(str))) { System.out.println(str); } else { System.out.println("输出了空字符"); } } /** * Click点击空格键 * * @param ae 要点击的控件 * @return 返回是否点击 */ public boolean clickView(AndroidElement ae) { return clickView(ae, ""); } /** * Click点击控件 * * @param ae 控件 * @param str 控件的文字描述,供错误时候输出 * @return 返回是否存在控件 */ public boolean clickView(AndroidElement ae, String str) { if (ae != null) { ae.click(); return true; } else { print(str + "为空,点击错误"); } 

转载于:https://www.cnblogs.com/111testing/p/7823815.html

Appium的Java封装相关推荐

  1. java appium_Android应用开发之AS+Appium+Java+Win自动化测试之Appium的Java测试脚本封装(Android测试)...

    本文将带你了解Android应用开发AS+Appium+Java+Win自动化测试之Appium的Java测试脚本封装(Android测试),希望本文对大家学Android有所帮助. 一.为什么需要封 ...

  2. Java封装OkHttp3工具类

    点击关注公众号,Java干货及时送达  作者:如漩涡 https://blog.csdn.net/m0_37701381 Java封装OkHttp3工具类,适用于Java后端开发者 说实在话,用过挺多 ...

  3. Java:封装的概念,UML类图,构造方法,this关键字,static关键字,方法重载,包package

                     oop三大特性:封装,继承,多态 oop一般指面向对象程序设计(一种计算机编程架构) 一.封装的概念:    将东西包在一起,然后以新的完整形式呈现出来       ...

  4. 基于java封装的语言_封装在java中的应用

    封装在java中的应用 发布时间:2020-07-01 11:53:47 来源:亿速云 阅读:92 作者:Leah 本篇文章给大家分享的是有关封装在java中的应用,小编觉得挺实用的,因此分享给大家学 ...

  5. java dsp_GitHub - Onemeaning/JavaDsp: 数字信号处理(DSP)方面的Java封装,包含常用的一些处理方法,如滤波、信号变换等等。...

    JavaDsp 数字信号处理(DSP)方面的Java封装,包含常用的一些处理方法,如滤波.信号变换等等. 该类库是我本科毕业设计中的一部分,绝大部分都是我自己写实现的,很少部分算法有我另外几个朋友参与 ...

  6. java封装原则_跟我学java编程—理解Java面向对象的封装原则

    前面一节内容讲到了抽象与对象,抽象是把同类事物的共同特征抽取出来归纳为类,类的具体实例为对象.例如:把具有汁液多.糖分多.含有挥发性芳香物质.可以生食等特征的事物归纳为水果类,苹果.葡萄.生梨则为水果 ...

  7. java 集成 v8_J2V8首页、文档和下载 - V8 的 Java 封装版本

    J2V8 是 V8 引擎的 Java 封装版本,注重性能和紧密集成. 示例代码:V8 v8 = V8.createV8Runtime(); V8Array result = v8.executeArr ...

  8. leveldb java实例_EZDB首页、文档和下载 - LevelDB 的 Java 封装 - OSCHINA - 中文开源技术交流社区...

    EZDB 为 LevelDB 提供一个很好的 Java 封装. 功能包括:Key/value 查询 Hash/range 查询 (类似 Amazon 的 DynamoDB) 可插入式的序列化 可插入式 ...

  9. java封装数组_Java封装数组之动态数组实现方法详解

    本文实例讲述了Java封装数组之动态数组实现方法.分享给大家供大家参考,具体如下: 前言:在此之前,我们封装的数组属于静态数组,也即数组空间固定长度,对于固定长度的数组当元素超过容量时会报数组空间不足 ...

最新文章

  1. angular artDialog未及时更新
  2. ant 合并 jar
  3. android如何导入活动,关于android:如何将活动值传递给另一个活动(Kotlin)
  4. 前端学习(2449):发布文章组件
  5. 国科大提出FreeAnchor,新一代通用目标检测方法,代码已开源
  6. c语言switch scanf语句,c语言switch语句 谢谢·!~!~
  7. golang 的 tag
  8. 好用的python表白神器_Python|520表白神器
  9. python 提取最小外接矩形_python给人脸带上口罩(简单版)
  10. 【转】12 TOP Command Examples in Linux
  11. 凸优化第九章无约束优化 9.1无约束优化问题
  12. 麒麟官方应用商店下载地址
  13. 软考初级程序员常见类型题,错题个人笔记
  14. selenium爬取新浪滚动新闻
  15. 你的梦想是什么?灿星文化眼含热泪只想IPO
  16. Python根据地名获取经纬度
  17. 认识计算机课件小游戏,2013年小学信息技术教案《认识计算机二》教案
  18. 凸显文化+科技融合创新,第九届漫博会VR AR技术应用强势来袭
  19. 实战为上!深入解析20个运维命令
  20. MYSQL获取当前时间、前一天时间,前一个月时间

热门文章

  1. SpringBoot项目使用nacos,kotlin使用nacos,java项目使用nacos,gradle项目使用nacos,maven项目使用nacos
  2. 2022-2028年中国塑料编织品的制造行业市场竞争态势及投资方向分析报告
  3. GCC 编译 C++ 程序分步骤流程(预处理 gcc -E、编译 gcc -S、汇编 gcc -c 和链接 gcc 以及 gcc -o 选项)
  4. 不同的设计模式的特点总结
  5. 地理围栏API服务开发
  6. Pass Infrastructure基础架构(上)
  7. AlexeyAB DarkNet YOLOv3框架解析与应用实践(六)
  8. 2021年大数据Kafka(九):kafka消息存储及查询机制原理
  9. C++ sizeof 运算符的使用
  10. python 怎样让 print 打印的结果不换行