Appium學(xué)習(xí)(二)--工具介紹、服務(wù)關(guān)鍵字、元素定位

一、使用Android工具查找包名和activity

以下有三種查看應(yīng)用包名package和入口activity名稱(chēng)的方法:
方法一:使用aapt //aapt是sdk自帶的一個(gè)工具,在sdk\builds-tools\目錄下
1.以ES文件瀏覽器為例,命令行中切換到aapt.exe目錄執(zhí)行:aapt dump badging E:\apk\es3.apk | findstr "package launchable-activity"
2.運(yùn)行后的結(jié)果中以下兩行分別是應(yīng)用包名package和入口activity名稱(chēng)
package: name=’com.estrongs.android.pop’
launchable-activity: name=’com.estrongs.android.pop.view.FileExplorerActivity’
注:在android sdk目錄搜索可以找到aapt.exe,如果沒(méi)有可以下載apktool。

查看當(dāng)前的activity:
adb shell dumpsys window windows|findstr “mCurrentFocus”


image.png

方法二:查看AndroidManifest.xml
1.使用apktool反編譯app:apktool.bat d es3.apk E:\apk\es
2.打開(kāi)AndroidManifest.xml
manifest節(jié)點(diǎn)的package屬性值是應(yīng)用的包名:<manifest package=”com.estrongs.android.pop”>
查找android.intent.action.MAIN和android.intent.category.LAUNCHER對(duì)應(yīng)的activity,該activity對(duì)應(yīng)的android:name屬性既是入口activity名稱(chēng),如下:
<activity android:theme=”@*android tyle/Theme.NoTitleBar” android:label=”@string/app_name” android:name=”com.estrongs.android.pop.view.FileExplorerActivity”>
<intent-filter>
<action android:name=”android.intent.action.MAIN” />
<category android:name=”android.intent.category.LAUNCHER” />
</intent-filter>
</activity>
android.intent.action.MAIN決定應(yīng)用程序最先啟動(dòng)的Activity
android.intent.category.LAUNCHER決定應(yīng)用程序是否顯示在程序列表里

方法三:通過(guò)hierarchyviewer.bat查看包名和activity
比如在設(shè)備上打開(kāi)一個(gè)計(jì)算器,然后進(jìn)入adt目錄的sdk\tools中打開(kāi)hierarchyviewer.bat
D:\adt-bundle-windows-x86_64-20140702\sdk\tools\hierarchyviewer.bat
就能看到包名和activity

image.png

注:也可以問(wèn)Android開(kāi)發(fā)包名和activity,執(zhí)行appium自動(dòng)化測(cè)試安裝app時(shí)在appium圖形化視圖中看日志也可以查看到包名和activity。

二、使用Android工具查找元素

進(jìn)入sdk\tools\uiautomatorview.bat 打開(kāi)這個(gè)工具


image.png

monitor.bat和hierarchyviewer.bat工具也能查看元素,只能看到元素的坐標(biāo),沒(méi)有uiautomatorview.bat好用。

三、擴(kuò)展學(xué)習(xí)adb命令

參考:http://www.lxweimin.com/p/fb4462919015

四、appium服務(wù)關(guān)鍵字

