11
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

はじめに

Goのテストは標準機能が強い一方で、実務では次に詰まりやすいです。

  • テストを書いたのに壊れやすい
  • モックが増えて何を担保しているか分からない
  • integrationテストが遅くて回らない

この記事は「理想論」ではなく、チームで回る最小ルールをテンプレとしてまとめます。

先に結論 最小のテスト方針

  • unit は純粋関数と境界の分岐を厚くする
  • integration はDBや外部I/Oとの契約を薄く広く取る
  • 遅いテストは毎回回さないが、CIでは必ず回す
  • テーブル駆動で増やしやすくする

テーブル駆動のテンプレ

func TestAdd(t *testing.T) {
    tests := []struct {
        name string
        a, b int
        want int
    }{
        {"ok", 1, 2, 3},
        {"zero", 0, 0, 0},
    }
    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            if got := Add(tt.a, tt.b); got != tt.want {
                t.Fatalf("got=%d want=%d", got, tt.want)
            }
        })
    }
}

unit と integration の線引き

  • unit
    • 入力と出力が明確で、外部依存がない
    • 例: バリデーション、変換、状態遷移
  • integration
    • DBやHTTPなど、外部との契約を確かめる
    • 例: repository層、migration、HTTPハンドラ

線引きが曖昧だと、遅いテストが増えて運用が止まります。

失敗しにくいテストのコツ

  • 時刻や乱数は注入する
  • グローバル状態を持たない
  • 並行処理を含むテストは待ち合わせを明示する
  • エラー型は文字列ではなく errors.Is / As で検証する

CI運用テンプレ

  • 速いテスト
    • プルリクごとに必須
  • integration
    • mainブランチ、夜間、または変更があったときだけ必須
  • カバレッジ
    • 数字を目的化しない。壊れやすい境界を優先する

レビュー用チェックリスト

  • テストが何を守っているか(契約)が読める
  • 文字列比較ではなく errors.Is / As を使っている
  • テーブル駆動でケース追加が容易
  • 時刻や乱数が固定または注入されている
  • integrationテストの起動条件が運用として決まっている
11
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?