選單
GSS 技術部落格
在這個園地裡我們將從技術、專案管理、客戶對談面和大家分享我們多年的經驗,希望大家不管是喜歡或是有意見,都可以回饋給我們,讓我們有機會和大家對話並一起成長!
若有任何問題請來信:gss_crm@gss.com.tw
6 分鐘閱讀時間 (1129 個字)

CDC Testing

cdc-vs-e2e https://microsoft.github.io/code-with-engineering-playbook/automated-testing/cdc-testing/

近年來的疫情可說是大大影響了我們,「疾管署」Centers for Disease Control, CDC 也成為熱門單位。筆者這次想蹭個熱度,談談軟體測試領域中的 CDC (Consumer-driven Contract) Testing,以及如何在 .NET API 開發中應用。

首先概述一下,在測試金字塔最頂端的 End-to-End 測試,雖然速度最慢,成本最高,但還是在大多數網際網路服務中,除了又笨又沒效率的人工測試之外,最能佔據使用者的目光,也最能吸引開發端投入。

因此這也造就了「使用者驅動的合約測試」,所謂「使用者」,相對於提供者或開發者,指的是 API 或訊息佇列的一方。在多數的開發場景,由系統分析師多次訪談,來回確認以挖掘出使用者真正的需求,並交給開發人員實作,但這個過程不但冗長又不好控制。那有沒有可能由使用者主動提出心中願景呢?如果這種「合約」能夠很容易地產出,對雙方是不是都具有重大意義?理想是如本文一開始的配圖,讓維護成本與時間呈線性,而非指數關係,而且這概念已被廣泛移植到各種程式語言了。聽起來不錯,接下來讓我們看看 .NET 如何實現? 

在 cdc.sln 方案中包含了四個專案 Consumer, Consumer.Tests, Provider, Provider.Tests 與一個目錄 Contract,應該不難想像使用者/提供者各負責兩個專案,並共享 Contract 目錄的內容。既然是使用者驅動,那想必是由 Consumer 或 Consumer.Tests 專案開始(如果你信奉 TDD)。這裡再借 Martin Fowler 大師站上的文章,從一個極簡的功能需求說起:

這些敲定後,這次我們不走傳統的 Provider 先行,而是由 Consumer 深入,以進一步提供細節。首先是專案唯一的程式 HelloApiClient.cs:

三大功能需求,在此由使用者角度實現了兩項,諸如路徑、動詞、標頭、內容、狀態碼、例外處理等,但畢竟不是真的做,重點在描述合約。接下來看 Consumer.Tests 專案,首先引入 PactNet 套件參考,然後唯一的程式:

這是一個 Xunit 單元測試,要特別說明的幾行是:

  • 17 由編譯結果位置 <Solution>\Consumer.Tests\bin\Debug\net8.0 起算,上四層正好到方案目錄,之下的 Contract 子目錄用來放雙方共享的合約。
  • 19 雖然套件目前的穩定版本是 4.5,但這裡指的是 Pact Specification v3,這個坑我掉進去很久才爬出來,希望聰明的讀者你不會。第一個參數是 Consumer 的名稱,第二個則是 Provider。
  • 27 為這份合約取個名稱
  • 28 動詞與路徑(這裡沒有標頭與上傳內容,需要的話請隨後加入)
  • 31 狀態碼
  • 32 回傳內容
  • 37 生成 Consumer.HelloApiClient 實例
  • 38 呼叫 SayHello 方法
如果單元測試通過,在 Contract 目錄將會有如 <Consumer>-<Provider>.json 檔名的合約。

接著是 Provider 這方的程式,也是依行號特別說明:

  • 6 三大功能中的第一個
  • 10 保留給 PactNet 用,規範路徑、動詞,回傳不重要(照抄就好了)
  • 17 整合測試用,請參考這篇

最後重頭戲在 Provider.Tests 專案,也要引入 PactNet 套件,再加上 PactNet.Output.Xunit。測試程式的部份,UnitTest2.cs 是為了驗證合約是否履行:

  • 20 單純用來確認受測站台是否服務,這說來有點話長,由於 PactNet 目前還沒有支援前面提到微軟最新的整合測試,只好另外用程式開。不過那不是本文重點,讀者手動也是可以的。
  • 26 一樣是取得受測站台的網址
  • 31 與 Xunit 搭配必備
  • 35 找到合約
  • 39 表明我是 Provider 一方,以及受測站台所在
  • 40 上傳合約
  • 41 上傳路徑,就是之前提到保留給 PactNet 用的
  • 42 驗證合約

如此一來,開發人員除了寫自己的單元測試之外,也可以執行這個額外的「合約驗證」,了解完成度。如果是部份完成的情況,打開合約來看:

假設 20~33, 34~47 這兩段都還沒履行,6~19 已完成功能,所以整份合約的驗證失敗,那要怎麼驗證完成部份有沒有符合合約呢?很簡單,把未完成的部份刪除,另存新檔,並且驗證時指定新檔就可以囉。

回到過去 - 避免 PactNet 整合測試的困擾
組件版本自動取號,與-swaggerdoc-上的呈現
 

評論

尚無評論
已經注冊了? 這裡登入
Guest
2025/06/09, 週一

Captcha 圖像