Unit Test

  • 小型測試帶來優秀的代碼質量、良好的異常處理、優雅的錯誤報告;大中型測試會帶來整體產品質量和數據驗證。
  • 不同類型的項目,對測試的需求不同,總體上有一個經驗法則,即70/20/10原則:70%是小型測試,20%是中型測試,10%是大型測試。
  • 如果一個項目是面向用戶的,擁有較高的集成度,或者用戶接口比較複雜,他們就應該有更多的中型和大型測試;如果是基礎平台或者面向數據的項目,例如索引或網絡爬蟲,則最好有大量的小型測試,中型測試和大型測試的數量要求會少很多。 unit_test

"自動化實現的,用於驗證一個單獨函數或獨立功能模塊的代碼是否按照預期工作,著重於典型功能性問題、數據損壞、錯誤條件和大小差一錯誤(譯註:大小差一(off-by-one)錯誤是一類常見的程序設計錯誤)等方面的驗證" - 《Google軟件測試之道》

  • 正確的對容器內服務進行健康檢測,避免unittest 啟動時候資源還未 ready
  • 應該交由 app 自己來初始化數據,比如 db 的scheme,初始的 sql 數據等,為了滿足測試的一致性,在每次結束後,都會銷毀容器 unit_test_2 unit_test_3
  • 在單元測試開始前,導入封裝好的 testing 庫,方便啟動和銷毀容器。
  • 對於 service 的單元測試,使用 gomock 等庫把 dao mock 掉,所以在設計包的時候,應該面向抽象編程。
  • 在本地執行依賴 Docker,在 CI 環境裡執行Unittest,需要考慮在物理機裡的 Docker 網絡,或者在 Docker 裡再次啟動一個 Docker unit_test_4

單元測試的基本要求:

基於 docker-compose 實現跨平台跨語言環境的容器依賴管理方案,以解決運行 unittest 場景下的(mysql, redis, mc)容器依賴問題:

  • 本地安裝 Docker。
  • 無侵入式的環境初始化。
  • 快速重置環境。
  • 隨時隨地運行(不依賴外部服務)。
  • 語義式 API 聲明資源。
  • 真實外部依賴,而非 in-process 模擬。

Using Subtests and Sub-benchmarks

https://go.dev/blog/subtests

func TestFoo(t *testing.T) {
    // <setup code>
    t.Run("A=1", func(t *testing.T) { ... })
    t.Run("A=2", func(t *testing.T) { ... })
    t.Run("B=1", func(t *testing.T) {
        if !test(foo{B:1}) {
            t.Fail()
        }
    })
    // <tear-down code>
}

Run a group of tests in parallel The above semantics allows for running a group of tests in parallel with each other but not with other parallel tests:

func TestGroupedParallel(t *testing.T) {
    for _, tc := range testCases {
        tc := tc // capture range variable
        t.Run(tc.Name, func(t *testing.T) {
            t.Parallel()
            if got := foo(tc.in); got != tc.out {
                t.Errorf("got %v; want %v", got, tc.out)
            }
            ...
        })
    }
}

Cleaning up after a group of parallel tests In the previous example we used the semantics to wait on a group of parallel tests to complete before commencing other tests. The same technique can be used to clean up after a group of parallel tests that share common resources:

func TestTeardownParallel(t *testing.T) {
    // <setup code>
    // This Run will not return until its parallel subtests complete.
    t.Run("group", func(t *testing.T) {
        t.Run("Test1", parallelTest1)
        t.Run("Test2", parallelTest2)
        t.Run("Test3", parallelTest3)
    })
    // <tear-down code>
}

利用 go 官方提供的: Subtests + Gomock 完成整個單元測試。

  • /api
    • 比較適合進行集成測試,直接測試 API,使用 API 測試框架(例如: yapi),維護大量業務測試 case。
    • Yapi
  • /data
    • docker compose 把底層基礎設施真實模擬,因此可以去掉 infra 的抽象層。
  • /biz
    • 依賴 repo、rpc client,利用 gomock 模擬 interface 的實現,來進行業務單元測試。
  • /service
    • 依賴 biz 的實現,構建 biz 的實現類傳入,進行單元測試。

基於 git branch 進行 feature 開發,本地進行 unittest,之後提交 gitlab merge request 進行 CI 的單元測試,基於 feature branch 進行構建,完成功能測試,之後合併 master,進行集成測試,上線後進行回歸測試。

Reference

© Kimi Tsai all right reserved.            Updated : 2023-07-12 09:04:53

results matching ""

    No results matching ""

    results matching ""

      No results matching ""