1.deviceName
手機(jī)設(shè)備的名字或者模擬器名字(雖然是必須項(xiàng),但在安卓平臺(tái)上這個(gè)值寫(xiě)啥都行,不影響腳本)
2.app
App(.ipa/.apk)安裝文件所在路徑,本地路徑或者遠(yuǎn)程路徑,或者是一個(gè)包含app安裝文件的.zip文件。Appium將先嘗試安裝應(yīng)用到設(shè)備上。注意,如果在安卓上你指定了應(yīng)用的appPackage和appActivity那么app這個(gè)參數(shù)就不是必須的。這個(gè)參數(shù)與browserName沖突,例如:/abs/path/to/my.apk or http://myapp.com/app.ipa
3.browserName
手機(jī)web自動(dòng)化的瀏覽器的名字。如果是做一個(gè)app的自動(dòng)化這個(gè)參數(shù)值為空(但是實(shí)際上這個(gè)參數(shù)直接不寫(xiě)就可以了)
例如:'Safari' for iOS and 'Chrome', 'Chromium', or 'Browser' for Android
4.newCommandTimeout
等待新命令超時(shí)時(shí)間,單位是秒,默認(rèn)是60秒。當(dāng)appium服務(wù)在指定的超時(shí)時(shí)間內(nèi)未接收到任何來(lái)自客戶(hù)端的指令,appium服務(wù)端與客戶(hù)端會(huì)主動(dòng)斷開(kāi)鏈接
一般可以設(shè)置時(shí)間為600秒,即10分鐘,這樣不影響自動(dòng)化在執(zhí)行過(guò)程中等待元素的加載。
5.autoLaunch
設(shè)置appiun啟動(dòng)后是否自動(dòng)安裝和啟動(dòng)app應(yīng)用。默認(rèn)值是true(當(dāng)這個(gè)值是true時(shí),代碼里則不能使用driver.launchApp方法)
6.udid
鏈接物理指定設(shè)備的唯一標(biāo)識(shí)(安卓上就是通過(guò)adb devices看到的設(shè)備名稱(chēng))
7.noReset
不重置應(yīng)用數(shù)據(jù),默認(rèn)是false
8.fullReset
(iOS) 刪除整個(gè)虛擬目錄,(Android) 通過(guò)卸載app來(lái)重置應(yīng)用默認(rèn)是false
9.appActivity
應(yīng)用的起始啟動(dòng)
10.appPackage
應(yīng)用的包名(當(dāng)以安裝模式執(zhí)行腳本的時(shí)候,appPackage和appActivity可以不寫(xiě))
11.appWaitActivity
啟動(dòng)后等待的activity
12.deviceReadyTimeout
等待設(shè)備連接正常的超時(shí)時(shí)間
13.unicodeKeyboard
使用Unicode input輸入法, true
14.resetKeyboard
在運(yùn)行了unicodeKeyboard完成測(cè)試后將輸入法重置為原有狀態(tài),如果單獨(dú)使用該參數(shù)將被忽略,true(該參數(shù)好像沒(méi)用,測(cè)試前需要把Android的輸入法改成appium Android input manager for unicode,測(cè)試時(shí)才可以輸入中文。如果測(cè)試前沒(méi)有修改為這個(gè)輸入法,測(cè)試時(shí)中文輸入會(huì)失敗)
15.noSign
在uiautomator模式下跳過(guò)檢查和應(yīng)用的重簽名, true

在Androidsetting方法中會(huì)用到上面講到的關(guān)鍵字,代碼如下:

