百度/微信小程序自动化测试总结

目 录:

1. 小程序自动化方案
  1.1 小程序的基本构成
  1.2 原生组件定位之UiSelector
     1.2.1 原生组件定位之UiSelector
     1.2.2 web元素定位
  1.3 小程序自动化准备
    1.3.1 安装appium
    1.3.2 安装adb tools
    1.3.3 chromedriver.exe版本
    1.3.4 打开手机的开发者选项
    1.3.5 打开webview的debug模式
    1.3.6 关于context切换
    1.3.7 关于windowHandles
    1.3.8 常见的问题
2. 微信小程序自动化
  2.1 开启微信webview debug模式
  2.2 开始你的自动化demo
    2.2.1 启动appium服务
    2.2.2 确认小程序的androidProcess参数
    2.2.3 爱奇艺视频小程序demo
3. 百度小程序自动化
  3.1 安装百度智能小程序调试包
  3.2 确认androdProcess进程名
  3.3 百度小程序demo
4. 小程序自动化库
  4.1 百度小程序接口
  4.2 微信小程序接口
  4.3 安卓常用操作接口Device
  4.4 命令行操作接口Command
  4.5 图像识别AirCv

1. 小程序自动化方案

目前小程序自动化主要有以下三种方案:

网易的Airtest在图像识别元素上做的很不错,但爱奇艺视频小程序固定的UI元素非常少,大部分都是视频封面图,应用自动化比较受限制。
腾讯的FAT是腾讯测试团队刚开源的框架,粗略看了下代码,可能对腾讯自家的APP支持的比较好,比如微信、qq浏览器等,但如果要测试其他的小程序,比如百度/支付宝小程序,可能还需要一些修改源代码的成本,目前社区也不太活跃,对于其执行效率,宣传说是比Appium要高,但我暂时未写demo详细去对比,具体性能数据未知。
最终还是选择了appium框架,再加Airtest图像识别功能辅助测试,appium社区相对来说活跃度较高,维护团队稳定。

1.1 小程序的基本构成

小程序融合了Native app和web-app的特性,属于混合型应用(Hybrid App)。以爱奇艺视频微信小程序为例,上面的TopActionBar和下边的Bottom Action Bar是属于原生的组件,而中间是由webview渲染的,属于web应用。


image.png

对于安卓原生的UI组件,我们可以直接用UIAutomator查看元素属性,如下图所示


image.png

1.2 原生组件和web元素定位

1.2.1 原生组件定位之UiSelector

UiSelector对于各种原生组件属性的匹配,有以下四种匹配关系:

  • 完全匹配
  • 包含匹配
  • 正则匹配
  • 起始匹配

每个原生组件有很多属性,如resource-idtextclasscontent-desc等,这些是比较常用的,还有如下属性

属性值 值类型 说明
index        int        索引:同级组件的下标;从0开始计
instance     int        界面中同一类View的所有实例的下标;从0开始计
class        String     组件的类名,如 android.widget.TextView
package      String     包名
Content-desc String     描述
checkable    boolean    是否可选,一般只对 单选或 复选框有用。
checked      boolean    单选或 复选框 是否被选中
clickable    boolean    是否可点击
enabled      boolean    是否可操作,如 按钮置灰不可操作状态
focusable    boolean    是否可获取焦点
focused      boolean    是否获取到焦点
Scrollable   boolean    是否可滚动,一般是list
Long-clickable  boolean 是否可长按
password     boolean    是否密码
selected     boolean    是否具有背景选择属性,如按钮点击后背景色变化
bounds       Rect       坐标,如 [366,999][708,1197]表示控件的矩形区域左上和右下坐标点

appium中查找原生组件的方法可用findElementByAndroidUIAutomator,以下会省略该方法名,直接写UiSelector

driver.findElementByAndroidUIAutomator("new UiSelector().text(\"爱奇艺视频\")")
  • ID属性resource-id定位
//resourceId全匹配
new UiSelector().resourceId("com.baidu.searchbox.remotedebug:id/baidu_searchbox")
//正则匹配baidu_searchbox结尾
new UiSelector().resourceIdMatches(".*baidu_searchbox")
//包含匹配,包含SearchTextInput的组件
new UiSelector().resourceIdContains("SearchTextInput")
//起始匹配
new UiSelector().resourceIdStartsWith("com.baidu.searchbox.remotedebug")
  • 文本属性text定位
//通过文本定位
driver.findElementByAndroidUIAutomator("new UiSelector().text(\"爱奇艺视频\")")
//正则匹配查找未登录或我的
new UiSelector().textMatches("未登录|我的")
new UiSelector().textMatches("爱奇艺.*")
//包含我的
new UiSelector().textContains("我的")
//以首开头
new UiSelector().textStartsWith("首")
//查找界面中文本为“微信红包”的第3个组件
new UiSelector().text("微信红包").instance(2);
  • 描述属性content-desc
//通过文本定位
driver.findElementByAndroidUIAutomator("new UiSelector().description(\"更多\")")
new UiSelector().descriptionMatches("更多\w+")
new UiSelector().descriptionContains("更多")
new UiSelector().descriptionStartsWith("更多")
  • 其他属性
//类名为android.widget.RelativeLayout,下标index为5的
new UiSelector().className("android.widget.RelativeLayout").index(5);
//包名为com.android.deskclock的第五个组件
new UiSelector().packageName("com.android.deskclock").instance(5)
//checkable属性为true的
new UiSelector().checkable(true);
new UiSelector().longClickable(true).index(4);

  • 节点关系复杂定位
    - 父:Parent
    - 子: Children
    - 同胞: Sibling
    - 先辈: Ancestor
    - 后代:Descendant
//childselector查找子类
new UiScrollable(new UiSelector().scrollable(true)
.childSelector(new UiSelector().text("Android")))

//formParent查找父类
new UiSelector().resourceId("com.baidu.searchbox.remotedebug:id/search_list")
.fromParent(new UiSelector().className("android.widget.LinearLayout").index(1));

1.2.2 web元素定位

文档较多,不列举

1.3 小程序自动化准备

JAVA: 1.8
node js : 10.14.2
adb: 1.0.40
appium : 1.8.1

1.3.1 安装appium

  • 安装node环境
$ node -v
v10.14.2

$ npm -v
6.4.1
  • 利用npm全局安装appium
npm install appium@1.8.1 -g
#安装需要一定时间,安装完成后
$ appium -v
1.8.1

1.3.2 安装adb tools

参考:Android测试环境搭建

$ adb --version
Android Debug Bridge version 1.0.40
Version 4986621
Installed as D:\Program Files\androidsdk\Android\Sdk\platform-tools\adb.exe

1.3.3 chromedriver.exe版本

appiumDriver切换webview context需要用到chromedriver,每个app使用的webview版本可能不同,所以需要不同版本的chromedriver与之对应。详见:
http://appium.io/docs/cn/advanced-concepts/chromedriver/

1.3.4 打开手机的开发者选项

每个手机开启的方式不一样,自行搜索。

  • 小米手机需要打开开发者选项、安全模式、关闭miui优化
    开启后,通过命令adb devices验证,如果能发现设备说明开启成功
ceshi@DESKTOP-UE2D6JR F:\android-perf-recorder
> adb devices
List of devices attached
ce96dc1b        device
d24c3bcc        device
  • adb无法识别的问题排查
  1. 确认数据线没问题
  2. 按教程:https://jingyan.baidu.com/article/ce09321b5b76642bff858f31.html
  3. 还是不行的话,按照教程https://blog.csdn.net/zhouyingge1104/article/details/42145429
  4. 还是不行的话,重新弄一个androidsdk吧。

1.3.5 打开webview的debug模式

要实现小程序的自动化,一个非常重要的步骤就是打开app webview的debug模式。但是app一般不会提供debug模式。验证debug模式是否开启,可以通过如下步骤:

  • 打开APP的小程序,数据线连接至电脑

  • PC打开chrome浏览器输入chrome://inspect

    image.png

  • 找到小程序的webview,点击inspect,可看到小程序界面


    image.png

如果能看到小程序使用的webview,那么表明该webview的debug已开启

1.3.6 关于context切换

appium原本是设计为NATIVE_APP的自动化,为了支持混合应用或APP里的webv页面测试,所以有这一概念。默认拉起app后,进入的NATIVE_APP,一般还会有WEBVIEW_xxx可以查看当前所有的context,python版本:

