在昨天 Day 2-什麼是單元測試及何謂優秀的單元測試? (基礎-1) 曾提到早期的測試開發,可能會因為開發者風格的不同,導致測試單元可大可小;換一種說法,若今天這次測試單元檢測由複數個邏輯組成的功能例如開發系統時,先從資料庫取得資料後進行商業邏輯處理,再進行資料重組等,則大大地增加測試的複雜性。舉例來說,撰寫測試流程中可能會因為檢測複數個檢查點如資料庫連線、原生 SQL 或 ORM 取得的資料是否正確、演算法的流程是否有誤、模擬資料結構重組後是否符合預期等,而可能產生多個失敗的可能性。
此外,上述流程或許多其他的系統開法,其商業邏輯通常會搭配第三方套件資料結構或功能,會使得原始碼無法完全掌控,違背了單元測試的定義。然而,對於系統的穩定性,還是需要驗證模組與模組之間的邏輯關係(由如上述的檢驗流程),又或是透過第三方套件驗證一些行為 (Behavior) 是否執行正常(例如:利用 NUnit3 + Selenium 驗證網頁的 UI 元件執行情況或 NUnit3 + EntityFramework 創造測試用的資料庫與資料表進行 SQL 相關功能的驗證等等)。
因此,Roy Osherove 在單元測試的藝術中定義了整合測試:
整合測試是對一個工作單元進行測試,而這個測試對被測試的單元並沒有完全的控制,而是使用該單元的一個或多個真實依賴的相依物件,例如時間、網路、資料庫、執行緒、或亂數產生器等等。
綜合單元測試與整合測試的描述,兩者之間最大的不同在於,單元測試的測試流程需引用本身內建的程式碼功能(已達到完全控制,不會有黑盒子的狀況);而整合測試則是可利用第三方套件驗證較複雜的行為且可針對較流程繁瑣的系統進行整合性驗證。
另一種常見的驗證方式,是利用使用端對系統端進行測試。常見的例子是網站系統上線時,模擬使用者的行為對網站進行互動,並驗證其結果是否符合預期行為。此部分的行爲是最為複雜的,常見的例子是早期網站開發時,版面的狀況會隨著瀏覽器的不同導致不一樣的排版,針對排版自動化的測試是極其複雜的事情,因此常見的手法為開發完的系統上線後,由開發團隊的 PG, SA, PM 等人一同人工觀閱其正確性。
但後來針對端對端測試,依然還是有採取半自動化甚至可達到全自動化的測試,比如 Google 針對發展的 Angular Material UI 元件庫還是提供了可自動化且完整的 E2E 測試,透過自動化截圖並匹配圖片來比對 UI 誤差是否大於 1px 的手法,提供該資訊的文章來源可參閱 Will 保哥的文章-次搞懂單元測試、整合測試、端對端測試之間的差異又或是直接觀閱 Google 提供的說明會。而現在大多前端的套件或工具都有針對 E2E 測試提供各種 APIs,比如 Postman、Vue.js、React.js 或 Angular.js。
相信除了整合測試、端對端測試,還有許多其他的測試方式;但因為篇幅關係在此就先不探討,所以總結單元測試是在撰寫套件時,驗證其行為是否符合預期、整合測試是在系統模組與模組之間介接的時候,驗證其相互行為是否正常;而端對端測試則是在驗證系統(文章以網站為例)運行是否正常。以下的圖做個這三個測試之間關係的總結:
如果想瞭解更細,可參考 Lawrence Tan 在 Medium 寫的文章——Unit Tests, UI Tests, Integration Tests & End-To-End Tests 在 In Summary 階段提供了數張圖片,很清晰的詮釋了這幾種測試之間的關係該文章提供了單元測試、整合測試與端對端測試的相對應關係。
此外,在查閱整合測試的相關資料時,發現 C# 論壇中,已經有人在探討如何用單元測試或整合測試的觀點來驗證 Web APIs 的功能是否正常 (RESTful Day #7)。會做為在此三十天當中,單元測試-情境及應用部分的主題參考,若有興趣者可先翻閱該網站,又或是等我下半月的文章。
最後,花了三天的時間介紹了==單元測試的基本概念(很多都是在網路上常介紹的內容,透過這三天算是做個整理),明天開始會開始接觸程式碼(C#、NUnit 3)及環境設定(終於要開始寫程式碼了 XDDD)。