public void AndroidSettings() throws MalformedURLException {
        //獲取當(dāng)前根目錄下的文件,當(dāng)前根目錄就是D:\Springboot\AppiumTest
        File classpathRoot = new File(System.getProperty("user.dir"));
        //獲取apps目錄下的文件
        File appDir = new File(classpathRoot, "/apps");
        //需要提前把該apk放到apps文件夾下
        File app = new File(appDir, "meituan-9.12.801.apk");

        //創(chuàng)建設(shè)備屬性對(duì)象
        DesiredCapabilities capabilities = new DesiredCapabilities();
        //設(shè)置設(shè)備系統(tǒng)為Android
        capabilities.setCapability("platformName", "Android");
        //設(shè)置設(shè)備名稱(chēng)為edaed87d,可以通過(guò)usb連接手機(jī),在cmd中輸入命令,adb devices 看到設(shè)備名稱(chēng)
        // (這個(gè)名稱(chēng)寫(xiě)什么都行,通常情況下測(cè)試時(shí)只會(huì)連一臺(tái)設(shè)備,appium會(huì)直接去連,如果有多臺(tái)用udid參數(shù)指定設(shè)備號(hào))
        capabilities.setCapability("deviceName","edaed87d");
        //udid指定設(shè)備信息,如果有多臺(tái)設(shè)備這個(gè)值會(huì)有用
//        capabilities.setCapability("udid","edaed87d");
        //設(shè)置設(shè)備安卓系統(tǒng),可以在手機(jī)的設(shè)置中查看系統(tǒng)號(hào)
        capabilities.setCapability("platformVersion", "6.0.1");

        //獲取app的絕對(duì)路徑
//        capabilities.setCapability("app", app.getAbsolutePath());
        //設(shè)置app的包名,在cmd中進(jìn)入aapt.exe的目錄輸入命令aapt dump badging E:\apk\es3.apk | findstr "package launchable-activity" 查看包名和activity
        capabilities.setCapability("appPackage", "com.sankuai.meituan");
        //設(shè)置app的入口activity
        capabilities.setCapability("appActivity", "com.meituan.android.pt.homepage.activity.MainActivity");
        //設(shè)置每次運(yùn)行不清空app的數(shù)據(jù)
        capabilities.setCapability("noReset","true");
//        //設(shè)置每次運(yùn)行不重簽名app
//        capabilities.setCapability("noSign","true");
        //設(shè)置超時(shí)時(shí)間,超過(guò)10分鐘,客戶(hù)端與服務(wù)器斷開(kāi)鏈接
//        capabilities.setCapability("newCommandTimeout",600);
        //在Android4.2版本以下需要指定這個(gè)Selendroid
//        capabilities.setCapability("automationName","Selendroid");


        //使用Unicode編碼方式發(fā)送字符串
        capabilities.setCapability("unicodeKeyboard","True");
        //恢復(fù)鍵盤(pán)輸入法,也可以說(shuō)是隱藏鍵盤(pán)(要輸入中文,需要先把手機(jī)上的輸入法調(diào)整成appium android input manager for unicode)
        //如果需要把鍵盤(pán)調(diào)出來(lái)只能手工的去改輸入法
        capabilities.setCapability("resetKeyboard","True");

        //設(shè)置測(cè)試機(jī)與idea的通訊協(xié)議
        driver = new AndroidDriver<WebElement>(new URL("http://127.0.0.1:4723/wd/hub"), capabilities);
        driver.manage().timeouts().implicitlyWait(15, TimeUnit.SECONDS);
        System.out.println("App is launched!");
}

五、定位

5.1 Xpath定位:
Xpath定位中都是用classname定位的。

        WebElement element = driver.findElement(By.xpath("http://android.support.v7.widget.RecyclerView/child::android.view.ViewGroup[1]/android.widget.FrameLayout"));
        element.click();
image.png

要定位到紅框里的元素,首先找到它的父級(jí)目錄,父級(jí)目錄的classname是android.support.v7.widget.RecyclerView
紅框里的元素的classname是android.view.ViewGroup,他是第1個(gè)元素,所以
寫(xiě)android.view.ViewGroup[1],如果是最后一個(gè)就可以寫(xiě)[last()],如果要定位倒數(shù)第2個(gè)就寫(xiě)[last()-1]


image.png

android.view.ViewGroup[1]下面還有元素,我們要定位到以上圖中的紅框的元素,找到該元素的classname是android.widget.FrameLayout

該xpath中用到一個(gè)child:: 就是存在一個(gè)父級(jí)和子級(jí)的關(guān)系:
driver.findElement(By.xpath("http://android.support.v7.widget.RecyclerView/child::android.view.ViewGroup[1]/android.widget.FrameLayout"));

如果父級(jí)跟目錄下有多個(gè)級(jí)別元素,可以通過(guò)descendant:: 定位子孫元素:


image.png

通過(guò)父級(jí)去找:

        driver.findElement(By.xpath("http://android.widget.FrameLayout{contains(@resource-id,'tv.danmaku.bili:id/cover_layout')}/parent::android.view.ViewGroup/fowlling:sibling::android.view.ViewGroup[2]/android.widget.FrameLayout/android.widget.ImageView")).click();

通過(guò)parent找到上一級(jí),然后再找同一目錄下的其他元素。

一般通過(guò)定位classname和id就能定位到元素,Xpath會(huì)有點(diǎn)繁瑣,用findElementbyId和findElementbyClassname實(shí)現(xiàn)上面的定位
代碼如下:

        //找到第一個(gè)元素點(diǎn)擊,默認(rèn)是第一個(gè)元素
