APP元素定位方式

图片说明
图片说明

手势操作实战

滑动事件

  1. 向上滑动

    /***
      * 向上滑动
      * (x/2, 8*y/10)->(x/2, 2*y/10)
      * @param AndroidDriver<AndroidElement> driver
      */
     public static void swipeToUp(AndroidDriver<AndroidElement> driver) {
         int x=driver.manage().window().getSize().getWidth();
         int y=driver.manage().window().getSize().getHeight();
         TouchAction action=new TouchAction(driver);
         action.press(PointOption.point(x/2, 8*y/10)).waitAction(WaitOptions.waitOptions(Duration.ofMillis(500))).moveTo(PointOption.point(x/2, 2*y/10)).release().perform();
     }
  2. 手势解锁--支付宝为例

    public void unlock(){
    
         TouchAction action=new TouchAction(driver);
         action.press(PointOption.point(240, 822))
           .moveTo(PointOption.point(544, 822))
           .moveTo(PointOption.point(544, 1122))
           .moveTo(PointOption.point(544, 1422))
           .release().perform();
    //        InitDriver.geUnlock(driver, By.id("com.alipay.mobile.gesturebiz:id/lockView"), new int[] {0,1,4,7});
     }

    封装一下

    /**
      * 思路:拿到密码九个点的父级,抽象成九宫格后,根据数学方式,计算出每个点的坐标
      * @param driver
      * @param by
      * @param pwd
      */
    public static void geUnlock(AndroidDriver<AndroidElement> driver,By by,int[] pwd) {
         AndroidElement lockview=driver.findElement(by);
    
         int start_x=lockview.getLocation().getX();//起始点X
         int start_y=lockview.getLocation().getY();//起始点Y
    
         int w=lockview.getSize().getWidth();
         int h=lockview.getSize().getHeight();
    
         List<PointOption> corLists=new ArrayList<PointOption>();
         for(int i=0;i<3;i++) {//行
    
             for(int j=0;j<3;j++) {//列
                 int x_center=start_x+((2*j+1)*w)/6;
                 int y_center=start_y+((2*i+1)*h)/6;
                 corLists.add(PointOption.point(x_center, y_center));
             }
    
         }
    
         TouchAction action=new TouchAction(driver);
     //    action.press(PointOption.point(x/2, 8*y/10)).waitAction(WaitOptions.waitOptions(Duration.ofMillis(500))).moveTo(PointOption.point(x/2, 2*y/10)).release().perform();
         action.press(corLists.get(pwd[0])).waitAction(WaitOptions.waitOptions(Duration.ofMillis(300)));
    
         for(int i=1;i<pwd.length;i++){
             action.moveTo(corLists.get(pwd[i])).waitAction(WaitOptions.waitOptions(Duration.ofMillis(300)));
         }
         action.release().perform();
     }

    微信实战

    微信公众号:H5,使用Chrome Inspect调试定位元素

    调试准备:
    ①开启tbs调试:
    • 在微信任意聊天窗口输入debugtbs.qq.com,
    • 点击该链接进入到图一界面
    • 点击安装线上内核,等待自动安装完成
    • 再点击DebugX5,进入图二界面,勾选相关选项
    图片说明
    图片说明
    ②查看Android的webview视图版本:手机链接电脑后,手机打开微信的待测试的小程序,在电脑Chrome打开页面chrome://inspect/#devices查看Android的Chrome内核版本;点击inspect后,即弹出谷歌自带的H5控制台,可调试元素
    图片说明
    图片说明

代码实现:
①初始化driver:

/**
         * 微信公众号初始化driver
         * 与正常APP调试不同点:
         *     1.根据微信公众号x5内核内嵌的谷歌浏览器版本,指定Chrome driver的本地路径
         *     File chromedriver=new File("D:\\chromedownload\\chromedriver2.40\\chromedriver.exe");
         *     2.将Chromedriver执行路径添加至DesiredCapabilities参数中
         *     caps.setCapability(AndroidMobileCapabilityType.CHROMEDRIVER_EXECUTABLE, chromedriver.getAbsolutePath());
         *     3.建立Chrome与微信的链接
         *     ChromeOptions options=new ChromeOptions();
         *     options.setCapability("browserName", "");
         *     //指定Chrome连接的手机的进程
         *     options.setExperimentalOption("androidProcess", "com.tencent.mm:tools");
         *     caps.setCapability(ChromeOptions.CAPABILITY, options);
         * @param udid
         * @param appPackage
         * @param appActivity
         * @return
         * @throws Exception
         */