driver=webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)
driver.contexts
['NATIVE_APP', 'WEBVIEW_com.tencent.mm:tools', 'WEBVIEW_com.tencent.mm:toolsmp']
>>>driver.switch_to.context(u'WEBVIEW_com.tencent.mm:tools')
>>>driver.page_source
'<!DOCTYPE html><html xmlns="http://www.w3.org/1999/xhtml" ......

1.3.7 关于windowHandles

windowhandle可以看成是chrome里一个标签页,小程序每跳转一个新页面,会生成一个新的window handle,但driver并不会自动切换新的window,所以每次查找元素前,都需要手动切换到相应的window,否则会报no such element
目前能想到的笨办法是,找一个能标识每个页面的唯一性元素,然后遍历每个页签,如果page_source有该元素,则切到该页签

>>>driver.window_handles
['CDwindow-56b52630-ffcc-4b1f-88cc-c26d4b5e10ed', 'CDwindow-3168289f-c448-4597-bf21-cf825fd29b5c', 'CDwindow-4a0d4647-27a5-4cfa-92a7-357ee6901c2a']
>>>driver.switch_to.window('CDwindow-3168289f-c448-4597-bf21-cf825fd29b5c')
>>>driver.current_window_handle
'CDwindow-3168289f-c448-4597-bf21-cf825fd29b5c'
>>>driver.title
'中国新说唱官方投票通道'
>>>driver.switch_to.window('CDwindow-4a0d4647-27a5-4cfa-92a7-357ee6901c2a')
>>>driver.title
''
>>>driver.switch_to_window('CDwindow-56b52630-ffcc-4b1f-88cc-c26d4b5e10ed')
>>>driver.title
'百度一下'

1.3.8 常见的问题

  • 如何解决打开页面路径太长的问题
    由于微信小程序没有类似的H5的url,所以得通过点击路径打开目标页面,路径长容易导致稳定性差。解决办法是可通过执行wx api来直接跳转页面,因为在小程序内,开发也是直接调用wx.navigateTo来跳转的,所以想到,能不能通过js executor来执行wx api

    image.png

  • 元素的点击方法无反应
    可以找到元素,但调用元素的点击方法无反应,原因是有的微信元素监听的是tap事件,不是click事件。

    image.png

  • 元素getLocation接口获取的坐标位置不准


    image.png
  • 如何校验视频正在播放

    image.png

  • 切换context一直卡住,appium报chrome not reachable

  1. 确认webview的debug模式开启
  2. 确认chrome://inspect可以看到小程序
  3. 确认androidProcess正确
  4. 微信小程序的话确认是从搜一搜入口进去
  5. 查找appium的日志看报错
  • 查找元素时报no sucn element
  1. 打印pageSource,看是否有相应元素
  2. 打印出所有windowHandles,遍历所有看是否有相应元素
  3. 如果没有,那就不是小程序的webview context,确认androidProcess是否正确
  • chrome version must be >xx
  1. chromedriver版本与小程序的webview版本不匹配
    解决: 启动appium时指定--chromedriver-executable参数,或者将appium的默认chromedriver.exe版本替换
  • 微信点击搜一搜报错
    appium 1.8.1,java-client6.1.0
driver.findElementByAndroidUIAutomator("text(\"搜一搜\")").click()

该行代码报UiAutomator exited unexpectedly with code 4294967295

https://testerhome.com/topics/13496,不是缺少/data/local/tmp/AppiumBootstrap.jar
https://blog.csdn.net/Sily_Z/article/details/80584750,重启手机也不是很好使

看日志是堆栈溢出:[UIAUTO STDOUT] INSTRUMENTATION_RESULT: shortMsg=java.lang.StackOverflowError

改为用adb点击搜一搜也是一样的结果。
https://www.cnblogs.com/chongyou/p/5263198.html,说前面有程序没结束,所以手动清理了后台的微信进程。并设置微信不能一直保持后台运行。还是没解决。
解决:换为uiautomator2版本。

  • uiautomator2一直提示安装uiautomator2.server和uiautomator2.server.test
    解决:小米手机的话,打开usb安装,并关闭miui优化
    或者修改uiautomator2-server源码:
    https://blog.csdn.net/hszxd479946/article/details/78900982

  • 点击报错:java.lang.StackOverflowError

