前言:

用appium做UI自动化,测试APP里面的H5和测试手机浏览器打开的H5的操作流程上是有所区别的。比如要测试APP内嵌的H5需要先操作appium启动APP,然后通过context切到webview模式,才能操作H5页面,但是如果测试手机网页的话就比较简单了,设置好浏览器比如选择Chrome,直接访问网址就好了。

------------------------------------------------#  增加知识简介

原生应用程序:(Native App)

原生APP是什么?原生APP就是利用Android、iOS平台官方的开发语言、开发类库、工具进行开发。比如安卓的java语言,iOS的object-c 语言。在应用性能上和交互体验上应该是最好的。
优点:
  1、可访问手机所有功能、可实现功能最齐全;
  2、运行速度快、性能高,绝佳的用户体验;
  3、支持大量图形和动画。不卡,反应快。
  4、比较快捷地使用设备端提供的接口,处理速度上有优势。
缺点:
  1.在过去主要是成本高、周期长,Android和iOS都需要单独开发。
  2.更新版本需要重新下载安装包。

混合应用程序(Hybrid App)

Hybrid APP指的是半原生半Web的混合类App。需要下载安装,看上去类似Native App,但只有很少的UI Web View,访问的内容是 Web ,即利用了原生APP的开发技术还应用了HTML5开发技术,是原生和HTML5技术的混合应用。混合比例不限。
例如Store里的新闻类APP,视频类APP普遍采取的是Native的框架,Web的内容。
Hybrid App 极力去打造类似于Native App 的体验,但仍受限于技术,网速,等等很多因素。尚不完美。

优点:
  1、开发周期短;
  2、功能更新发布快;
缺点:
  1、用户体验不如本地应用;
  2、性能稍慢(需要连接网络);

Web版APP (Web App)

本质就是浏览器功能的叠加,用普通Web开发语言开发的,通过浏览器运行。
优势:
  1、支持范围广;
  2、开发成本低、周期短。
缺点:
  1、对联网要求高,离线不能做任何操作;
  2、功能有限;
  3、运行速度慢,页面不能承载太多东西;
  4、图片和动画支持性不高;
  5、如果用户使用更多的新型浏览器,那么就会出现运行问题。

Web App、Hybrid App、Native App 技术特性

APP内嵌H5:

如何判断APP里面是否有H5呢, 使用uiautomaterview的时候发现页面元素含有webview,这就说明这个APP是混合应用,那么如何测试这个APP内部的H5页呢?

准备工作:

移动端

在eclipse/IDEA 中配置AndroidSDK环境(Android6.0、ADT23.0)
将手机与PC通过USB连接,开启USB调试模式;
使用360手机助手或在dos窗口输入adb devices查看手机驱动连接是否成功;

PC端

在Chrome浏览器地址栏输入chrome://inspect,进入调试模式;
此时页面显示了手机型号、驱动名称、APP要调试的WebView名称;
点击inspect,若成功加载与APP端相同界面的调试页面,则配置成功;
若获取不到WebView或者调试页面预览框显示空白,则需要进行VPN破解–安装翻墙软件(由于默认的DevTools使用的是appspot服务器,这在国内是需要翻越GWF)

原理:

Appium通过 chromedriver-port 9515端口进行通信,驱动安卓手机上的WebView;

查看手机系统应用Android System WebView显示的Chrome版本,下载与之对应的chromedriver并添加到Appium安装目录下的chromedriver目录,保证驱动程序版本对应,Appium后台启动时会自动重启chromedriver,此时后台不会出现等待chromedriver启动现象;

//杀掉chromedriver进程并重启,要先切换到NATIVE_APP(包括微信端)
public static void RestartChromedriver() throws Exception{
Runtime.getRuntime().exec("taskkill /F /im chromedriver.exe");
System.setProperty("webdriver.chrome.driver", "D:\\Appium\\node_modules\\appium\\node_modules\\appium-chromedriver\\chromedriver\\win\\chromedriver.exe");
}

如果端口被占用了,先停掉端口应用,再启动chromedriver

Appium切换context、切换webview

import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.WebElement;
import com.tms.app.itms.logs.Log;
import io.appium.java_client.android.AndroidDriver; public class ITMS_GetElement{
public static void getContextHandle(AndroidDriver<WebElement> driver) {
Set<String> context = null ;
for(int i=1;i<=20;i++){
context = driver.getContextHandles();
for(String contextName : context) {
System.out.println(contextName);//打印当前上下文
if(contextName!=null && contextName.contains("WEBVIEW_com.quantum.Tmsp7")||contextName.contains("WEBVIEW_com.tencent.mm:tools")){
switchTo_WEBVIEW(driver);
driver.getPageSource();
return;
}
if(i==20) assert false;
}
Log.goSleep(1);
}
} public static void switchTo_WEBVIEW(AndroidDriver<WebElement> driver) {
String str = driver.currentActivity();//检查当前APP for(int k=0;k<30;k++){
try {
if(str.equals(".MainActivity")){
driver.context("WEBVIEW_com.quantum.Tmsp7");
return;
}else if(str.equals(".plugin.webview.ui.tools.WebViewUI")){
driver.context("WEBVIEW_com.tencent.mm:tools");
return;
}
} catch (Exception e) {
if(k<10){
Log.info("switch...");
}if(k==30){
Log.fatal(driver, "switch fail!", e);
}
} finally{
driver.manage().timeouts().implicitlyWait(1, TimeUnit.SECONDS);
}
}
}
}

切换到webdriver之后,测试脚本类似Selenium,后面就可以像测试WEBUI一样写脚本了(注意: 此时的appium方法将无法使用!!!)

//loginSubmit
ITMS_GetElement.getContextHandle(driver);
driver.findElementById("username").sendKeys("15029200344");
driver.findElementById("password").sendKeys("111111");
driver.findElementByCssSelector("#loginSubmit").click();
// switchTo_NATIVE 获取当前地理位置——检查[允许]按钮
ITMS_GetElement.getAlertTitleNewThread(driver);//小米、华为
Thread.sleep(3000);
ITMS_GetElement.switchTo_WEBVIEW(driver);
driver.quit();

项目实战中我发现各位可能遇到如下问题:

1. 从1个webview页面跳转到另外一个webview页面,此时即便你切换到了WEBVIEW也无法操作页面元素

解决方法: 切换WEBVIEW的标题 ,通过如下方法可以确保你识别当前的webview页面元素

public static void switchToWindowTitle(String windowTitle) {
try {
String currentHandle = driver.getWindowHandle();
Set<String> handles = driver.getWindowHandles();
for (String s : handles) {
if (s.equals(currentHandle))
continue;
else {
driver.switchTo().window(s);
if (driver.getTitle().contains(windowTitle)) {
Log.logInfo("Switch to window: "
+ windowTitle + " successfully!");
break;
} else
continue;
}
}
} catch (NoSuchWindowException e) {
Log.logInfo("Window: " + windowTitle
+ " cound not found!" + e.fillInStackTrace());
}
}

直接测试浏览器:

这一块没什么难度,主要是通过appium连接真机,然后启动你要测试的浏览器,后面的测试用例编写就和Selenium 一样了

模块的主要作用就是连接真机,所需的参数我没有直接写死在代码里面而是通过配置文件读取到程序里面,这个是为了后面部署到jenkins上面方便配置,具体可以参见工程里面的MyConfig.prop文件。

package testdriver;

import io.appium.java_client.android.AndroidDriver;
import io.appium.java_client.ios.IOSDriver;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.remote.DesiredCapabilities;
import testdata.GlobalVars;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Properties; public class BaseDriver { public static WebDriver driver; /**
* 启动driver
* @return
*/
public void startDriver() throws MalformedURLException { /**
* 初始化appium webdriver
*/
initializeTestData(); DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability("deviceName", GlobalVars.DEVICE_NAME);
capabilities.setCapability("browserName", GlobalVars.BROWER_NAME);
capabilities.setCapability("platformVersion", GlobalVars.PLATFORM_VERSION);
capabilities.setCapability("platformName", GlobalVars.PLATFORM_NAME );
capabilities.setCapability("noReset", GlobalVars.NO_RESET);
capabilities.setCapability("unicodeKeyboard", true);
capabilities.setCapability("resetKeyboard", true); if (GlobalVars.PLATFORM_NAME.contains("iOS")){
capabilities.setCapability("udid", GlobalVars.UDID);
driver = new IOSDriver(new URL(GlobalVars.APPIUM_SERVER), capabilities);
}else{
driver = new AndroidDriver(new URL(GlobalVars.APPIUM_SERVER), capabilities);
} driver.get(GlobalVars.TEST_URL);
} /**
* 退出driver
*/
public void stopDriver(){
driver.quit();
} /**
* 初始化测试环境数据
*/
private void initializeTestData(){
Properties prop = new Properties();
try{ //读取属性文件a.properties
InputStream in = new BufferedInputStream(new FileInputStream("MyConfig.prop"));
///加载属性列表
prop.load(in); GlobalVars.DEVICE_NAME = prop.getProperty("device_name");
GlobalVars.PLATFORM_NAME = prop.getProperty("platform_name");
GlobalVars.PLATFORM_VERSION = prop.getProperty("platform_version");
GlobalVars.UDID = prop.getProperty("udid");
GlobalVars.BROWER_NAME = prop.getProperty("brower_name");
GlobalVars.APPIUM_SERVER = prop.getProperty("appium_server");
GlobalVars.NO_RESET = prop.getProperty("no_reset").equals("true")?true:false;
GlobalVars.TEST_URL = prop.getProperty("test_url"); in.close();
}
catch(Exception e){
System.out.println(e);
}
} }