//        driver.findElement(By.id("tv.danmaku.bili:id/cover")).click();
        //找到第二個(gè)元素點(diǎn)擊,因?yàn)閕d都一樣,所有通過(guò)list來(lái)接收,通過(guò)elements.get(1).click();點(diǎn)擊第二個(gè)元素
        List<AndroidElement> elements = driver.findElementsById("tv.danmaku.bili:id/cover");
        elements.get(1).click();
        //點(diǎn)擊屏幕
        driver.findElementById("tv.danmaku.bili:id/video_view_biliplayer").click();
        //點(diǎn)擊右上角返回鍵
        driver.findElementByClassName("android.widget.ImageButton").click();

以上代碼要定位到第二個(gè)視頻,打開(kāi)后再返回


image.png

xpath內(nèi)容補(bǔ)充:
一、XPath

from lxml import etree

html = etree.parse('html源代碼',etree.HTMLPaser())

1.節(jié)點(diǎn)的獲取

a.html.xpath('//*') #匹配HTML中的所有節(jié)點(diǎn)

b.html.xapth('//li') #匹配所有的li節(jié)點(diǎn)

c.// 獲取所有的子孫節(jié)點(diǎn) ‘/’ 獲取子節(jié)點(diǎn)(區(qū)別好 '//' 與 '/')

d.html.xapth('//li[@class='item-0']') #根據(jù)屬性匹配

e.html.xapth('//li[contains(@class,'li')]) #屬性多值匹配 contains()方法,第一個(gè)參數(shù)傳入屬性名稱(chēng),第二個(gè)參數(shù)傳入屬性值,只要此屬性包含所傳入的屬性值就可以完成匹配

f.多屬性匹配 .html.xapth('//li[contains(@class,'li') and @name='item'])

g.按順序選擇 html.xapth('//li[last()]') 最后一個(gè)li節(jié)點(diǎn)

html.xapth('//li[position()<3]') 位置小于3的li節(jié)點(diǎn)

html.xapth('//li[1]') 選擇第一個(gè)li節(jié)點(diǎn)

h.節(jié)點(diǎn)軸選擇 html.xapth('//li/child::') 直接子節(jié)點(diǎn)

html.xapth('//li/ancestor::') 所有祖先節(jié)點(diǎn)

html.xapth('//li'/attribute::) 獲取所有的屬性值

html.xapth('//li/decendant::') 獲取所有的子孫節(jié)點(diǎn)

2.屬性,文本獲取

(1).文本獲取

html.xapth('//li/text()')

(2).屬性獲取

html.xapth('//li/@class') #獲取li標(biāo)簽的class的屬性值

5.2 滑動(dòng)操作

image.png

Appium處理滑動(dòng)方法是swipe

滑動(dòng)API:Swipe(int start x,int start y,int end x,int y,duration)
解釋?zhuān)?br> int start x-開(kāi)始滑動(dòng)的x坐標(biāo);
int start y -開(kāi)始滑動(dòng)的y坐標(biāo) ;
int end x -結(jié)束點(diǎn)x坐標(biāo);
int end y -結(jié)束點(diǎn)y坐標(biāo);
duration 滑動(dòng)時(shí)間(默認(rèn)5毫秒)。

屏幕左上角為起點(diǎn),坐標(biāo)為(0,0),起點(diǎn)往右為Y軸,起點(diǎn)以下為X軸
微信來(lái)說(shuō),登錄按鈕起點(diǎn)和終點(diǎn)坐標(biāo)分別為(63,1716)和(432,1860)


image.png

封裝的代碼:

package com.yin.Appiumdemo;

import io.appium.java_client.AppiumDriver;
import org.openqa.selenium.WebElement;

public class SwipeCenter {

    /*
    方法參數(shù)介紹:
    driver(就是把a(bǔ)ppiumdriver對(duì)象傳進(jìn)來(lái))
    during(這里是填寫(xiě)毫秒數(shù),這里的 毫秒數(shù)越小 滑動(dòng)的速度越快~ 一般設(shè)定在500~1000,如果你想快速滑動(dòng) 那就可以設(shè)置的更加小)
    num(是只滑動(dòng)的次數(shù),如相冊(cè)多張圖片翻頁(yè)測(cè)試什么的滑動(dòng)或者滑動(dòng)到列表底部。就直接輸入次數(shù)就行了)
     */

    //上滑 swipeToUp
    public static void swipeToUp(AppiumDriver driver,int during,int num) throws InterruptedException {
        //先獲取屏幕的分辨率
        int width = driver.manage().window().getSize().width;
        int height = driver.manage().window().getSize().height;
        Thread.sleep(2000);
        for (int i=0;i<num;i++){
            driver.swipe(width/2,height*3/4,width/2,height/4,during);
            Thread.sleep(2000);
        }

    }
    //下拉 swipeToDown
    public static void swipeToDown(AppiumDriver<WebElement> driver,int during,int num) throws InterruptedException {
        //先獲取屏幕的分辨率
        int width = driver.manage().window().getSize().width;
        int height = driver.manage().window().getSize().height;
        //等待2秒
        Thread.sleep(2000);
        for (int i=0;i<num;i++){
            driver.swipe(width/2,height/4,width/2,height*3/4,during);
            //等待2秒
            Thread.sleep(2000);
        }

    }
    //向左滑動(dòng) swipeToLeft
    public static void swipeToLeft(AppiumDriver<WebElement> driver,int during,int num) throws InterruptedException {
        //先獲取屏幕的分辨率
        int width = driver.manage().window().getSize().width;
        int height = driver.manage().window().getSize().height;
        //等待2秒
        Thread.sleep(2000);
        for (int i=0;i<num;i++){
            driver.swipe(width*3/4,height/2,width/4,height/2,during);
            //等待2秒查看界面變動(dòng)
            Thread.sleep(2000);
        }

    }
    //向右滑動(dòng) swipeToRight
    public static void swipeToRight(AppiumDriver<WebElement> driver,int during,int num) throws InterruptedException {
        //先獲取屏幕的分辨率
        int width = driver.manage().window().getSize().width;
        int height = driver.manage().window().getSize().height;
        //等待2秒
        Thread.sleep(2000);
        for (int i=0;i<num;i++){
            driver.swipe(width/4,height/2,width*3/4,height/2,during);
            //等待2秒查看界面變動(dòng)
            Thread.sleep(2000);
        }

    }

}

調(diào)用的代碼:

    @Test(description = "滑動(dòng)操作")
    public void testswip() throws InterruptedException {

        //調(diào)取SwipeCenter類(lèi)中的方法,實(shí)現(xiàn)向上、向下、向左、向右滑動(dòng)
        //向上滑動(dòng)
        SwipeCenter.swipeToUp(driver,500,2);
        //向下滑動(dòng)
        SwipeCenter.swipeToDown(driver,500,1);
        //向左滑動(dòng)
        SwipeCenter.swipeToLeft(driver,500,1);
        //向右滑動(dòng)
        SwipeCenter.swipeToRight(driver,500,1);
}

還可以利用try、catch,先去找元素,找不到滑動(dòng)頁(yè)面再找

        WebElement element = null;
        try {
            //先去找元素
            element = driver.findElementByName("百萬(wàn)播放");
        }catch(Exception e){
            e.printStackTrace();
            //找不到向左滑動(dòng)
            SwipeCenter.swipeToLeft(driver,500,1);
            element = driver.findElementByName("百萬(wàn)播放");
            //找到后再點(diǎn)擊click
            element.click();
        }

5.3 location坐標(biāo)定位

    @Test(description = "location坐標(biāo)定位")
    public void testlocation() throws InterruptedException {
        //tap模擬手指點(diǎn)擊
        //先等待2秒,等待元素出來(lái)
        Thread.sleep(2000);
        //使用tap方法,第一個(gè)參數(shù)是模擬一個(gè)手指去點(diǎn),第二個(gè)參數(shù)是X點(diǎn),第三個(gè)是y點(diǎn),第四個(gè)是持續(xù)點(diǎn)擊0.5秒
        //通過(guò)Ui Automator viewer定位看到坐標(biāo)點(diǎn)是[846,362][1080,482],取X值在846~1080之間,取Y值在362~482之間
        driver.tap(1,900,420,500);
        Thread.sleep(2000);
        System.out.println("坐標(biāo)定位成功");
    }
image.png

5.4 混合應(yīng)用定位獲取webview頁(yè)面的元素
混合應(yīng)用就是在app中嵌套了H5的頁(yè)面,H5頁(yè)面的元素是webview的。
步驟都在代碼中有些注釋?zhuān)?/p>

    @Test(description = "獲取webview頁(yè)面元素")
    public void testwebview(){

        //獲取driver中的handles,利用foreach循環(huán)查找如果是webview的頁(yè)面就進(jìn)入webview頁(yè)面,轉(zhuǎn)換成html在瀏覽器中打開(kāi)再去定位到某個(gè)元素
        //定位成功之后再轉(zhuǎn)回到NATIVE_APP 頁(yè)面
        Set<String> contextset = driver.getContextHandles();
        for (String context : contextset ){
            System.out.println("頁(yè)面上context是:"+context);


            if (context.toLowerCase().contains("webview")){
                driver.context(context);//進(jìn)入webview頁(yè)面
                System.out.println("進(jìn)入成功");
                break;
            }
        }
        //通過(guò)封裝的方法把webview源碼轉(zhuǎn)換成html,然后在瀏覽器中打開(kāi)去定位到元素
        //封裝的方法還沒(méi)有實(shí)現(xiàn),如果找到webview頁(yè)面,獲取到源碼使用chrome-development tool 來(lái)定位元素
        //使用步驟參考:https://blog.csdn.net/wanglin_lin/article/details/77100028
//        PageResourceGetter.initialize("uers/dir/prg.html",driver.getPageSource());
        //定位到元素
       driver.findElement(By.id("username")).sendKeys("appium.test@gmail.com");
       //再回到原生app
        driver.switchTo().window("NATIVE_APP");

    }

