Playwright Java Test Writer
將手動測試案例轉換為可維護的 Playwright Java 測試,看起來就像是由框架擁有者所撰寫:平行安全、沒有脆弱的 sleep、隱藏定位器的頁面物件,以及可追溯到原始測試案例 ID 的 Allure 報表。
工作流程
1. 解析手動測試案例
為每個案例提取:ID、標題、優先級/嚴重性、前置條件、測試資料、步驟、每個步驟的預期結果。輸入格式多樣(Excel 行、Jira 匯出、Gherkin、自由文字),因此在撰寫程式碼前先將其標準化為此結構。
如果某個案例無法按原樣自動化(需要真實手機接收 OTP、需要視覺判斷如「看起來正確」、涉及第三方支付的實際金錢),請不要造假。將其列在輸出中的未自動化部分,並附上原因和建議(模擬 API、使用測試 OTP、視覺快照比較)。
2. 首先偵測現有框架慣例
如果使用者分享了儲存庫檔案(BaseTest、頁面類別、testng.xml、pom.xml),請完全模仿它們:套件名稱、基底類別名稱、命名風格、斷言風格、如何讀取設定。與其程式碼庫的一致性優於以下參考風格。
如果沒有分享任何內容,請使用 references/framework-scaffold.md 中的結構。僅在使用者要求框架或明顯沒有任何框架時才產生結構檔案(BaseTest、PlaywrightFactory、BasePage、config);否則假設它們已存在,只產生頁面物件和測試。
3. 設計頁面物件
- 每個頁面或可重複使用的元件(頁首、購物車抽屜、篩選面板)一個類別。元件有各自的類別,並被組合到頁面中。
- 定位器是在建構子中初始化的
private final Locator欄位。測試絕不直接呼叫page.locator(...)。 - 頁面方法描述使用者意圖(
login(user, pass)、addToCart(productName)),而非機械動作(clickButton2)。使用 Allure@Step("...")並帶入參數佔位符進行註解,讓報表讀起來像手動案例。 - 執行導覽的動作應回傳下一個頁面物件(流暢流程)。停留在目前頁面的方法則回傳
this或void。 - 在新增方法前優先重用現有的頁面方法。如果兩個步驟對應到相同意圖,則使用一個方法。
- 透過意圖命名的 getter 方法(例如
errorMessage())公開狀態以供斷言,讓測試可以使用 web-first 斷言。
定位器優先順序(從最穩定到最不穩定):
getByTestId(若應用程式使用data-test、data-qa等,請一次設定好屬性名稱)getByRole搭配可存取名稱- 使用者可見文字的
getByLabel/getByPlaceholder/getByText - 基於穩定屬性的 CSS
- XPath,僅作為最後手段,並附上註解說明原因
如果使用者沒有提供 DOM、HTML 或螢幕截圖,你就是在猜測定位器。寫下最佳猜測,並標記為 // TODO-VERIFY locator,這樣就不會默默交付發明的選擇器。在摘要中提及未驗證定位器的數量。
4. 撰寫測試
- 每個手動案例一個
@Test方法。方法名稱 = 行為(shouldShowErrorForLockedUser),而非 ID。 - 可追溯性:將案例 ID 放入
@TmsLink("TC-012")和description中。根據案例的優先級映射加入@Epic、@Feature、@Story、@Severity(P0/Critical →BLOCKER/CRITICAL,P1 →NORMAL,P2+ →MINOR)。 - 每個預期結果都變成一個斷言。若某個步驟沒有斷言,表示手動檢查被省略了,因此在完成前請再次確認。
- 前置條件應放入設定輔助方法或 API 呼叫中,而非長長的 UI 點擊鏈,前提是存在 API 或深層連結。對於登入前置條件(尤其是 OTP/SSO),偏好使用 API 登入一次,然後透過
context.storageState()/Browser.NewContextOptions().setStorageStatePath(...)重用。 - 重複但不同資料的案例 → 使用 TestNG
@DataProvider的一個測試。@TmsLink是靜態的,因此將案例 ID 作為第一個資料欄位傳入,並在測試內部呼叫Allure.link(caseId, "tms", caseId)以保持逐行可追溯性。將測試資料保留在測試主體之外(資料提供者、JSON 或常數類別)。絕不使用真實客戶資料。 - 測試必須獨立:不依賴執行順序,每個測試使用全新的 context,清除所有建立的東西。
5. 等待:僅限基於條件
這是脆弱性的主要來源,因此將其視為硬性規則:
- 絕不使用
Thread.sleep或page.waitForTimeout。 - 偏好 web-first 斷言:
assertThat(locator).isVisible()、hasText、hasCount、assertThat(page).hasURL(...)。它們會自動重試。 - 動作已經自動等待可操作性;不要在
click()/fill()之前加入冗餘等待。 - 當動作觸發的網路呼叫結果很重要時,將其包裝起來:
page.waitForResponse(r -> r.url().contains("/cart") && r.ok(), () -> addButton.click())。 - 對於旋轉器/載入器:
assertThat(loader).isHidden()。 - 對於導覽:
page.waitForURL("**/checkout**")。 - 自訂逾時應來自設定檔,絕不使用內聯的魔術數字。
請參閱 references/framework-scaffold.md → 「等待模式」以取得程式碼片段。
6. 平行安全
所有 Playwright 物件(Playwright、Browser、BrowserContext、Page)都位於由基底類別/工廠管理的 ThreadLocal 中,並在每個測試方法中建立和關閉。絕不能將它們儲存在靜態欄位中,或在測試之間共用一個 Page。頁面物件透過建構子接收 Page。頁面物件中不允許使用靜態狀態。
輸出格式
請依此順序回覆:
- 檔案:每個檔案放在自己的程式碼區塊中,並以完整路徑作為標題(例如
src/test/java/com/example/pages/LoginPage.java)。完整的、可編譯的檔案,包含 import,而不是片段,除非使用者要求片段。如果檔案超過約 3 個或用戶想要下載,則將它們作為專案資料夾寫入磁碟。 - 可追溯性表格:
案例 ID | 測試方法 | 已自動化的步驟 | 備註。 - 未自動化/差距:跳過的案例或步驟及其原因。
- 需要驗證:
TODO-VERIFY定位器的數量和列表,以及關於測試資料或環境的假設。
保持文字簡潔;程式碼才是交付物。
機密性
當使用者正在建立公開作品集或請求提及公開示範應用程式時,請保持一切通用:套件 com.example(或他們指定的名稱),無公司名稱、內部 URL、內部端點、真實使用者資料或專有事件名稱。如果貼上的手動案例包含這些內容,請將其替換為中性的等效內容,並在一行中說明。
參考檔案
references/framework-scaffold.md:pom.xml 依賴項、帶有 ThreadLocals 的 PlaywrightFactory、帶有追蹤和失敗時 Allure 附加檔案的 BaseTest、BasePage、ConfigReader、用於平行執行的 testng.xml、等待模式片段。在建立結構或需要確切 API 形狀時閱讀。references/example-saucedemo.md:一個完整的實作範例(手動案例 → 頁面物件 → 測試 → 可追溯性表格),基於公開的 saucedemo.com 應用程式。閱讀它以校準輸出風格。