JSONPlaceholder 給了你什麼
可預期的資源。 貼文、留言、使用者、待辦事項與相簿,識別碼穩定,結構一致。
HTTP 動詞一應俱全。 GET、POST、PUT、PATCH 與 DELETE 都會給出合理的回應。
巢狀關聯。 留言屬於貼文,貼文屬於使用者。結構足夠拿來練習。
那堂意外的課
JSONPlaceholder 的寫入都是模擬的。你送出 POST,拿到帶有識別碼的 201,但什麼都沒存下來。回頭再查一次,東西並不在那裡。
多數人把這當成一種限制。其實這是整個服務裡最有用的一件事,因為它把初學者常混為一談的兩件事分開了: 請求成功了 以及 變更發生了。一套只斷言狀態碼的測試,在這裡會通過每一個寫入測試,理直氣壯,而且永遠如此。
如果你的斷言能在 JSONPlaceholder 的假寫入下存活,那它就是個薄弱的斷言。改寫它,讓它去確認事後那個東西真的存在,並把這個習慣帶到你自己的 API 上——在那裡,同樣的弱點是看不見的。
該在這裡練什麼,照這個順序
結構與欄位
針對回應主體的結構做斷言,而不是狀態。
檢查型別,不只是檢查有沒有。
關聯
先取得一篇貼文,再取得它的留言,然後確認那些留言真的指向這篇貼文。
大多數真正的 bug 都藏在兩次呼叫之間。
失敗路徑
請求一個不存在的識別碼,並斷言回應的結構是正確的。
大家會略過的那種測試,也正是真的抓得到問題的那種。
它教不了的事
所有跟狀態有關的事,也就是讓真實 API 測試變難的那一切。工作階段與過期、從某個回應擷取下來、要在下一個請求裡用的值、必須依序發生的呼叫,以及跑完之後的清理。JSONPlaceholder 一個都沒有,因為什麼都不會留下來。
所以它是很棒的第一個小時,卻是會誤導人的第二週。基礎一上手就換到有真實狀態的 API,並且要有難度陡升的心理準備。
帶得走的第一個小時
如果你希望這次練習在自己的 API 上真的有價值,就照順序做這四件事,而不是隨便亂試。
取得一篇貼文,針對三個特定欄位連同型別做斷言,而不是只確認呼叫成功。取得一篇不存在的貼文,針對狀態與回傳內容的結構做斷言。取得一篇貼文,接著取得它的留言,並斷言每一則留言都指向你要的那篇貼文。然後建立一篇貼文,再把它抓回來,看著斷言失敗。
最後那一項,才是整個練習的重點。寫入回報成功,識別碼也拿到了,卻什麼都沒留下來。所有值得帶到真實 API 的習慣,都藏在這件事裡:看出你的測試為什麼還是通過了,然後把它改寫成不會通過。
換到真實的服務
這四件事,在專門打造的那一層裡,就是 Auto-Authentication、Dynamic Variables、Dependency Chains 與 Auto-Cleanup 負責處理的部分。運作細節請見 API 測試文件。
終端機
npm install -g @testsprite/testsprite-cli
testsprite setup
不想在本機安裝的人,用儀表板也能完成同樣的事;完整的指令則收錄在 CLI 儲存庫。
把它對準真實 API 之後,有什麼不一樣
JSONPlaceholder 教不了的一切,正是 TestSprite 負責處理的部分。Auto-Authentication 對應執行到一半就過期的工作階段。Dynamic Variables 對應建立請求回傳的識別碼。Dependency Chains 對應必須等別的事情先發生才能執行的呼叫。Auto-Cleanup 對應每次執行留下來的紀錄。
起手式和上面的練習一樣:把專案指向你的 base URL,讓 API Discovery 列出裡面有些什麼,並在執行任何東西之前先讀過產生出來的計畫。差別在於,這份計畫現在涵蓋授權與邊界情況,而且對象是一個寫入真的會留下來的服務。
你得到的,正是這場練習一路指向的東西:經得起狀態考驗的斷言,而且是在每一次變更時執行,而不是等你想起來才跑。
為什麼我的 POST 請求沒有留下來?
這是刻意設計的。JSONPlaceholder 只是模擬寫入。把它當成一堂課:斷言要針對結果,而不是針對回應。
它適合用在 CI 嗎?
教學用的測試,偶爾可以。任何每次提交都要跑的東西,改用本機的 mock。它終究是一個免費的共用服務。
接下來我該換到什麼?
換到有身分驗證、也會真正保存資料的服務。難度陡升正是重點,能帶得走的能力就是從那裡開始的。
我可以把測試產生器對準它嗎?
可以,而且因為沒有東西會被污染,這裡很適合安全地看看自動產生的覆蓋範圍長什麼樣子。
有其他選擇嗎?
想練刻意製造的失敗與狀態碼,用 HTTPBin;想練大量資料的分頁,用 PokeAPI;想練需要身分驗證的行為,用公開的 GitHub API。