參考地址:https://blog.csdn.net/wanglin_lin/article/details/77100028
一般情況下通過(guò)Ui Automator viewer也可以看到webview中的控件,如果看不到就把driver.getPageSource()的內(nèi)容打印出來(lái),然后分析里面的控件再定位也可以。

appium的api

image.png

手機(jī)坐標(biāo)、首頁(yè)導(dǎo)航滑動(dòng)前面已經(jīng)講過(guò),省略。

5.5 截屏操作
先創(chuàng)建一個(gè)截屏類(lèi):

package com.yin.Appiumdemo;
/*
截圖操作
 */

import io.appium.java_client.AppiumDriver;
import io.appium.java_client.android.AndroidDriver;
import org.apache.commons.io.FileUtils;
import org.openqa.selenium.OutputType;

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class Screenshot {
    public static void Screenshot(AppiumDriver driver, String ScreenName) throws IOException {
        //設(shè)置時(shí)間格式,截圖的文件要加上時(shí)間戳這樣不會(huì)重復(fù)
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
        //生成時(shí)間戳
        String dataString = simpleDateFormat.format(new Date());
        //設(shè)置存放圖片目錄
        String dir_name = System.getProperty("user.dir")+"\\異常圖片";
        System.out.println("異常圖片目錄:"+dir_name);
        //防止出現(xiàn)圖片目錄被刪除,所以先判斷目錄是否存在,如果不存在就新建一個(gè)目錄
        if (!(new File(dir_name).isDirectory())){
            //如果不存在就創(chuàng)建一個(gè)目錄
            new File(dir_name).mkdir();
        }
        //調(diào)用方法獲取頁(yè)面截屏
        File screenfile = driver.getScreenshotAs(OutputType.FILE);
        //復(fù)制圖片到指定目錄,放到dir_name目錄下,命名是時(shí)間戳+測(cè)試用例名稱(chēng)
        FileUtils.copyFile(screenfile,new File(dir_name+"\\"+dataString+ScreenName+".jpg"));
        //打印圖片名稱(chēng),
        System.out.println("異常圖片名稱(chēng):"+dir_name+"\\"+dataString+ScreenName+".jpg");

    }
}

在測(cè)試方法中調(diào)用:

    @Test(description = "截屏")
    public void testscreenshot() throws InterruptedException, IOException {
        //正常請(qǐng)求的截圖
        Thread.sleep(1000);
        Screenshot.Screenshot(driver,"test001");
        Thread.sleep(1000);

        //異常的截圖放到catch中
        try{
            driver.findElementByName("百萬(wàn)播放");
        }catch (Exception e){
            Screenshot.Screenshot(driver,"test001");
        }


    }

生成目錄時(shí)可能會(huì)遇到目錄出現(xiàn)亂碼的情況,進(jìn)入idea的設(shè)置中找到File Encoding 都設(shè)置成UTF-8,然后再執(zhí)行測(cè)試類(lèi)就可以了


image.png

5.6 元素之間的滑動(dòng)

image.png

image.png

image.png
image.png

控件的滑動(dòng)可以用兩種方式實(shí)現(xiàn),第一種是TouchAction,第二種是swipe
封裝的方法如下:

package com.yin.Appiumdemo;

import io.appium.java_client.AppiumDriver;
import io.appium.java_client.TouchAction;
import org.openqa.selenium.WebElement;

/*
封裝方法,實(shí)現(xiàn)控件的滑動(dòng)
 */
public class ElementHua {
    //利用TouchAction 拖動(dòng)控件
    public static void Element_HuaWithTouchAction(AppiumDriver driver,WebElement element, String swipeway) throws InterruptedException {
        //先獲取控件的起點(diǎn)x坐標(biāo)值
        int xStartPoint = element.getLocation().getX();
        //獲取控件的寬度,計(jì)算出控件的x終點(diǎn)坐標(biāo)值
        int xEndPoint = xStartPoint+element.getSize().getWidth();
        //獲取控件的Y起點(diǎn)坐標(biāo)值
        int yStartPoint = element.getLocation().getY();
        System.out.println("X起點(diǎn)坐標(biāo)是"+xStartPoint);
        System.out.println("X終點(diǎn)坐標(biāo)是"+xEndPoint);
        System.out.println("Y起點(diǎn)坐標(biāo)是"+yStartPoint);

        //利用TouchAction類(lèi)實(shí)現(xiàn)拖動(dòng)
        TouchAction action = new TouchAction(driver);

        if (swipeway.equals("左滑")){
            Thread.sleep(1000);
            //可以根據(jù)控件的寬度調(diào)整滑動(dòng)多寬,可以調(diào)整20為30、40等等,以下方法類(lèi)似
            action.press(xEndPoint-20,yStartPoint+20).waitAction(1000).moveTo(xStartPoint,yStartPoint+20).release().perform();
            Thread.sleep(1000);

        }
        if (swipeway.equals("右滑")){
            Thread.sleep(1000);
            action.press(xStartPoint+20,yStartPoint+20).waitAction(1000).moveTo(xEndPoint,yStartPoint+20).release().perform();
            Thread.sleep(1000);
        }

    }
    //利用滑動(dòng) 滑動(dòng)控件
    public static void Element_HuaWithSwipe(AppiumDriver driver,WebElement element, String swipeway) throws InterruptedException {
        //先獲取控件的起點(diǎn)x坐標(biāo)值
        int xStartPoint = element.getLocation().getX();
        //獲取控件的寬度,計(jì)算出控件的x終點(diǎn)坐標(biāo)值
        int xEndPoint = xStartPoint+element.getSize().getWidth();
        //獲取控件的Y起點(diǎn)坐標(biāo)值
        int yStartPoint = element.getLocation().getY();
        System.out.println("X起點(diǎn)坐標(biāo)是"+xStartPoint);
        System.out.println("X終點(diǎn)坐標(biāo)是"+xEndPoint);
        System.out.println("Y起點(diǎn)坐標(biāo)是"+yStartPoint);


        if (swipeway.equals("左滑")){
            Thread.sleep(1000);
            driver.swipe(xEndPoint-20,yStartPoint+20,xStartPoint+10,yStartPoint+20,500);
            Thread.sleep(1000);

        }
        if (swipeway.equals("右滑")){
            Thread.sleep(1000);
            driver.swipe(xStartPoint+10,yStartPoint+20,xEndPoint-20,yStartPoint+20,500);
            Thread.sleep(1000);
        }

    }
}

