自動化測試通常可透過手動執行指令碼,或使用測試架構中的輔助程式 (通常稱為「測試執行器」) 來尋找並執行測試。不過,您不一定每次都需要手動執行指令碼。您可以利用多種方式執行測試,以便在開發生命週期的不同階段提供意見回饋和信心。
前置指令碼
網站專案通常會有由 npm、pnpm、Bun 或類似設定的設定檔 (package.json
檔案)。這個設定檔包含專案的依附元件、其他資訊以及輔助指令碼。這些輔助指令碼可能包含如何建構、執行或測試專案。
在 package.json
中,您需要新增名為 test
的指令碼,說明如何執行測試。這一點很重要,因為使用 npm 或類似工具時,「test」指令碼具有特殊意義。這個指令碼可只指向擲回例外狀況的單一檔案 (類似 node tests.js
),但我們建議您使用這個指令碼指向已建立的測試執行器。
如果您使用 Vitest 做為測試執行器,package.json
檔案會如下所示:
{
"name": "example-project",
"scripts": {
"start": "node server.js",
"test": "vitest --run"
}
}
透過這個檔案執行 npm test
會執行一次 Vitest 的預設測試組合一次。Vitest 預設會尋找所有結尾是「.test.js」或類似的檔案,然後執行這些檔案。視您選擇的測試執行器而定,指令可能會略有不同。
我們選擇使用 Vitest 這個測試架構,這個測試架構越來越受歡迎,本課程中有許多範例。如要進一步瞭解這項決策,請參閱以測試執行工具執行 Vitest。但請注意,測試架構和執行器 (甚至是不同語言) 都必須具有共通的三種版本。
手動測試叫用
手動觸發自動化測試 (例如在上述範例中使用 npm test
) 的做法,在主動處理程式碼集時可能很實際。在開發功能時,針對某項功能編寫測試可協助您瞭解該功能的運作方式,這點與測試驅動開發 (TDD) 的概念有關。
測試執行器通常會有一項簡短的指令,您可以叫用這些指令來執行部分或所有測試,並可能在儲存時重新執行測試工具模式。這些都是在開發新功能時提供的實用選項,且經過設計後,您可以輕鬆編寫新功能和/或測試,而且都能迅速提供意見回饋。舉例來說,Vitest 預設會在監看程式模式中運作:vitest
指令會監控變更,並重新執行找到的任何測試。建議您在編寫測試時在其他視窗中開啟這個連結,以便在開發測試時取得測試的相關快速回饋。
部分執行器也可讓您在程式碼中將測試標示為 only
。如果您的程式碼包含 only
測試,那麼只有在執行測試時才會觸發這些測試,讓測試開發能更快、更簡便地進行疑難排解。即使所有測試都能快速完成,使用 only
也可以減少負擔,並移除與目前所用功能或測試無關的執行測試。
如果是小型專案,尤其是只有一個開發人員的專案,您可能會希望養成定期執行程式碼集整個測試套件的習慣。如果您的測試規模很小,而且能快速完成 (所有的測試不到幾秒鐘),這個做法就特別有用,這樣您就能確保一切正常運作,再繼續下一步。
在預先提交或審查過程中執行測試
許多專案會在將程式碼合併回其 main
分支版本時,確認程式碼集是否正常運作。如果您是測試新手,但過去曾對開放原始碼專案做出貢獻,則可能已經注意到部分提取要求 (PR) 程序可以確認所有專案的測試通過,這代表令人振奮的新貢獻不會對現有專案造成負面影響。
如果您在本機執行測試,專案的線上存放區 (例如 GitHub 或其他程式碼託管服務) 不會知道測試是否通過,因此以預先提交工作的形式執行測試,會讓所有一切都有作用的貢獻者清楚知道。
舉例來說,GitHub 會將這些項目稱為「狀態檢查」,您可以使用 GitHub Actions 新增這些檢查項目。GitHub Actions 是基本測試:每個步驟都必須成功 (不會失敗或擲回 Error
),才能傳遞動作。您可以將動作套用至專案的所有 PR,且專案可能需要先傳遞動作,您才能提供程式碼。GitHub 的預設 Node.js 動作會將 npm test
做為其中一個步驟執行。
這個方法可藉由不接受未成功執行測試的程式碼,來確保程式碼集一律為「綠色」,
在持續整合中執行測試
接受綠色 PR 後,大多數的程式碼集會根據專案的 main
分支版本 (而非先前的 PR) 執行「再次」執行測試。這可能會立即發生,或定期 (例如每小時或每晚) 發生。這些結果通常會顯示在持續整合 (CI) 資訊主頁中,這個資訊主頁會顯示專案的整體健康狀態。
這個 CI 步驟似乎多餘的,尤其是程式碼集較少的專案,也就是在審查期間通過測試,因此應會在變更後通過測試。然而,事實並非如此!即使成功產生綠色結果,測試仍可能突然失敗。可能的原因包括:
- 系統「一次」接受多項變更 (有時稱為競爭狀況),並以巧妙、未經測試的方式相互影響。
- 您的測試無法重現,或測試「不穩定」的程式碼;這兩種測試都可能會通過,但因為不需要變更程式碼,測試也會失敗。
- 如果您使用程式碼集以外的系統,可能就會發生上述情況。以 Proxy 來說,請想像測試
Math.random() > 0.05
的情況:這會在 5% 的時間中隨機失敗。
- 如果您使用程式碼集以外的系統,可能就會發生上述情況。以 Proxy 來說,請想像測試
- 有些測試執行成本太高或太昂貴,例如每個 PR 執行 (例如端對端測試 (請參閱自動化測試類型)),且可能會在沒有一律快訊的情況下逐步中斷。
以上任何問題都無法解決,但整體來說,測試和軟體開發絕對是不可能的任務。
翻白覆
如果系統在持續整合中執行測試,即使測試是以狀態檢查的形式執行,版本仍可能處於「紅色」狀態,或是其他表示測試失敗的狀態。如前文所述,這可能由許多原因造成,包括提交測試時的競爭狀況,或是不穩定的測試。
如果專案規模較小,你的直覺可能會視為危機!停止所有項目、復原或還原不安全的變更,並回到已知的良好狀態。這「可以」為有效方法,但請記得,測試 (和一般的軟體!) 是「對最終目標」,而非單純的目標。您的目標可能是編寫軟體,而非所有測試都通過。而是可以改為向前,方法是搭配另一項變更來修正失敗的測試。
另一方面,您可能看過或處理過永久毀損的大型專案。更糟的是,大型專案有一個不穩定的測試,而且測試通常中斷,進而造成開發人員的警報疲勞。主管通常會需要解決這個問題,因為系統會將這些測試視為「精進開發」階段,因此甚至可能被關閉。
雖然目前沒有快速修正此問題,但這有助於更有把握地撰寫測試 (增進技能),並縮減測試的範圍 (簡化),以便更輕鬆地找出失敗情形。增加元件測試或整合測試 (更多自動化測試類型類型) 比一項難以維護和一次完成所有事項的大量「端對端測試」更有信心。
資源
隨堂測驗
npm 和類似程式在測試時尋找的特殊指令碼名稱為何?