一、使用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”
方法二:查看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
注:也可以問(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è)工具
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();
要定位到紅框里的元素,首先找到它的父級(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]
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:: 定位子孫元素:
通過(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)后再返回
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)操作
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)
封裝的代碼:
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)定位成功");
}
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
手機(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)就可以了
5.6 元素之間的滑動(dòng)
控件的滑動(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()方法
控件的輸入
用到sendkeys()
@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)按
@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á)式部分:
高級(jí)表達(dá)式部分: