昨天介紹過Appium Inspector的使用方式後,今天再來開始寫Appium語法會快速很多。寫Appium可以用很多語法,因我們是Android開發者,所以我這邊選擇JVM的版本來開發,語法用Java或是Kotlin都可以。我選擇的開發工具是一樣是由Jetbrains開發的IDE IntelliJ,不使用Android Studio的原因是因為我不是開發Android App,用Android Studio來開發會變成是小題大作,專案內的SDK都不會用到。而且IntelliJ的開發介面和習慣跟Andoid Studio差不多,大家應該可以很快上手。
我們在IntelliJ裡建立一個新的maven專案,然後在src/java/test/資料夾中新增一個UnitTest.kt的檔案。
另外在pom檔裡面要加入下面的dependecies,第一個dependency就是appium,第三及第四個的dependency是看JUnit的部份要選擇用kotlin還是java開發,擇一即可。
<dependencies>
<!-- appium -->
<dependency>
<groupId>com.github.appium</groupId>
<artifactId>java-client</artifactId>
<version>7.0.0</version>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib-jdk8</artifactId>
<version>${kotlin.version}</version>
</dependency>
<!-- kotlin version -->
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-test-junit</artifactId>
<version>${kotlin.version}</version>
<scope>test</scope>
</dependency>
<!-- java version -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
當denpendency都設置完成後,我們就可以開始來寫Appium test的語法了。還記得昨天講的inspector launch application的參數嗎?在Appium裡被稱為Capability,回去看看昨天講的inspector裡的參數是不是也寫上capability。我們要動態讓Appium呼叫APK起來測試也是透過capability的設置,這裡只要把昨天提到的capabilities依序填入即可。
我們要回傳的物件是AndroidDriver,第一個參數是Appium Server的URL物件,如果我們不改Appium Server的預設URL那就是http://127.0.0.1:4723/wd/hub ,第二個參數需傳入用DesiredCapabilities()包裝起來的capabilities。這個AndroidDriver要做的事就是告訴Appium Server開啟capabilities的設定。
AndroidDriver(URL("http://127.0.0.1:4723/wd/hub"), capabilities)
fun getAppiumDriver(): AndroidDriver<AndroidElement> {
val capabilities = DesiredCapabilities().apply {
setCapability(MobileCapabilityType.PLATFORM_NAME, MobilePlatform.ANDROID)
setCapability(MobileCapabilityType.DEVICE_NAME, "Pixel2")
setCapability(AndroidMobileCapabilityType.AUTO_GRANT_PERMISSIONS, true)
setCapability(MobileCapabilityType.AUTOMATION_NAME, AutomationName.ANDROID_UIAUTOMATOR2)
setCapability(MobileCapabilityType.APP, "/Users/danielchen/Desktop/app-debug.apk")
}
return AndroidDriver(URL("http://127.0.0.1:4723/wd/hub"), capabilities)
}
在Test class裡我們跟之前一樣在function前加上Test的annotation告訴JUnit我們要測試,再來我們透過剛剛講的AndroidDriver的回傳物件來操作元件測試。針對我們有用到的語法說明如下。
class UnitTest {
@Test
fun testAppium() {
getAppiumDriver().apply {
manage().timeouts().implicitlyWait(15, TimeUnit.SECONDS) //設定每個動作的最長等待時間
findElementById("button").click() //進入MainActivity後透過ID尋找button元件並呼叫click點擊
//進入ListActivity後利用xpath抓取RecyclerView裡的元件(請參閱Day25的說明明
val userList = findElementsByXPath("/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.view.ViewGroup/android.widget.FrameLayout[2]/android.widget.LinearLayout/androidx.recyclerview.widget.RecyclerView/android.widget.LinearLayout\n")
//我們click第一個item
userList[0].click()
//進入DetailActivity後抓取editText並輸入God
findElementById("editText").sendKeys("God")
//找到Button元件點擊
findElementById("button").click()
//最後用assertEquals方式判斷textView裡的字串是不是跟預期一樣。
assertEquals(findElementById("textView").text, "God is level 10")
}
}
}
我們很快就完成了一個e2e的測試,你有沒有發現我們沒有寫到任何一行Android SDK的程式,只要拿了build好的APK就完成了這次的測試,很神奇吧。透過Appium的測試我們可以讓不會寫Android或IOS的人加入測試的行列,也可以讓各自平台的工程師用更快速的方法來寫e2e測試。以Andriod平台來說,用Appium開發比用Espresso簡單很多,雖然performance會差一點點,必竟一個是native控制一個是透過web selenium去轉發,但開發時間就有顯著的差異了。
而e2e test一個很重要的特點是模擬使用者的行為,大家都知道Android phone的特色就是各家廠商都在framework層有不同程度的客制化,A手機執行沒問題不代表B手機執行沒問題,所以在不同的device上測試也很重要。但我們不可能只為了測試就不斷購入不同的手機,下一節我們來聊聊寫好了Appium有沒有什麼Cloud Service能讓我們更方便進行不同設備e2e的測試。