Appium Java Test Writer
產出看起來像 SDET 親自撰寫的行動測試:一套程式碼同時涵蓋 Android 和 iOS,平行裝置安全執行,無任何 sleep,手勢相容於 java-client 9+,以及可追溯到手動案例 ID 的 Allure 報表。此外也處理 Python → Java 遷移,這是常見的真實工作任務,值得忠實完成而非僅是逐字轉換。
決定模式
- 手動案例 → Java:遵循工作流程 A。
- Python/Appium 程式碼 → Java:遵循工作流程 B。先閱讀
references/python-to-java-migration.md。 - 建立框架脚手架:根據使用者的應用程式和平台,生成
references/framework-scaffold.md中的檔案。
如果使用者分享了任何現有的 Java 框架檔案(BaseTest、螢幕類別、testng.xml、能力設定),請以他們的慣例為主,覆蓋參考檔案。
工作流程 A:手動案例 → 測試
- 標準化每個案例為:ID、標題、優先級、平台、前置條件、測試資料、步驟、預期結果。注意平台特定的步驟(Android 返回按鈕、iOS 權限提示)。
- 螢幕與元件:每個螢幕一個類別;可重複使用的小工具(底層導航、工具欄、底部表單)作為元件類別,組合到螢幕類別中。螢幕方法表達使用者意圖,並帶有 Allure
@Step("...")。導航動作返回下一個螢幕物件。 - 定位器 — 通過在同一欄位上的註解實現跨平台:
優先級:accessibility id → Android resource-id / iOS name → UiAutomator / iOS predicate 或 class chain → XPath 最後(在 iOS 上慢,在各處都脆弱;如果使用請註明原因)。如果未提供頁面原始碼、Appium Inspector 輸出或螢幕截圖,請將猜測標記為@AndroidFindBy(accessibility = "login-button") @iOSXCUITFindBy(accessibility = "login-button") private WebElement loginButton;// TODO-VERIFY locator。如果僅知道一個平台的定位器,請撰寫該平台的定位器,並在另一個註解中留下TODO-VERIFY,而不是盲目複製。 - 測試:每個案例一個
@Test,方法名稱以行為命名,帶有@TmsLink加上案例 ID,以及@Epic/@Feature/@Story/@Severity(P0 → BLOCKER/CRITICAL,P1 → NORMAL,P2+ → MINOR)。資料變體 →@DataProvider,第一欄為案例 ID,並在方法體內使用Allure.link(caseId, "tms", caseId)。每個預期結果都轉變為斷言。 - 裝置/應用程式狀態:指出需要非預設能力的案例(權限對話框需要
autoGrantPermissions=false,引導流程需要乾淨安裝 /noReset=false,僅限模擬器的功能如指紋),並將它們放在單獨的群組或註明覆蓋設定。 - 前置條件:優先使用深度連結(Android 上的
driver.get("myapp://cart"),mobile: deepLink)或 API 設定,而非長按序列。盡可能透過 API/工作階段進行登入前置條件。 - 無法自動化(真實的 SMS OTP、真實付款、無模擬器支援的生物辨識、主觀視覺檢查):在「未自動化」下列出,並提供替代方案(測試 OTP、沙箱付款、在模擬器/模擬器上使用
mobile: enrollBiometric/sendBiometricMatch、視覺比較工具)。
工作流程 B:Python → Java 遷移
- 閱讀
references/python-to-java-migration.md。 - 先映射結構(conftest fixture → BaseTest/工廠方法、頁面模組 → 螢幕類別、
parametrize→@DataProvider),然後翻譯程式碼。 - 修正反模式而非直接移植:
time.sleep→ 顯式等待,TouchAction/MultiAction→ W3C Actions 或mobile:手勢,desired-capabilities 字典 →UiAutomator2Options/XCUITestOptions,全域 driver → ThreadLocal。 - 保持測試意圖和斷言相同。如果 Python 測試斷言較弱(例如
assert element)或隱藏失敗(try/except: pass,條件內的斷言),請修正並在遷移對照表中指出,因為原始測試可能永遠無法失敗。 - 輸出遷移對照表:
Python 檔案/函式 | Java 類別/方法 | 翻譯之外的變更。
等待:顯式且基於條件
- 隱式等待設定為 0。混合隱式和顯式等待會導致不可預測的超時。
- 永遠不要使用
Thread.sleep。請使用WebDriverWait搭配ExpectedConditions(visibilityOf、elementToBeClickable、invisibilityOf、textToBePresentInElement、attributeToBe),並透過BaseScreen中的輔助方法使用。 - 等待載入器/spinner 消失,而非等待時間過去。
- 超時時間來自設定檔,而非內聯數字。
- 在執行會重新渲染列表或輪播的操作後,等待一個之後始終為真的訊號(表單關閉、載入器消失、列表存在、計數符合預期)。不要等待「第一個項目文字改變」:預期值可能已經存在,而等待會超時。BaseScreen 的等待會忽略
StaleElementReferenceException,因此在條件內重新查詢。
手勢
java-client 9 移除了 TouchAction/MultiAction。請使用:
- 滾動到元素:Android 使用
AppiumBy.androidUIAutomator("new UiScrollable(...).scrollIntoView(...)");iOS 使用mobile: scroll搭配predicateString。 - 滑動/拖曳/長按:平台特定的
mobile:手勢(Android 使用mobile: swipeGesture、longClickGesture;iOS 使用mobile: swipe、touchAndHold)或在BaseScreen中使用 W3CPointerInput序列以實現跨平台使用。 請參閱references/framework-scaffold.md→ 手勢。
平行安全性
Driver 存在於每個測試(或每個類別,如果使用者要求速度)建立的 ThreadLocal<AppiumDriver> 中,在 quit() 之後總是 remove()。每個平行裝置需要自己的 udid 和唯一的 systemPort(Android)/ wdaLocalPort(iOS)來自 testng.xml 參數。沒有靜態 driver 或靜態元素狀態。
輸出格式
- 檔案:完整的可編譯檔案,包含 imports,每個檔案在其路徑標題下。如果超過約 3 個檔案或使用者想要下載,也將它們寫入磁碟作為專案資料夾。
- 追溯性對照表(工作流程 A)或遷移對照表(工作流程 B)。
- 未自動化 / 差距。
- 需要驗證:計算並列出
TODO-VERIFY定位器數量、假定的能力(應用程式路徑、套件/活動、bundle id)、僅限平台的步驟。
保持文字簡潔;程式碼才是最終產出。
機密性
對於作品集/公開項目,請使用套件 com.example(或使用者的套件)、一個公開的示範應用程式,並將任何公司名稱、內部應用程式 ID、內部 URL、真實電話號碼/電子郵件或專有活動名稱替換為中性名稱。在一行中說明替換。
參考檔案
references/framework-scaffold.md:pom.xml、設定檔、包含 ThreadLocal + Options 類別的 DriverFactory、包含失敗時 Allure 截圖/頁面原始碼擷取的 BaseTest、包含等待輔助方法和手勢的 BaseScreen、用於平行裝置的 testng.xml。references/python-to-java-migration.md:Python Appium/pytest 慣用語法與 Java/TestNG 的並排映射,以及一個完整的遷移範例。references/example-swaglabs.md:關於 Sauce Labs 公開示範應用程式的手動案例 → 螢幕 → 測試。