java.lang.StackOverflowError: stack size 1037KB\n\tat android.util.SparseArray.get

https://github.com/appium/appium/issues/10204

  • 想拉微信却拉起了chrome浏览器
    解决:加上以下配置
        caps.setCapability(MobileCapabilityType.BROWSER_NAME,"");
  • uiautomator2报签名错误
java.lang.SecurityException: Permission Denial: starting instrumentation 
ComponentInfo{io.appium.uiautomator2.server.test/androidx.test.runner.AndroidJUnitRunner} 
from pid=19303, uid=19303 not allowed because package io.appium.uiautomator2.server.test 
does not have a signature matching the target io.appium.uiautomator2.server

原因是安装了不同的uiautomator版本,卸载原来的就行。
解决:https://stackoverflow.com/questions/3082780/java-lang-securityexception-permission-denial

adb uninstall io.appium.uiautomator2.server.test

2. 微信小程序自动化

2.1 开启微信webview debug模式

注意:

  • 微信6.7.3版本时代,webview是57版本,此时可通过如下方法打开debug,但必须从微信搜一搜入口打开小程序,才可以切换webview的context,从其他入口均报chrome not reachable
  • 微信6.7.3时代,安卓8.0系统,57版本对应的chromedriver有bug,也包chrome not reachable
  • 微信升级7.0后,webview升级到66版本,此时搜一搜入口也无法切换context
  • 目前只有6.6.7以下版本,可开启debug模式进行自动化

微信打开http://debugx5.qq.comx5调试页面,点击信息,然后勾选【打开TBS内核Inspector调试功能】,勾选后重启微信

image.png
  • 遇到低版本无法登录的问题?
    解决:暂时未找到,貌似跟微信账号还有关系,有的能登,有的不行

手机通过数据线连接电脑,adb devices命令验证连接成功
微信扫码打开爱奇艺视频小程序,chrome浏览器输入chrome://inspect,看能否找到小程序的webivew,点击inspect可查看小程序页面。

2.2 开始你的自动化demo

chrome inspect成功后,恭喜你已经成功准备好环境,下一步便可开始撸代码了

2.2.1 启动appium服务

启动appium服务比较简单,但得注意appium自带的chromedriver版本可能与微信的webview无法匹配。详见:appium与chromedriver
因此,在启动时最好带--chromedriver-executable参数,目前微信webview版本是66,可用2.36版本的chromedriver,启动服务命令如下:

C:\Users\zengzhihua>appium --chromedriver-executable=D:\chromedrivers\chromedriver_2.36.exe --log-level=debug
(node:632) [DEP0005] DeprecationWarning: Buffer() is deprecated due to security and usability issues. Please use the Buffer.alloc(), Buffer.allocUnsafe(), or Buffer.from() methods instead.
[Appium] Welcome to Appium v1.8.1
[Appium] Non-default server args:
[Appium]   chromedriverExecutable: D:\chromedrivers\chromedriver_2.36.exe
[Appium] Appium REST http interface listener started on 0.0.0.0:4723

如果没有报错就ok了,默认开启4723端口

2.2.2 确认小程序的androidProcess参数

appium进行混合应用的自动化,需要androidProcess参数,我理解是小程序在android系统中的进程名,获取方法如下

    1. 打开爱奇艺视频小程序,运行在前端
    1. 输入adb shell进入adb命令行模式,如果是多个设备,需加-s参数
    1. 输入dumpsys activity top|grep ACTIVITY,查看进程号pid
    1. 输入ps pid, pid为上一步获取
$ adb shell
# 打开小程序,然后输入以下命令查看当前活动的进程号
shell@PD1621:/ $ dumpsys activity top|grep ACTIVITY
  ACTIVITY com.tencent.mm/.plugin.appbrand.ui.AppBrandInToolsUI ad729c6 pid=28902
# 查看当前进程号28902的进程信息,进程名为com.tencent.mm:tools。

shell@PD1621:/ $ ps 28902
USER      PID   PPID  VSIZE  RSS   WCHAN            PC  NAME
u0_a227   28902 669   1900832 246896            00000000 R com.tencent.mm:tools
shell@PD1621:/ $

并不是每次都是com.tencent.mm:tools,貌似跟打开小程序的入口有关,有的是com.tencent.mm:toolsmp,还有的com.tencent.mm:appbrand0com.tencent.mm:appbrand1