調(diào)用的方法是:

    @Test(description = "控件滑動(dòng)")
    public void testactionswipe() throws InterruptedException {
        //調(diào)用封裝的方法實(shí)現(xiàn)控件滑動(dòng)

        driver.findElementByName("追番").click();
        driver.findElementByName("時(shí)間表").click();
        List<WebElement> elements = driver.findElementsById("tv.danmaku.bili:id/date_item");
        WebElement element = elements.get(2);

        ElementHua.Element_HuaWithTouchAction(driver,element,"左滑");
        ElementHua.Element_HuaWithTouchAction(driver,element,"右滑");

        ElementHua.Element_HuaWithSwipe(driver,element,"左滑");
        ElementHua.Element_HuaWithSwipe(driver,element,"右滑");
    }

5.7 控件點(diǎn)擊操作
很簡(jiǎn)單,就用click()方法

image.png

控件的輸入
用到sendkeys()

image.png

    @Test(description = "控件的輸入")
    public void testsendkeys() throws InterruptedException {
        Thread.sleep(1000);
        driver.findElementById("tv.danmaku.bili:id/expand_search").click();
        Thread.sleep(1000);
        driver.findElementById("tv.danmaku.bili:id/search_src_text").sendKeys("test");
        Thread.sleep(1000);

    }

5.8 控件長(zhǎng)按

image.png

    @Test(description = "控件的長(zhǎng)按")
    public void testlongpress(){
        //獲取控件的X、Y坐標(biāo)點(diǎn),通過(guò)坐標(biāo)點(diǎn)長(zhǎng)按

        WebElement element = driver.findElementByName("追番");
        int X = element.getLocation().getX();
        int Y = element.getLocation().getY();

        TouchAction action = new TouchAction(driver);
        //通過(guò)坐標(biāo)點(diǎn)長(zhǎng)按
        action.longPress(X,Y).perform();
        //通過(guò)定位到元素長(zhǎng)按
        action.longPress(driver.findElementByName("時(shí)間表")).perform();
    }

5.9 控件的點(diǎn)擊
TouchAction action = new TouchAction(driver);
//通過(guò)坐標(biāo)點(diǎn)點(diǎn)擊控件,
action.tap(X,Y).release().perform();
//通過(guò)輸入控件的element點(diǎn)擊控件
action.tap(element).release().perform();

tap比click點(diǎn)擊準(zhǔn)確,會(huì)點(diǎn)擊控件的中間位置,click會(huì)存在點(diǎn)擊不準(zhǔn)確的情況。

5.10 Appium調(diào)起手機(jī)端chrome app瀏覽器
appium測(cè)試手機(jī)web的方法。
請(qǐng)參考http://www.lxweimin.com/p/b46d3687fcfc

5.11 CSS定位
適用與webview的頁(yè)面。
基礎(chǔ)表達(dá)式部分:

image.png

image.png

高級(jí)表達(dá)式部分:


image.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • ¥開(kāi)啟¥ 【iAPP實(shí)現(xiàn)進(jìn)入界面執(zhí)行逐一顯】 〖2017-08-25 15:22:14〗 《//首先開(kāi)一個(gè)線(xiàn)程,因...
    小菜c閱讀 6,510評(píng)論 0 17
  • Swift1> Swift和OC的區(qū)別1.1> Swift沒(méi)有地址/指針的概念1.2> 泛型1.3> 類(lèi)型嚴(yán)謹(jǐn) 對(duì)...
    cosWriter閱讀 11,136評(píng)論 1 32
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫(kù)、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,223評(píng)論 4 61
  • 莎士比亞:上大學(xué)還是不上大學(xué),這是一個(gè)值得思考的問(wèn)題。 蘇軾:月有陰晴圓缺,學(xué)有大小之分,此事古難全,但愿人長(zhǎng)久,...
    海紅果閱讀 221評(píng)論 0 4
  • 我抬筆將冷暖世態(tài)隔絕 究竟抵不過(guò) 所鐘情之人贈(zèng)我涼薄 早春暮春 酒暖花深 酒自飄香 花自飄落 千千心結(jié) 付與誰(shuí)知 ...
    曾經(jīng)美得像花兒閱讀 492評(píng)論 0 1