為什麼要 POM:把「測什麼」和「怎麼操作」分開
#Page Object Model #POM #測試架構 #QA 實戰
開發把登入按鈕的 resource id 改了一個字,你的測試崩了十二個。你一個一個去改,改完隔天他又動了輸入框。問題出在你的測試沒有把「操作 UI」這件事集中管理。 沒有 POM 的痛 locator 直接寫在每個 test 裡,看起來快,痛起來慢。 et username 改名成 input username,你要改幾行?光這三個 test 就有兩處;五個 locator 加起來,總共寫了十次。locator 越散、test 越多,維護成本就越高。 POM 是封裝 Page Object Model 的核心只有一件事: 把 UI 的結構和操作藏進一個 class,讓 test 只看語意。 test 只需要呼叫 login page.login(...),完全看不見任何 locator: et username 改名,只要改 LoginPage. USERNAME 一行,三個 test 全部自動修好。 好處 UI 改只改一處 :locator 集中在 page class,不散在 test 裡。 測試讀起來像業務語言 :login page.login("demo", "pw") 一眼就懂,比一長串 find element(...) 接 send keys(...) 好讀得多。 重複操作可複用 :登入這個動作在幾十個 test 裡都用同一個 method,不用複製貼上。 一個原則 斷言放在 test,不放進 page object。 page object 負責「怎麼操作」,test 負責「驗什麼」。兩件事分開,失敗訊息才清楚:是操作壞了,還是預期行為錯了。 實務上我會讓 page object 的方法回傳布林值或資料,例如「有沒有看到歡迎文字」,由 test 拿去 assert。這條界線我守得很嚴:整個專案的 page object 裡,幾乎找不到斷言。 POM 還能少下指令 POM 常被講成「好維護」。我在專案裡還發現另一個好處:它能讓測試跑得比較快。 App 自動化最花時間的,是一個一個送到裝置上的指令。導航、關彈窗、返回首頁,每一步都是好幾個來回。這些步驟如果攤在測試裡,每支測試都要重寫一次,也很難看出哪裡可以省。 這是我專案裡一支測試改寫前的樣子(名稱換成通用的),驗證訪客點進付費功能時會被擋下來: 改寫後,流程收進 page object 的一個高階方法: 流程收進來以後,重複的彈窗處理和導航可以合併,不用每支測試各做一次,指令數自然就少了。更重要的是,下次 UI 流程改了,只要改 check premium blocked 一處。 我後來把這件事變成 review 時的檢查項目: 測試裡有連續三個以上的導航呼叫 → 收進 page object 的高階方法 同一段彈窗處理在好幾支測試裡重複 → 收進共用方法 一支測試驗了太多東西 → 拆開,一支只驗一個核心行為 為了「保險」多加的重複檢查 → 拿掉 我現在的判斷標準 打開一支測試,如果讀起來像操作手冊(先點這裡、再點那裡、關掉這個、返回),就是 page object 還沒封裝好。讀起來像驗收條件(訪客點付費功能會被擋),才算對了。