2.2.3 爱奇艺视频小程序demo

目前打开小程序,必须从首页的搜索按钮或者发现页的搜一搜,搜索爱奇艺视频小程序,然后点击切换到小程序TAB,点击第一个链接(一般第一个链接便是)

/**
 * Created by zengzhihua on 2019/3/30.
 */
import io.appium.java_client.MobileElement;
import io.appium.java_client.android.AndroidDriver;
import io.appium.java_client.remote.AndroidMobileCapabilityType;
import io.appium.java_client.remote.MobileCapabilityType;

import java.net.MalformedURLException;
import java.net.URL;

import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.remote.DesiredCapabilities;

public class WeXinTest {

    static AndroidDriver<MobileElement> driver = null;
    public static DesiredCapabilities getDefaultCapabilities() {
        DesiredCapabilities caps = new DesiredCapabilities();
        ChromeOptions chromeOptions = new ChromeOptions();
        chromeOptions.setExperimentalOption("androidProcess", "com.tencent.mm:tools");
        caps.setCapability(ChromeOptions.CAPABILITY, chromeOptions);
        caps.setCapability(MobileCapabilityType.NEW_COMMAND_TIMEOUT, 1200);
        caps.setCapability(MobileCapabilityType.PLATFORM_NAME, "Android");
        caps.setCapability(MobileCapabilityType.DEVICE_NAME, "34c2ca44");
        caps.setCapability(MobileCapabilityType.FORCE_MJSONWP, true);
        caps.setCapability(AndroidMobileCapabilityType.APP_PACKAGE,  "com.tencent.mm");
        caps.setCapability(AndroidMobileCapabilityType.APP_ACTIVITY, ".ui.LauncherUI");
        caps.setCapability("showChromedriverLog", true);
        caps.setCapability(MobileCapabilityType.AUTOMATION_NAME, "uiautomator2");
        caps.setCapability("noReset", true);
        caps.setCapability("unicodeKeyboard", true);
        caps.setCapability("resetKeyboard", true);
        caps.setCapability(MobileCapabilityType.CLEAR_SYSTEM_FILES, true);
        caps.setCapability(MobileCapabilityType.BROWSER_NAME,"");
//        caps.setCapability("chromedriverExecutableDir", chromeDriverDir);
//        caps.setCapability("chromedriverChromeMappingFile", "D:\\minidrivers\\chromeDriverMapping.json");
//        caps.setCapability(MobileCapabilityType.BROWSER_NAME,"");
//        caps.setCapability(AndroidMobileCapabilityType.AUTO_GRANT_PERMISSIONS, true);
        return caps;
    }

    public static void main(String[] args) throws Exception {
        DesiredCapabilities desired_capabilities = getDefaultCapabilities();
        try {
            driver = new AndroidDriver<>(new URL("http://127.0.0.1:4723/wd/hub"),desired_capabilities);
            String searchIconSelector = "new UiSelector().description(\"搜索\")";
            driver.findElementByAndroidUIAutomator(searchIconSelector).click();
            driver.findElementByAndroidUIAutomator("text(\"搜索\")").sendKeys("爱奇艺视频小程序");
            driver.findElementByAndroidUIAutomator("text(\"小程序、公众号、文章、朋友圈和表情等\"").click();
            Thread.sleep(2000);
            //点击方法可切换到webview查找元素点击。clickByPointPercent方法是根据坐标百分比点击
            clickByPointPercent(30, 15);    //点击小程序标签
            Thread.sleep(2000);
            clickByPointPercent(26, 26);    //点击打开小程序,一般第一个即是目标小程序
            Thread.sleep(5000);
            System.out.println(driver.getContextHandles());
            System.out.println(driver.getContext());
            driver.context("WEBVIEW_com.tencent.mm:tools");
            System.out.println(driver.getWindowHandles());
            System.out.println(driver.getPageSource());
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
    }
}

3. 百度小程序自动化

百度小程序的自动化总体类似,只是需要下载百度的调试包。调试包可下载百度小程序开发者工具,然后点击远程调试,会自动安装百度智能小程序的调试包。

3.1 安装百度智能小程序调试包

手机百度调试包:
链接:https://pan.baidu.com/s/1L1HwW7yYoZ1LlKY7q_KwPA
提取码:khef
百度智能小程序调试包下载地址:
链接:https://pan.baidu.com/s/1tQ3ddlSctowJ_NfV7GjmmA
提取码:rniz

3.2 确认androdProcess进程名

3.3 百度小程序demo

打开小程序方法,从首页搜索“爱奇艺视频”,搜索联想词第一个便是小程序,点击便可打开

/**
 * Created by zengzhihua on 2019/3/30.
 */
import io.appium.java_client.MobileElement;
import io.appium.java_client.android.AndroidDriver;
import io.appium.java_client.remote.AndroidMobileCapabilityType;
import io.appium.java_client.remote.MobileCapabilityType;

import java.net.MalformedURLException;
import java.net.URL;

import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.remote.DesiredCapabilities;

public class WeXinTest {

