上一篇 走進 Prism for Xamarin.Forms 講了簡單的創建一個項目,然后添加了幾個頁面來回切換,這篇想先搞下 UITest
官方詳細地址:https://developer.xamarin.com/guides/testcloud/uitest/intro-to-uitest/
一、首先在項目上右鍵添加一個 UITest 項目,我命名為 SD.Xamarin.UITest ,因為 項目叫 SD.Xamarin
建完的項目引用的 NUnit 的引用包千萬別升級,官方說了,3.X的是不兼容的,所以你就用2.6.X的好了,官方文檔很重要有木有,不然像我總喜歡升級到最新版的人,就會悲劇的
IOS項目需要添加 Nuget 包 Xamarin.TestCloud.Agent(官網說的,沒有 Mac 沒法測試)
同時要添加 Android 和 IOS 項目的引用
摘自官方的說明
- NUnit 2.6.x – Xamarin.UITest is not compatible with NUnit 3.x.
- A Test Runner for Visual Studio – A 3rd party test runner, such as the NUnit Test Adapter for NUnit 2 or Resharper from Jetbrains, is required for Visual Studio to be able to run the NUnit tests. The NUnit3TestAdapter is not compatible with Xamarin.UITest.
- Android SDK – Only if testing Android apps. Windows requires that the
ANDROID_HOME
environment variable is set with the path to the Android SDK. - Java Developers Kit – Only if testing Android apps.
二、執行 Test
- REPL
建完項目會有2個文件,其中一個叫 AppInitializer.cs 的文件就是配置路徑的文件,也就是讓項目知道去哪里找到生成的包文件,Android 的是 apk 文件,IOS 的是 app 文件
public class AppInitializer { public static IApp StartApp(Platform platform) { if (platform == Platform.Android) { return ConfigureApp .Android .ApkFile("../../../SD.Xamarin/SD.Xamarin.Droid/bin/Release/SD.Xamarin.Droid.apk") .StartApp(); } return ConfigureApp .iOS .AppBundle("../../../SD.Xamarin/SD.Xamarin.iOS/bin/iPhoneSimulator/Release/SD.Xamarin.iOS.app") .StartApp(); } }
紅色的部分就是需要自己加的,因為在一個項目文件夾下,所以前邊的 ../../../ 就是往上找目錄(C# 的人都懂的),然后是 項目名 / 測試平台的項目名 / 生成包的路徑,Debug 還是 Release 隨你喜歡了(Debug 的包名稱要適當修改,見下邊),這里要說明下,千萬不要把項目放到VS 的默認目錄下,因為 WIN 10 的權限關系,它只讓你搞 AppData 文件夾,而 VS 默認目錄是 Document 文件夾,所以你根本找不到。
Android: Debug 目錄下生成的是 SD.Xamarin.Droid-Signed.apk ,Release 目錄下會生成 SD.Xamarin.Droid-Signed.apk 和 SD.Xamarin.Droid.apk 兩個
IOS: 由於沒有Mac 無法驗證,但是看到生成 的是 SD.Xamarin.IOS.exe ,不是 app ,不知道是否沒有連接 Mac 的事情
當然跑之前要先 Build 好 apk 包,因為用 Android 跑的, IOS 需要連接 Mac 所以沒法測試
這是 Test 方法
[Test] public void TestLogin() { _app.EnterText(n => n.Marked("Username"), "Name"); _app.EnterText(n => n.Marked("Password"), "Password"); _app.Tap(c => c.Button("LoginButtons")); _app.Repl();
AppResult[] result = _app.Query();
Assert.IsTrue(result.Any(), "Login"); }
先運行下試試
失敗了,不過沒關系,說明配置都是對的,只是沒有設備而已。
啟動 Visual Studio Emulator for Android
嗯,還是配置的問題
官方說要這樣配置,https://developer.xamarin.com/guides/testcloud/uitest/working-with/running-tests-in-ide/
TARGET | ARCHITECTURE |
---|---|
iOS Simulator | x86 |
iOS device | x86_64 |
Android Device | Typically armeabi-v7a |
Google Emulator | Depends on the Android Virtual Device |
改到 Release 和 ARM 后,再來,彈出了一個窗體,輸入 tree 回車
成功了,頁面里內容都顯示出來了,而且因為我寫了 Button 的觸發,還列出了跳轉后的頁面的內容
同時模擬器也會有跑 Test
- 真機調試
1.手機啟用開發者模式,USB 調試打開
2.電腦上安裝 Google USB Driver(Android SDK Manager 里最下邊那里有)
3.把手機連接到電腦上,如果一切正常,啟動那里就可以選 Device 了(手機的名字,比如我的 Letv X800+)
如果你現在直接啟動測試,會發現報錯
那就指定一下設備吧,打開 ADB 控制台
輸入 adb device
很明顯的錯誤,是說2個設備,因為還有個 Emulator ,所以你需要指定設備,設備號碼在錯誤里會有,修改啟動方法如下
public static IApp StartApp(Platform platform)
{
if (platform == Platform.Android)
{
return ConfigureApp
.Android
.ApkFile("../../../SD.Xamarin/SD.Xamarin.Droid/bin/Release/SD.Xamarin.Droid.apk")
.DeviceSerial("96e5b85b")
.StartApp();
}
return ConfigureApp
.iOS
.AppBundle("../../../SD.Xamarin/SD.Xamarin.iOS/bin/iPhoneSimulator/Release/SD.Xamarin.iOS.app")
.StartApp();
}
當你再次啟動測試時,會發現還是會報錯,超時的錯誤,這點和 Emulator 很不一樣,所以需要修改測試方法
[Test] public void TestLogin() { _app.Tap(c => c.TextField("Username")); _app.EnterText(n => n.Marked("Username"), "Name"); _app.WaitForElement(n => n.Marked("Username").Text("Name")); _app.Tap(c => c.TextField("Password")); _app.EnterText(n => n.Marked("Password"), "Password"); _app.WaitForElement(n => n.Marked("Password").Text("Password"), ""); _app.Tap(c => c.Button("LoginButton")); AppResult[] result = _app.Query(); Assert.IsTrue(result.Any(), "Login"); }
在我看來這樣應該是對的了,但是不知道是我的環境問題還是怎樣,在想把焦點跳到 Password 的時候,手機的虛擬鍵盤收起又彈出,但是焦點沒有跳過去,所以我手點了一下,運行到點擊 Button 的時候又跳不過去焦點,於是我又點了一下,但是沒有在登錄按鈕上抬起,於是焦點跳過去了,然后就觸發了 Button 的點擊,但是不寫 Tap 第一個 Username 的焦點也不會進,所以我覺的焦點是這么跳的,我想不可能是只需要 WaitForElement 方法,然后都需要手動輸入吧,掐斷點的時候你會發現到 WaitForElement 方法的時候是會停住的,直到符合條件才會繼續,但是如果你一直不符合條件,還是會報超時的錯誤。
Tips:1. 如果這里是我理解的錯誤,還請賜教
2. 如果跑 test 時遇到 refused to install the app by The ADB command ! 錯誤,去任務管理器里結束 adb.exe 進程
- Xamarin Test Cloud
首先需要注冊試用,https://testcloud.xamarin.com/register
進去后右上角點擊 頭像下的 Account Setting ,左邊選 Teams & Apps,show API Key 會出來一個 key 留着一會上傳用
SD.Xamarin\packages\Xamarin.UITest.2.1.2\tools 下會有一個 test-cloud.exe (VS 2017 沒有右鍵上傳,VS 2015 有)
如果賬號確認后,就可以創建新的 Test 了
點擊 New Test Run,選擇 Android
選擇想測試的設備
選擇分支和語言
最終生成了腳本的模板
復制腳本,修改你的真實參數
打開 cmd 窗體,把位置改到項目的地址
比如代碼放在了E盤
- E:
- cd E:\Code\SD.Xamarin
- 粘貼修改過的命令
回車后會看到上傳過程和結果
失敗了,沒關系,先繼續看同時網頁那邊的情況,回頭再改
當再次刷新網站時,頁面變成下邊這樣
點進去看看詳情
可以看到正在跑 Test
點進去看下
這就是大概的詳情,下邊還有一些內容,請自己試驗時看吧
點擊失敗的 Test 可以看到截圖
具體錯誤的原因可以查看 Log 修改,直到 可以測試成功。
補充成功的截圖
雖然成功了,但還是很奇怪,焦點跳不過去,所以沒有跳轉頁面,但是模擬器卻始終好使。
這里就是模擬器和真機的區別了,模擬器沒有顯示鍵盤,真機需要手動關閉一下鍵盤,不然焦點就會不跳轉
修改后的代碼如下
[Test] public void TestLogin() { _app.WaitForElement(x => x.Marked("Username")); _app.Tap(x => x.Marked("Username")); _app.EnterText(x => x.Marked("Username"), "Name"); _app.Screenshot("Fill Name Finished"); _app.DismissKeyboard(); _app.WaitForElement(x => x.Marked("Password")); _app.Tap(x => x.Marked("Password")); _app.EnterText(x => x.Marked("Password"), "Password"); _app.DismissKeyboard(); _app.Tap(x => x.Marked("LoginButton")); _app.Screenshot("Login"); AppResult[] result = _app.Query(); Assert.IsTrue(result.Any(), "Login"); }
腳本生成過程 https://developer.xamarin.com/guides/testcloud/organizations-and-teams/creating-a-test-run/
腳本參數 https://developer.xamarin.com/guides/testcloud/uitest/working-with/submitting-tests-at-command-line/
四、幾個 Test 方法
方法 | 描述 |
Button |
在屏幕上定位一個或多個按鈕 |
Class |
定位指定類的視圖 |
Id |
用指定的Id定位視圖 |
Index |
從集合中返回匹配的視圖。通常和其他方法結合使用。接受從0開始的索引 |
Marked |
根據之前提到的啟發返回視圖 |
Text |
匹配包含提供文本的視圖 |
TextField |
匹配 Android EditText 或者 iOS UITextField . |
更多內容請參考官方文檔,如有錯誤以官方為准,有些地方翻譯和理解的可能有誤差