配置文件:

device_name=i
platform_name=Android
platform_version=7.0
brower_name=chrome
udid=827dc51fd4adcc5234164e581f63bcba11547923
appium_server=http://127.0.0.1:4723/wd/hub
no_reset=true
test_url=http://m.baidu.com

PageHomeElms主要功能是对页面元素的初始化并提供页面元素的对象。 初始化元素用到了两种方式,
首先该类初始化的时候回通过PageFactory模式定位到当前页面已经加载出来并且被@FindBy标记的元素,
如果元素是后加载的或者PageFactory没有定位到的话后面还可以通过webdriver的findElement方法定位

package pageobjects.pages;

import pageobjects.baseclass.PageObjectBase;
import pageobjects.pageselements.PageHomeElms; public class PageHome extends PageObjectBase { private PageHomeElms homePageElms = new PageHomeElms(); /**
* home页面的无参构造函数,初始化一下页面元素
*/
public PageHome(){
//页面元素初始化,只订单当前页面已经加载完的元素
homePageElms = homePageElms.initElements();
} public PageHome inputSearchWord(String keyword){
input(homePageElms.getSearchBox(),keyword);
return this;
} public PageHome tapSearchBtn(){
tap(homePageElms.getIndexBtn());
return this;
} }

PageHome的主要功能是向testcase提供页面的各种操作,比如页面的滑动,元素的点击,是否可见等。

package pageobjects.pageselements;

import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import pageobjects.baseclass.ElementsBase; /**
* Home页面的元素
*/
public class PageHomeElms extends ElementsBase { //搜索输入框
public static final String xpathSearchBox = "//*[@id=\"index-kw\"]";
public static final By locatorSearchBox = new By.ByXPath(xpathSearchBox);
@FindBy(xpath = xpathSearchBox)
private WebElement searchBox; //"百度一下"button,以下列举了三种xpath方式获取元素
//public static final String xpathIndexBtn = "//*[@class=\"se-bn\"]";
//public static final String xpathIndexBtn = "//*[@id=\"index-bn\"]";
public static final String xpathIndexBtn = "//button[contains(text(),'百度一下')]";
public static final By locatorIndexBtn = new By.ByXPath(xpathIndexBtn);
@FindBy(xpath = xpathIndexBtn)
private WebElement indexBtn; /**
* 初始化元素
* @return 当前页面对象
*/
public PageHomeElms initElements(){
//通过PageFactory工具加载当前页面已有元素,未加载的元素后续可以通过定位器单独找到
return locatePgElms(PageHomeElms.class);
} /**
* 获取元素 SearchBox, 如果PageFactory方式没有定位到该元素,
* 则通过传统的方式获取
* @return
*/
public WebElement getSearchBox(){
if (searchBox == null){
return locateElement(locatorSearchBox);
}else{
return searchBox;
}
} /**
* 获取元素 IndexBtn, 如果PageFactory方式没有定位到该元素,
* 则通过传统的方式获取
* @return
*/
public WebElement getIndexBtn(){
if (indexBtn == null){
return locateElement(locatorIndexBtn);
}else{
return indexBtn;
}
} }

测试用例:

package testcases;

import org.testng.annotations.*;
import pageobjects.baseclass.PgNavigator;
import testdriver.BaseDriver;
import java.net.MalformedURLException; public class TestCaseBase { public BaseDriver baseDriver = new BaseDriver(); public PgNavigator pgNavigator; @BeforeSuite
public void beforeSuit() throws MalformedURLException {
//整个测试库运行期间只启动一次driver
baseDriver.startDriver();
} @BeforeClass
public void beforeClass(){ } @BeforeMethod
public void beforeTest(){
//每个测试方法运行前清空一下页面池
pgNavigator = new PgNavigator();
} @AfterMethod
public void afterTest(){ } @AfterClass
public void afterClass(){ } @AfterSuite
public void afterSuit(){
baseDriver.stopDriver();
} }

详细可参考:https://blog.csdn.net/armarm9/article/details/82111278

