使用 OpenAPI 與 TypeScript 進行契約測試
原文由 Alex O'Callaghan 于 發布,訂閱此部落格
在擁有多個軟體開發團隊協作的大型組織中,系統之間的跨邊界互動往往是故障發生的關鍵點。建立定義清晰的 API 並就其運作方式達成共識,有助於大幅減少整合錯誤。透過 OpenAPI 與 TypeScript 這類工具,就能提供可藉由自動化測試來驗證的清晰定義。
情境
想像一個情境:一個工程團隊正在實作 Python 後端服務,同時與另一個負責開發網頁應用程式的團隊緊密合作,該應用程式將使用此服務來實現部分功能。雙方已就系統需求與 API 的運作方式達成共識,但隨著時間推移,越來越多團隊成為這個服務的消費者,功能不斷被新增與修改,錯誤也隨之產生。
我們該如何加入自動化測試來協助捕捉整合問題?端對端整合測試是個不錯的想法,但也有一些缺點。要啟動整個技術堆疊,需要在工具選擇上達成一致,而且測試執行起來可能很慢。再加上多個消費者,這類建置需要投入大量的工程時間與心力來維護。
契約測試,也就是驗證對服務發出的請求是否回傳預期的狀態碼與資料結構,能在技術選型上只需最低程度共識的情況下,協助捕捉未被察覺的錯誤與破壞性變更。
使用 OpenAPI 與 TypeScript
OpenAPI 是用於描述 API 的熱門標準,相容於 JSON Schema 並支援眾多框架。TypeScript 則是為 JavaScript 應用程式導入靜態型別的熱門選擇。
當後端服務提供了 OpenAPI 的 YAML 或 JSON 綱要,前端應用程式就能使用 openapi-typescript 來為該服務的 API 產生型別定義:
$ npx openapi-typescript https://service.dev/openapi.json -o ./schema.d.ts這些型別可以在發送請求與處理回應時手動引用,或搭配像 openapi-fetch 這類客戶端來提供具型別安全的請求。
執行 tsc --noEmit 即可進行型別檢查,找出任何問題。
與 CI 整合
在前端專案中,做法相當直觀:新增一個 CI 步驟,從正式環境的服務拉取最新的 OpenAPI 規格,用 openapi-typescript 產生型別定義,然後以 tsc 執行型別檢查。
至於後端專案,如果你的 CI 平台有支援,你可以在消費者的專案中觸發管線。舉例來說,使用 GitLab CI's multi-project pipelines:
# Backend service
## Generate `openapi.json` and store as an artifact
generate-openapi:
stage: test
artifacts:
paths:
- openapi.json
when: always
script:
- make generate-openapi
## Trigger a downstream pipeline in consumer
validate-openapi:
stage: test
needs: ["generate-openapi"]
variables:
UPSTREAM_REF: $CI_MERGE_REQUEST_REF_PATH
trigger:
project: path/to/consumer
branch: master
strategy: depend
# Frontend service
## Generate types from `openapi.json` schema and use `tsc` to type check
validate-openapi:
stage: test
needs:
- project: path/to/service
job: generate-openapi
ref: $UPSTREAM_REF
artifacts: true
rules:
- if: $CI_PIPELINE_SOURCE == "pipeline"
script:
- npx openapi-typescript openapi.json --output path/to/schema.ts
- tsc --noEmit如此一來,後端服務的任何變更,現在都會在所有消費者應用程式中被驗證是否有破壞性變更。
總結
在理想的世界裡,你會擁有一支能完整維護自身技術堆疊的跨職能團隊。在大型組織中,情況往往並非如此,跨團隊協作的協調也充滿挑戰。良好的溝通固然是關鍵,但自動化的契約測試能協助捕捉那些原本會流入正式環境的問題。即使是由單一團隊維護的單一服務與單一消費者,隨著系統複雜度提升,API 的變更也可能變得難以推斷。OpenAPI 與 TypeScript 是提升開發體驗的絕佳工具,能以相當簡單的方式,在系統之間建立起穩固且可測試的契約。
隨機一篇部落格
留言
登入後參與討論