public static AndroidDriver<AndroidElement> initDriverGZH(String udid, String appPackage,String appActivity) throws Exception{
            DesiredCapabilities caps = new DesiredCapabilities();
            // 表示我们的设备名字,在安卓下这个参数必须有,但是值可以随便写
            caps.setCapability(MobileCapabilityType.DEVICE_NAME, "xxx");// “devicesName”
            // 表示appium服务的session过期时间,单位是秒,默认是60秒
            caps.setCapability(MobileCapabilityType.NEW_COMMAND_TIMEOUT, 600);
            // 表示在安装的时候不对应用进行重签名操作,因为有的应用在重签名之后就无法正常使用
            caps.setCapability(AndroidMobileCapabilityType.NO_SIGN, true);
            // 下面两项是用来使用appium自带的unicode输入法,来隐藏键盘并且支持中文输入
            caps.setCapability(AndroidMobileCapabilityType.UNICODE_KEYBOARD, true);
            caps.setCapability(AndroidMobileCapabilityType.RESET_KEYBOARD, true);
            caps.setCapability(MobileCapabilityType.UDID, udid);
            File chromedriver=new File("D:\\chromedownload\\chromedriver2.40\\chromedriver.exe");
            caps.setCapability(AndroidMobileCapabilityType.APP_PACKAGE, "com.tencent.mm");
            caps.setCapability(AndroidMobileCapabilityType.APP_ACTIVITY, "com.tencent.mm.ui.LauncherUI");
            caps.setCapability(MobileCapabiliyType.NO_RESET, true);
        //RECREATE_CHROME_DRIVER_SESSIONS:重建Chrome与手机 的链接
        caps.setCapability(AndroidMobileCapabilityType.RECREATE_CHROME_DRIVER_SESSIONS, true);
        caps.setCapability(AndroidMobileCapabilityType.CHROMEDRIVER_EXECUTABLE, chromedriver.getAbsolutePath());
        ChromeOptions options=new ChromeOptions();
        options.setCapability("browserName", "");
        options.setExperimentalOption("androidProcess", "com.tencent.mm:tools");
        caps.setCapability(ChromeOptions.CAPABILITY, options);
        AndroidDriver driver = new AndroidDriver(
                new URL("http://127.0.0.1:4723/wd/hub"), caps);
        return driver;
    }

②编写test:以“爱心筹”公众号为例

/**
     * 微信小程序测试方法:以爱心筹公众号为例
     * @throws Exception
     */
    @Test
    public void vchatAixinchou() throws Exception{

        driver.findElement(By.xpath("//*[@text='通讯录']/..")).click();
        driver.findElement(By.xpath("//*[@text='公众号']/..")).click();
        driver.findElement(MobileBy.AndroidUIAutomator("text(\"爱心筹\")")).click();
        driver.findElement(MobileBy.AndroidUIAutomator("text(\"我的筹款\")")).click();
        driver.findElement(MobileBy.xpath("//*[contains(@text,'我要提现')]")).click();

        Thread.sleep(5000);
        //获取所有的ContextHandle
        Set<String> contexts=driver.getContextHandles();
        //这里是用来打印你当前的context的,如果看不到tencent的webview,说明你的debug开的有问题
        for(String s:contexts){
            System.out.println(s);
        }
        //切换driver到公众号的context上
        driver.context("WEBVIEW_com.tencent.mm:tools");
        Thread.sleep(2000);
        driver.findElement(By.partialLinkText("提现")).click();
        driver.findElement(By.linkText("去添加")).click();
        driver.findElement(By.cssSelector(".addBank")).click();
        driver.findElement(By.id("cardno")).sendKeys("673635235623655");
        //切换driver到原生的context上
        driver.context("NATIVE_APP");
    }

微信小程序:使用UIAutomator1辅助定位元素

