スキップしてメイン コンテンツに移動

Goテスト入門:実践と品質

Goテスト入門:実践と品質

Go実践でのテスト入門

Go言語は標準ライブラリに testing パッケージを備えており、テストを書くことが非常に簡単です。まずは go test コマンドを実行して、テストが走る環境を整えましょう。テストファイルは *_test.go という名前で作成し、関数名は TestXxx で始める必要があります。これにより、Goのビルドツールが自動的にテストを検出します。

テスト入門としては、まず簡単な関数を作り、期待値と実際の値を t.Errorf で比較します。失敗した場合にエラーメッセージを出力することで、何が問題かをすぐに把握できます。

testingパッケージの基本

testingパッケージは *testing.T 型を引数に取る関数をテストケースとして扱います。t.Run を使うとサブテストを作成でき、テストの粒度を細かく管理できます。サブテストは並列実行も可能で、t.Parallel() を呼び出すだけで実行されます。

また、テストの前後に共通処理を入れたい場合は TestMain を定義します。TestMain(m *testing.M) はテスト全体のセットアップとクリーンアップを行うために使われ、m.Run() で実際のテストを実行します。

TestMainとt.Runでのテスト構造

以下は TestMain と t.Run を組み合わせたサンプルです。

package main

import (
    "os"
    "testing"
)

func TestMain(m *testing.M) {
    // テスト前のセットアップ
    initDB()
    code := m.Run()
    // テスト後のクリーンアップ
    closeDB()
    os.Exit(code)
}

func TestExample(t *testing.T) {
    t.Run("正常系", func(t *testing.T) {
        result := add(1, 2)
        if result != 3 {
            t.Errorf("期待値 3 だが got %d", result)
        }
    })
    t.Run("異常系", func(t *testing.T) {
        result := add(-1, -2)
        if result != -3 {
            t.Errorf("期待値 -3 だが got %d", result)
        }
    })
}

この構造により、テストの前後に共通処理をまとめつつ、個別のケースをサブテストで分離できます。

テーブル駆動テストとExample

テーブル駆動テストは、入力と期待値をテーブル(スライス)にまとめてループで実行する手法です。コードの重複を減らし、テストケースを追加しやすくします。

func TestAdd(t *testing.T) {
    tests := []struct{
        name string
        a, b int
        want int
    }{
        {"正の数", 1, 2, 3},
        {"負の数", -1, -2, -3},
        {"ゼロ", 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.Errorf("add(%d,%d) = %d; want %d", tt.a, tt.b, got, tt.want)
            }
        })
    }
}

さらに、Example 関数を使うと、ドキュメントコメントと実行結果を自動で検証できます。go test が実行時に期待される出力と実際の出力を比較し、ドキュメントの正確性を保証します。

func ExampleAdd() {
    fmt.Println(add(1, 2))
    // Output: 3
}

カバレッジとベンチマークで品質を測る

テストだけでなく、コードのカバレッジを確認することで、未テスト領域を可視化できます。go test -coverprofile=coverage.out でプロファイルを生成し、go tool cover -html=coverage.out で可視化します。

また、ベンチマークテストは func BenchmarkXxx(b *testing.B) で書き、go test -bench=. で実行します。ベンチマークはパフォーマンスのボトルネックを特定し、品質向上に直結します。

総合的に見ると、Go実践におけるテスト入門から始め、testingパッケージの機能を駆使し、TestMainやt.Runで構造化し、テーブル駆動テストとExampleで可読性とドキュメント性を高め、最後にカバレッジとベンチマークで品質を定量的に測定する流れが理想的です。

この記事はAIによって作成されました。

コメント