    static AndroidDriver<MobileElement> driver = null;
    public static DesiredCapabilities getDefaultCapabilities() {
        DesiredCapabilities caps = new DesiredCapabilities();
        ChromeOptions chromeOptions = new ChromeOptions();
        chromeOptions.setExperimentalOption("androidProcess", "com.baidu.searchbox.remotedebug:aiapps0");
        caps.setCapability(ChromeOptions.CAPABILITY, chromeOptions);
        caps.setCapability(MobileCapabilityType.NEW_COMMAND_TIMEOUT, 1200);
        caps.setCapability(MobileCapabilityType.PLATFORM_NAME, "Android");
        caps.setCapability(MobileCapabilityType.DEVICE_NAME, "DEVICE_NAME");
        caps.setCapability(MobileCapabilityType.FORCE_MJSONWP, true);
        caps.setCapability(MobileCapabilityType.AUTOMATION_NAME, "uiautomator2");
        caps.setCapability(MobileCapabilityType.NO_RESET, true);
        caps.setCapability(MobileCapabilityType.CLEAR_SYSTEM_FILES, true);
        caps.setCapability(MobileCapabilityType.BROWSER_NAME,"");
        caps.setCapability("unicodeKeyboard", true);
        caps.setCapability("resetKeyboard", true);
        caps.setCapability("showChromedriverLog", true);

        caps.setCapability(AndroidMobileCapabilityType.APP_PACKAGE, APP_PACKAGE);
        caps.setCapability(AndroidMobileCapabilityType.APP_ACTIVITY, APP_ACTIVITY);
//        caps.setCapability("chromedriverExecutableDir", chromeDriverDir);
//        caps.setCapability("chromedriverChromeMappingFile", "D:\\minidrivers\\chromeDriverMapping.json");
//        caps.setCapability(AndroidMobileCapabilityType.AUTO_GRANT_PERMISSIONS, true);
//        caps.setCapability(AndroidMobileCapabilityType.VERSION, "6.0");
        return caps;
    }

    public static void main(String[] args) throws Exception {
        DesiredCapabilities desired_capabilities = getDefaultCapabilities();
        try {
            driver = new AndroidDriver<>(new URL("http://127.0.0.1:4723/wd/hub"),desired_capabilities);
            String searchInputResourceId = "com.baidu.searchbox.remotedebug:id/baidu_searchbox";
            driver.findElementByAndroidUIAutomator(searchInputResourceId).click();
            Thread.sleep(2000);
            String searchEditTextInputResourceId = "com.baidu.searchbox.remotedebug:id/SearchTextInput";
            driver.findElementByAndroidUIAutomator(searchEditTextInputResourceId).sendKeys(appName);
            Thread.sleep(2000);
            String miniProgramTitleResourceId = "com.baidu.searchbox.remotedebug:id/suggestion_item_title";
            driver.findElementByAndroidUIAutomator(miniProgramTitleResourceId).click();
            Thread.sleep(3000);
            System.out.println(driver.getContextHandles());
            System.out.println(driver.getContext());
            driver.context("WEBVIEW_com.tencent.mm:tools");
            System.out.println(driver.getWindowHandles());
            System.out.println(driver.getPageSource());
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
    }
}

4. 小程序自动化库

在appium的基础上,进行了简单的封装,同时加入了一点图像识别功能,解决难以定位的一些元素。


image.png

4.1 百度小程序接口

  • 提供百度小程序的一些常用操作方法
import com.iqiyi.qa.minidrivers.BaiduDriver;
import org.openqa.selenium.WebElement;

import java.net.URL;

/**
 * Created by zengzhihua on 2019/1/29.
 */
public class BaiduDemo {
    public static void main(String[] s) throws Exception {
        //构造函数
        //1.自启动默认的appium服务; 2.自选择连接的设备并拉起百度智能小程序app
        //BaiduDriver baiduDriver =new BaiduDriver();
        //1.手动启动appium服务
        //BaiduDriver baiduDriver = new BaiduDriver(new URL("http://127.0.0.1:4723/wd/hub"));
        //1..指定连接的设备id
        //BaiduDriver baiduDriver = new BaiduDriver("ce96dc1b");
        //1.手动启动appium服务;2.指定连接的设备id
        //BaiduDriver baiduDriver = new BaiduDriver(new URL("http://127.0.0.1:4723/wd/hub"),"ce96dc1b");
        //其他构造函数
        //public BaiduDriver(AppiumDriverLocalService service, Capabilities desiredCapabilities);
        //public BaiduDriver(AppiumServiceBuilder builder, Capabilities desiredCapabilities);
        //public BaiduDriver(Capabilities desiredCapabilities);
        //打开百度小程序
        baiduDriver.openMiniProgram("爱奇艺视频");
        //查找native原生控件
        WebElement mineTabEle = baiduDriver.findElementByAndroidUIAutomator("new UiSelector().textMatches(\"未登录|我的\")");
        baiduDriver.findElementByAndroidUIAutomator("new UiSelector().textMatches(\"未登录|我的\")").click();
        baiduDriver.pause(3);
        //baiduDriver.findElementByAndroidUIAutomator("new UiSelector().description(\"更多\")").click();
        baiduDriver.findElementByAndroidUIAutomator("text(\"爱奇艺视频\")").click();
        baiduDriver.pause(2);
        //点击坐标
        baiduDriver.clickByPoint(500,500);
        //按坐标滑动
        baiduDriver.swipe(100,1500,600,1500);
        //点击坐标百分比
        baiduDriver.clickByPointPercent(80,95);
        System.out.println(baiduDriver.getWindowSize().getWidth());
        System.out.println(baiduDriver.getWindowSize().getHeight());
        //截图保存默认图片路径
        baiduDriver.getScreenShotAs();
        String viewMoreTmplPath = "E:\\projects\\uiauto-miniprogram\\images\\templates\\openIqiyiBanner.png";
        //按照模板图片查找图片元素
        ImgElement imgEle = baiduDriver.findElementByImg(viewMoreTmplPath);
        //点击图片元素
        imgEle.click();
        //返回上一页
        baiduDriver.goBack();
        baiduDriver.pause(2);
        //返回首页
        baiduDriver.goHome();
        baiduDriver.pause(2);
        //最小化百度小程序
        baiduDriver.closeMiniProgram();
        //切换至百度小程序webview
        baiduDriver.switchToWebview();
        //切换至native context
        baiduDriver.switchToNative();
        //退出百度
        baiduDriver.quit();
        //baiduDriver.getScreenShotAs("E:\\screen.png");
        //System.out.print(baiduDriver.getContext());
        //baiduDriver.context("WEBVIEW_com.baidu.searchbox.remotedebug:aiapps0");
        //baiduDriver.getScreenShotAs("E:\\screen2.png");
    }
}

4.2 微信小程序接口