思路:使用UIAutomator辅助定位元素,与原生操作和实现一致。

  1. 初始化driver
    public static AndroidDriver initDriverXCX(String udid, String appPackage,String appActivity) throws Exception {
         DesiredCapabilities caps = new DesiredCapabilities();
         //设备名称,在android上没有用,值可以随便写
         caps.setCapability(MobileCapabilityType.DEVICE_NAME, "xxx");
         //平台名称,android或ios
         caps.setCapability(MobileCapabilityType.PLATFORM_NAME, "Android");
         //session超时时间设置
         caps.setCapability(MobileCapabilityType.NEW_COMMAND_TIMEOUT, 600);
         //真正的指定哪台设备执行测试,值就是adb devices看到的设备标识
         caps.setCapability(MobileCapabilityType.UDID, udid);
         //不重置应用数据
         caps.setCapability(MobileCapabilityType.NO_RESET, true);
         //caps.setCapability(MobileCapabilityType.APP, app.getAbsolutePath());
    //        caps.setCapability(AndroidMobileCapabilityType.APP_PACKAGE, "com.zhihu.android");
    //        caps.setCapability(AndroidMobileCapabilityType.APP_ACTIVITY,
    //                "com.zhihu.android.app.ui.activity.LauncherActivity");
         caps.setCapability(AndroidMobileCapabilityType.APP_PACKAGE, "com.tencent.mm");
         caps.setCapability(AndroidMobileCapabilityType.APP_ACTIVITY, "com.tencent.mm.ui.LauncherUI");
         //不重签名数据,因为很多app重签名后就不能用,有防篡改签名的措施
         caps.setCapability(AndroidMobileCapabilityType.NO_SIGN, true);
         //caps.setCapability(MobileCapabilityType.AUTOMATION_NAME, AutomationName.ANDROID_UIAUTOMATOR2);
         //使用appium的辅助输入法,支持中文和隐藏键盘
         caps.setCapability(AndroidMobileCapabilityType.UNICODE_KEYBOARD, true);
         //测试完成后,讲输入法重置回手机原有的输入法
         caps.setCapability(AndroidMobileCapabilityType.RESET_KEYBOARD, true);
         //自动授予各种权限
         caps.setCapability(AndroidMobileCapabilityType.AUTO_GRANT_PERMISSIONS, true);
         //caps.setCapability("autoLaunch", false);
         caps.setCapability(MobileCapabilityType.AUTOMATION_NAME, "uiautomator1");
         //AutomationName.APPIUM
         AndroidDriver driver = new AndroidDriver<AndroidElement>(new URL("http://127.0.0.1:4723/wd/hub"), caps);
         driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
         return driver;
     }
  2. testCase
@Test
    public void xcxTest() throws Exception {
        driver.findElement(By.xpath("//*[@text='发现']/..")).click();
        driver.findElement(MobileBy.AndroidUIAutomator("text(\"小程序\")")).click();
        driver.findElement(MobileBy.AndroidUIAutomator("text(\"腾讯课堂\")")).click();
        driver.findElement(MobileBy.AndroidUIAutomator("text(\"搜索老师、机构、课程\")")).sendKeys("码同学");;
        Thread.sleep(3000);
        //driver.findElement(MobileBy.AndroidUIAutomator("text(\"【码同学】全网干货zui多的Selenium/Appium自动化脚本实战训练营\")")).click();
        driver.findElement(MobileBy.AndroidUIAutomator("text(\"【码同学】全网干货zui多的Selenium/Appium自动化脚本实战训练营\")")).click();
        driver.findElement(MobileBy.AndroidUIAutomator("text(\"咨询\")")).click();
        driver.findElement(By.id("com.tencent.mm:id/aom")).sendKeys("这是测试");
    }

常见问题

1. Appium新版本不再支持ByName定位了怎么办

在使用appium1.5之后的版本时,你一定见过这个错误

org.openqa.selenium.InvalidSelectorException: Locator Strategy 'name' is not supported for this session

是否很心痛,曾经的定位神器居然ByName居然不再支持了,那我以前的脚本可怎么办,此时你去各种技术论坛或者群求助,会得到两种答案

  1. 换其他定位方式,比如用xpath代替

  2. 使用ByAByAccessibilityId代替,但实践证明这个方法并没有取代ByName

其中第一种是可取的,换其他定位方式,本文将交给大家一个不用换定位方式不用换之前脚本的方法来完成无缝升级appium版本的定位方式

一招修改源码解决问题根源,修改方法如下:

找到你的appium\node_modules\appium-android-driver\build\lib\driver.js 文件,只需要修改其中一行即可

this.locatorStrategies = ['xpath', 'id', 'class name', 'accessibility id', '-android uiautomator','name'];//注意原本是没有最后的name的,name就是咱们修改加上的

修改完成之后,保存,再次重启appium服务,就可以继续使用ByName定位啦,完美

参考文章

http://ask.testfan.cn/article/1121

参考视频

https://ke.qq.com/course/445742