APP内的H5页面测试方法, 移动端的浏览器(例如UC浏览器)测试方法的更多相关文章

  1. ios下app内嵌h5页面是video适配问题

    ios下做新闻详情用h5页面实现然后打包到app中,其中新闻详情页会有视频,安卓下video的poster可以做到适应video大小,但是ios下会按照poster图片大小将video等比撑大,但是视 ...

  2. app内嵌h5页面在ios手机端滑动卡顿的解决方法

    1.带滚动条的dom需加样式 -webkit-overflow-scrolling: touch;2.去掉 width:100%; height:100%

  3. app内嵌 h5页面 再滑动的时候 触发击穿底下的一些touchstart事件

    我们的目的是再滑动的时候 不要触发到touchstart事件. // 再滑动的时候无法点开视频 var is_scroll_start,is_scroll_end; $(window).on({ 't ...

  4. APP中内嵌H5页面为什么不能下载?

    在APP中内嵌H5页面,若页面上存在下载链接,没有任何反应,为什么呢? 原因是app中内嵌的H5页面是WebView解析的,什么是WebView呢? 在Android手机中内置了一款高性能webkit ...

  5. 客户端相关知识学习(一)之混合开发,为什么要在App中使用H5页面以及应用场景、注意事项

    混合开发 随着移动互联网的高速发展,常规的开发速度已经渐渐不能满足市场需求.原生H5混合开发应运而生,目前,市场上许多主流应用都有用到混合开发,例如支付宝.美团等.下面,结合我本人的开发经验,简单谈一 ...

  6. APP分享视频H5页面

    男左女右中国APP需要做一个APP分享视频H5页面,效果图见下面的图. 出现的问题: (1)URL参数为中文的时候乱码: (2)vedio点击默认是QQ,微信的播放器: (3)给视频添加一个默认的封面 ...

  7. 小程序中webview内嵌h5页面

    小程序内嵌h5页面跳转小程序指定页面,  需要引用  JSSDK:   <script src="https://res.wx.qq.com/open/js/jweixin-1.3.2 ...

  8. 利用浏览器调试APP中的H5页面

    安卓手机的情况下,可以用chrome浏览器来调试. 打开地址: chrome://inspect/#devices 手机用USB数据线连接电脑,并启动USB调试模式. 只要在APP中打开H5页面,界面 ...

  9. 禁止微信内的H5页面上下拖动

    客户需求:禁止微信内的H5页面上下拖动: 解决方案: 网上的答案几乎都是阻止默认事件,即: document.body.addEventListener('touchmove' , function( ...

随机推荐

  1. PHP Composer 包管理器的安装和使用

    一,包管理器的安装 01,首先确定 php 命令能够全局使用,要是不能请修改环境变量 02,使用 curl 命令安装 => curl -sS http://install.phpcomposer ...

  2. Oracle的基本数据类型(常用)

    转自:https://www.2cto.com/database/201810/783959.html 1.字符型 Char 固定长度字符串 占2000个字节 Varchar2 可变长度字符串 占40 ...

  3. delphi 调用 c++builder

    delphi 调用 c++builder c++builder 调用delphi 混合调用,mix https://community.embarcadero.com/blogs/entry/mixi ...

  4. java的第一次博客

    一枚16年本科毕业的java程序员,至今工作两年,这是我的第一个博客. 谢谢!!!

  5. 模糊查询内存查询java实现

    下面说说看到的工作项目中的代码,是这个样子的,事先查询一次数据库,将查询到的整张表的数据存到内存,以后使用时不再查询数据库,而直接操作内存中的数据,这主要用于数据库中的数据比较稳定,不会轻易改变的情况 ...

  6. shell字符串基本操作

    shell脚本中一切变量皆字符串,所以必须掌握字符串的常用处理方法.比如获取字符串长度.获取字符串指定位置字符.替换字符串中的指定字符或者删除某些字符等操作. 1.字符串操作列表 (1)var=val ...

  7. 知识点4: 配置echarts折线图和饼图

    折线图 效果图 html <template> <div id="v11-charts3"></div> </template> j ...

  8. 在JSP页面中导入jstl标签库

    1 在工程中引用JSTL的两个jar包和标签库描述文件. (1)在项目上右击,从弹出的快捷键菜单中选择Properties命令,在出现的项目属性对话框上,选择DeploymentAssembly. ( ...

  9. 在webpack构建的项目中使用vue

    一.复习在普通网页中使用vue1.使用script引入vue2.在index中创建 id为app的容器3.通过new vue得到vm实例二.在webpack中尝试使用vue://注意 : 在webpa ...

  10. vue分页 点击(非下拉)

    1.主页面 <template> <div class="list"> <template v-if="count"> 55 ...