  • 需安装微信6.6.5版本,高于此版本无法开启tbs调试,chrome://inspect无法成功
  • 提供微信小程序的一些常用操作方法
import com.iqiyi.qa.minidrivers.WxDriver;

import java.net.URL;

/**
 * Created by zengzhihua on 2019/1/29.
 */
public class WxDemo {
    public static void main(String[] s) throws Exception{
//        WxDriver wxDriver = new WxDriver();
//        WxDriver baiduDriver =new WxDriver();
        WxDriver wxDriver = new WxDriver(new URL("http://127.0.0.1:4723/wd/hub"));
        wxDriver.pause(3);
//        wxDriver.openMiniProgramFromSearch("aiqiyishipin");
//        WxDriver wxDriver = new WxDriver();
        wxDriver.openMiniProgram("周黑鸭外卖");
        wxDriver.pause(2);
        wxDriver.clickByPoint(500,500);
        wxDriver.clickByPointPercent(80,95);
        System.out.println(wxDriver.getWindowSize().getWidth());
        System.out.println(wxDriver.getWindowSize().getHeight());
        wxDriver.getScreenShotAs();
        String viewMoreTmplPath = "E:\\projects\\uiauto-miniprogram\\images\\templates\\openIqiyiBanner.png";
//        wxDriver.findElementByImg(viewMoreTmplPath).click();
        wxDriver.goBack();
       wxDriver.pause(2);
       wxDriver.goHome();
       wxDriver.pause(2);
       wxDriver.closeMiniProgram();
       wxDriver.quit();
    }
}

4.3 安卓常用操作接口Device

封装安卓设备的常用方法

import com.iqiyi.qa.device.AndroidDevice;

public class TestDevice {
    public static void main(String[] args) throws Exception{
         Device device = new AndroidDevice();
        //全屏截图
        device.getScreenShotAs("E:\\1.png");
        //执行adb shell 命令
        String output = device.executeShellCommand("wm size");
        //获取当前的ACTIVITY
        String act = device.getCurrentActivity();
        if (!device.isAppInstall("adbkeyboard")){
            device.installPackage("E:\\projects\\uiauto-miniprogram\\src\\main\\resources\\ADBKeyboard.apk");
        }
        //判断是否安装adb输入法
        boolean isExist = device.isAdbKeyboardInstall();
        //安装adb输入法
        device.installPackage("ADBKeyboard.apk");
        //设置adb输入法
        device.setAdbkeyboard();
        //adb输入中文
        device.inputText("小程序");
        //获取手机屏幕尺寸
        Dimension d = device.getWindowSize();
        System.out.println(device.dimension.getHeight());
        System.out.println(device.dimension.getWidth());
        //点击坐标
        device.clickByPoint(500, 500);
        //点击百分比坐标
        device.clickByPointPercent(95, 95);
        device.inputText("爱奇艺视频");
        AndroidDevice.quit();
    }
}

4.4 命令行操作接口Command

执行一些cmd或者shell命令,并拿到返回结果

import com.iqiyi.qa.command.Command;

public class TestCommand {

    public static void main(String[] args) throws Exception{
        String cmdString = "adb shell dumpsys activity top";
        Command command = new Command(cmdString);
        try {
            command.execute();
            String output = command.getStdOut();
            String[] outputLines = output.split("\n");
            for (int i=0;i<outputLines.length;i++) {
                String line = outputLines[i];
                if (line.contains("ACTIVITY")) {
                    String pid = line.split("pid=")[1].replace("\n", "");
                    Command command1 = new Command("adb shell ps " + pid);
                    command1.execute();
                    String output1 = command1.getStdOut();
                    String[] outputArray = output1.replace("\n", "").split(" ");
                    String processName = outputArray[outputArray.length-1];
                    System.out.println(processName);
                    break;
                }
            }
        } catch (InterruptedException | IOException e) {
            e.printStackTrace();
        }

    }
}

4.5 图像识别AirCv

简单的opencv封装,根据给定的模板图片,在目标图片(一般是屏幕截图)中进行匹配,匹配成功后返回对应的坐标点,然后可以根据坐标点,可用device接口对应的操作

import com.iqiyi.qa.aircv.AirCV;

public class TestCv {
    private static float defaultDegree = 0.9f;

    public static void main(String[] args) throws Exception{
        String screenShotPath = "E:\\projects\\uiauto-miniprogram\\images\\screenshots\\2019-02-26\\20190226-140934798.png";
        String templatePath = "E:\\projects\\uiauto-miniprogram\\images\\templates\\openIqiyiBanner.png";
        //在screenShotPath图片上查找templatePath模板图片,相似度最小90%,返回匹配的坐标
        AirCV.getMatchTemplateLoc(screenShotPath, templatePath, 0.9f);
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 162,050评论 4 370
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,538评论 1 306
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 111,673评论 0 254
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,622评论 0 218
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 53,047评论 3 295
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,974评论 1 224
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,129评论 2 317
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,893评论 0 209
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,654评论 1 250
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,828评论 2 254
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,297评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,619评论 3 262
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,326评论 3 243
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,176评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,975评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,118评论 2 285
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,909评论 2 278