判斷需要測試的項目,以及可以排除的項目。
上一篇文章介紹了測試案例的基本概念,以及應包含的內容。本文將從技術層面深入探討如何建立測試案例,並詳細說明每項測試應包含哪些內容,以及應避免的事項。基本上,您將會知道「要測試什麼」或「不應測試什麼」這類老問題的答案。
一般規範和模式
值得注意的是,無論您是進行單元、整合或端對端測試,特定模式和測試點都至關重要。這些原則可且應套用於兩種測試,因此是個不錯的起點。
保持簡單
在編寫測試時,請務必記住最重要的一點:保持簡單。請務必考量大腦的容量。主要的正式版程式碼會占用大量空間,因此無法再容納其他複雜的程式碼。這對測試來說尤其重要。
如果可用的空間較少,您在測試時可能會比較放鬆。因此,在測試時,請務必以簡單為優先。事實上,Yoni Goldberg 的 JavaScript 測試最佳做法強調了「黃金法則」的重要性:測試應像助理般提供協助,而非複雜的數學公式。換句話說,您應該能夠一眼瞭解測試的意圖。
無論測試類型有多複雜,您都應盡量簡化測試。事實上,測試越複雜,就越需要簡化。其中一種方法是採用平面測試設計,讓測試盡可能簡單,並只測試必要項目。也就是說,每個測試都應只包含一個測試案例,且測試案例應著重於測試單一特定功能。
從這個角度來看,讀取失敗測試時,應該可以輕易找出問題所在。因此,讓測試保持簡單易懂非常重要。這樣一來,您就能在問題發生時快速找出並修正問題。
測試哪些內容能發揮效用
平面測試設計也有助於吸引注意力,並確保測試有意義。請注意,請勿為了涵蓋率而建立測試,測試應有其目的。
不要測試實作詳細資料
測試中常見的問題之一,是測試通常會設計用於測試實作細節,例如在元件或端對端測試中使用選取器。實作詳細資料是指使用者通常不會使用、看到或瞭解的程式碼。這可能會導致測試中出現兩個主要問題:偽陰性和偽陽性。
偽陰性是指即使測試的程式碼正確,測試仍會失敗。應用程式程式碼重構後,實作細節可能會變更,就會發生這種情況。另一方面,即使測試通過,但測試的程式碼不正確,也會發生偽陽性。
解決這個問題的方法之一,就是考慮您擁有的不同類型使用者。使用者和開發人員的做法可能不同,因此他們與程式碼的互動方式也可能不同。規劃測試時,請務必考量使用者會看到或互動的內容,並讓測試依據這些內容,而非實作細節。
舉例來說,選擇較不易變更的選取器可讓測試更可靠:使用資料屬性,而非 CSS 選取器。詳情請參閱 Kent C. 請參閱 Dodds 的文章,或稍後再回來查看相關文章。
模擬:不要失去控制
模擬是單元測試 (有時也用於整合測試) 中使用的廣義概念。這項作業包括建立假資料或元件,模擬可完全控制應用程式的依附元件。這可進行隔離測試。
在測試中使用模擬資料可提高可預測性、分離關注重點和效能。如果您需要進行需要人為介入的測試 (例如護照驗證),則必須使用模擬資料隱藏測試。基於上述所有原因,模擬是值得考慮的實用工具。
同時,模擬可能會影響測試的準確度,因為模擬並非真實的使用者體驗。因此,使用模擬和虛擬資料時,請務必謹慎小心。
您是否應該在端對端測試中模擬?
一般來說,不建議這麼做。不過,模擬有時可以派上用場,因此我們不排除這個選項。
請想象以下情境:您正在為涉及第三方付款供應商服務的功能編寫測試。您目前處於他們提供的沙箱環境中,也就是說並未進行任何實際交易。很抱歉,沙箱發生故障,導致測試失敗。付款服務供應商必須修正問題。你只能等待供應商解決問題。
在這種情況下,減少對無法控制的服務的依賴程度可能會更有幫助。不過,建議您在整合或端對端測試中謹慎使用模擬功能,因為這會降低測試的信賴水準。
測試詳細資訊:允許和禁止事項
總而言之,測試包含哪些內容?測試類型之間有差異嗎?接下來,我們將進一步探討幾個針對主要測試類型量身打造的特定面向。
什麼是良好的單元測試?
理想且有效的單元測試應具備下列條件:
- 著重於特定面向。
- 獨立運作。
- 涵蓋小規模情境。
- 使用描述性名稱。
- 視情況採用 AAA 模式。
- 確保全面的測試涵蓋率。
建議做法 ✅ | 錯誤做法 ❌ |
---|---|
請盡可能縮小測試規模。每個測試案例只測試一項項目。 | 為大型單元編寫測試。 |
請務必隔離測試,並模擬單元外所需的內容。 | 加入其他元件或服務。 |
保持測試的獨立性。 | 依賴先前的測試或共用測試資料。 |
涵蓋不同的情境和路徑。 | 最多只測試正常路徑或負面測試。 |
使用描述性測試標題,讓您一眼就能看出測試內容。 | 僅依函式名稱測試,無法提供足夠的描述性資訊:testBuildFoo() 或 testGetId() 。 |
請盡量提高程式碼涵蓋率或擴大測試案例範圍,尤其是在這個階段。 | 從每個類別測試到資料庫 (I/O) 層級。 |
什麼是良好的整合測試?
理想的整合測試也與單元測試共用一些條件。不過,您還需要考量其他幾點。優質的整合測試應具備下列特徵:
- 模擬元件之間的互動。
- 涵蓋實際情境,並使用模擬或虛擬項目。
- 考量效能。
建議做法 ✅ | 錯誤做法 ❌ |
---|---|
測試整合點:確認各個單元在整合時能順利運作。 | 單元測試就是用來個別測試每個單元。 |
測試實際情境:使用實際資料衍生的測試資料。 | 使用重複的自動產生測試資料或其他不反映實際用途的資料。 |
使用外部依附元件的模擬資料和虛擬資料,以便控管完整的測試。 | 建立對第三方服務的依附元件,例如對外部服務的網路要求。 |
在每次測試前後使用清理例行程序。 | 忘記在測試中使用清理措施,否則可能會因缺乏適當的測試隔離而導致測試失敗或誤判。 |
什麼是良好的端對端測試?
完整的端對端測試應符合下列條件:
- 複製使用者互動。
- 涵蓋重要情境。
- 橫跨多個圖層。
- 管理非同步作業。
- 驗證結果。
- 考量成效。
建議做法 ✅ | 錯誤做法 ❌ |
---|---|
使用 API 驅動的捷徑。瞭解詳情。 | 請在每個步驟中使用 UI 互動,包括 beforeEach 鉤子。 |
在每次測試前使用清理例行程序。與單元和整合測試相比,這類測試的副作用風險更高,因此請更加留意測試隔離。 | 忘記在每次測試後清理。如果您沒有清理剩餘的狀態、資料或副作用,這些項目會影響日後執行的其他測試。 |
將端對端測試視為系統測試。也就是說,您需要測試整個應用程式堆疊。 | 單元測試就是用來個別測試每個單元。 |
在測試中盡量減少模擬,甚至不使用模擬。請仔細考慮是否要模擬外部依附元件。 | 極為仰賴模擬資料。 |
考量效能和工作負載,例如在同一個測試中不要過度測試大型情境。 | 不使用捷徑就能涵蓋大量工作流程。 |