Appium系列|ID定位方式
自動化可以簡單概括為三個步驟:
-
控制元件定位
-
控制元件操作
-
校驗點編寫
我們先來介紹下控制元件定位。Appium提供了多種定位方式,最常見使用的是ID這種定位方式,如果控制元件有ID儘量使用ID來進行定位,因為有時候控制元件佈局變化了,只要 ID不發生變化就有可能定位方式不需要修改。
那怎麼來檢視控制元件的ID呢? Android SDK有提供一個工具可以用來檢視控制元件的詳細資訊,可以藉助這個工具來進行資訊的提取,這個工具是uiautomatorviewer,可以在終端執行uiautomatorviewer就可以開啟這個工具了,開啟後如下所示:
這時候可以在手機或者模擬器上開啟要定位控制元件的應用所屬的介面,然後點選上圖的選單欄的第二個按鈕,這樣這個工具就可以將當地介面的快照放在上圖視窗的左側,然後滑鼠去點選需要 檢視的控制元件,就會自動在視窗右側展示這個控制元件的詳細資訊,具體如下圖所示:
如上圖所示,加入要獲取首頁底部的釋出按鈕,可以通過uiautomatoriviewer檢視到該控制元件是有ID的,如右側視窗所示ID為:"net.oschina.app:id/nav_item_tweet_pub",ID獲取到了就可以通過Appium提供的定位方式進行控制元件定位了。可以在測試工程新建一個包如appium.chapter2要來存放第二章的程式碼,具體程式碼如下所示:
package appium.chapter2; import io.appium.java_client.AppiumDriver; import io.appium.java_client.android.AndroidDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.remote.DesiredCapabilities; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import java.io.File; import java.net.URL; public class IDTest { private AppiumDriver<WebElement> driver; @BeforeMethod public void setUp() throws Exception { //構造被測試應用的路徑 File app = new File(System.getProperty("user.dir"), "AUT/osc.apk"); //例項化DesiredCapabilities DesiredCapabilities capabilities = new DesiredCapabilities(); //deviceName的值可以任意指定 capabilities.setCapability("deviceName","My Device"); //設定被測應用的絕對路徑 capabilities.setCapability("app", app.getAbsolutePath()); capabilities.setCapability("appPackage","net.oschina.app"); //設定啟動類的資訊,這個資訊可以通過aapt dump bading apkname來獲得 capabilities.setCapability("appActivity", ".AppStart"); //初始化AppiumDriver driver = new AndroidDriver<WebElement>(new URL("http://127.0.0.1:4723/wd/hub"), capabilities); } @Test public void testName() throws Exception { //等待控制元件出現,後續再介紹智慧等待的方法 Thread.sleep(3000); //通過driver.findElementById方法可以將uiatuomatorviewer獲取到的id拿來進行定位 WebElement publishBtn = driver.findElementById("net.oschina.app:id/nav_item_tweet_pub"); //對這個控制元件進行點選操作 publishBtn.click(); } @AfterMethod public void tearDown() throws Exception { driver.quit(); } }
其實每個測試指令碼的setUp和tearDown都是一樣的,不一樣的是具體的測試方法裡的實現,這裡通過driver提供的findElementById來進行ID定位,然後將uiautomatorviewer獲得的id作為引數值傳遞給這個方法就能定位到這個控制元件了,後面要介紹到的其他定位方式也是一樣的步驟,首先通過uiautomatorviewer獲取到控制元件的屬性值,然後通過這個屬性值去呼叫Appium對應的定位方式的方法進行控制元件定位。
每一種定位方式都有兩種等價的寫法,如上面的按ID來定位的方式還可以寫成這樣:
WebElement publishBtn = driver.findElement(By.id("net.oschina.app:id/nav_item_tweet_pub"));
這時候可以啟動Appium Server,然後選擇該測試指令碼滑鼠右鍵選擇“Run IDTest”,執行下這個指令碼,可以觀察到手機或者模擬器上開源中國這個應用被啟動起來,然後底部的釋出按鈕通過指令碼觸發了點選。
在實際專案中經常會碰到同一個頁面相同的ID有多個的情況,這時候怎麼去進行定位呢?
現在我們還是以開源中國這個應用為例子,比如首頁的資訊列表裡的資訊標題,可以通過uiauomatorviewer觀察,ID都是相同的,如下截圖所示:
可以觀察到上圖擷取處理的幾個部分的id都是一樣的。
這時候假如要定位到資訊列表裡第二行的資訊標題可以通過如下方式進行定位,也就是id加index來進行定位,具體程式碼如下所示:
package appium.chapter2;
import io.appium.java_client.AppiumDriver;
import io.appium.java_client.android.AndroidDriver;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import java.io.File;
import java.net.URL;
public class SameIDTest {
private AppiumDriver<WebElement> driver;
@BeforeMethod
public void setUp() throws Exception {
//構造被測試應用的路徑
File app = new File(System.getProperty("user.dir"), "AUT/osc.apk");
//例項化DesiredCapabilities
DesiredCapabilities capabilities = new DesiredCapabilities();
//deviceName的值可以任意指定
capabilities.setCapability("deviceName","My Device");
//設定被測應用的絕對路徑
capabilities.setCapability("app", app.getAbsolutePath());
capabilities.setCapability("appPackage","net.oschina.app");
//設定啟動類的資訊,這個資訊可以通過aapt dump bading apkname來獲得
capabilities.setCapability("appActivity", ".AppStart");
//初始化AppiumDriver
driver = new AndroidDriver<WebElement>(new URL("http://127.0.0.1:4723/wd/hub"), capabilities);
}
@Test
public void testName() throws Exception {
//等待控制元件出現,後續再介紹只能等待的方法
Thread.sleep(3000);
//因為首頁的標題ID也和列表裡資訊標題的id是一樣的,因此要取第二行的資訊標題相當於取第3行的標題,因為首頁頂部的標題相當於第一行
//index是從0開始的,所以第三行的index就是2
//Appium提供driver.findElements方法來獲取相同屬性的控制元件集,然後在通過index來獲取第幾個
WebElement title3 = driver.findElements(By.id("net.oschina.app:id/tv_title")).get(2);
//將資訊標題打印出來
System.out.println(title3.getText().toString());
}
@AfterMethod
public void tearDown() throws Exception {
driver.quit();
}
}
執行結果如下圖所示: