Go 言語で ユニットテストを作成する(組み込み機能)

はじめに

当エントリは以下のエントリの続きとなっています。

ここまででアプリケーションコードの開発が終わりました。

ここからはテストコードの追加を行っていきます。

開発中にコードをテストすることによって、変更を加えたときに組み込んでしまうバグを早期に検知することができます。

作成済みの Hello 関数をテストしてみます。

Go 言語の組み込みユニットテスト機能を使って簡単にテストできます。

コーディング開始!

1. greetings ディレクトリにテストコードを追加

greetings_test.go というファイルを作成します。

ファイル名の最後が _test.go で終わるコードを作成すると、 go test コマンド実行時にテストを含むコードとして扱われます。

2. greetings_test.go ファイルに以下のコードを記述し保存

package greetings

import (
    "regexp"
    "testing"
)

func TestHelloName(t *testing.T) {
    name := "genzouw"
    want := regexp.MustCompile(`\b` + name + `\b`)
    msg, err := Hello("genzouw")
    if !want.MatchString(msg) || err != nil {
        t.Fatalf(`Hello("genzouw") = %q, %v, want match for %#q, nil`, msg, err, want)
    }
}

func TestHelloEmpty(t *testing.T) {
    msg, err := Hello("")
    if msg != "" || err == nil {
        t.Fatalf(`Hello("") = %q, %v, want "", error`, msg, err)
    }
}

コード解説

かんたんに解説します。

  • テスト対象コードと一緒のパッケージにテストコードを配置しています。
  • greetings.Hello 関数をテストするための関数を 2 つ作成しました。
    • テスト関数の名前は TestXxx という命名規則となっています。
    • テスト関数名の Xxx の部分にはテストの内容がわかる名前をつけます。
    • テスト関数は testing.T 型の変数のポインタを受け取ります。
  • 2 つのテスト関数の実装は以下のとおりです。
    • TestHelloName
    • Hello 関数に名前を渡して呼び出し、妥当なメッセージが返却されることを確認しています。
    • 名前を渡して妥当なメッセージが返却されることを確認しています。
    • 返却されたメッセージが予期しないものだったり、エラーが返却された場合には t パラメータの Fatailf メソッドを呼び出します。
    • TestHelloEmty
    • Hello 関数に空文字列を渡して呼び出し、エラーが返却されることを確認しています。
    • エラーが返却されなかった場合には t パラメータの Fatailf メソッドを呼び出します。

3. greetings ディレクトリで go test コマンドを実行

go test コマンドはテストコード( ファイル名の末尾が _test.go となっているファイル )内のテスト関数を実行します。

( -v フラグを付与して、より詳細なテスト実行メッセージを表示させることもできます。 )

$ ls
go.mod  greetings.go  greetings_test.go

$ go test
PASS
ok      genzouw/greetings       0.087s

$ go test -v
=== RUN   TestHelloName
--- PASS: TestHelloName (0.00s)
=== RUN   TestHelloEmpty
--- PASS: TestHelloEmpty (0.00s)
PASS
ok      genzouw/greetings       0.083s

4. greetings.Hello 関数を壊し、テストが失敗することを確認

TestHelloName テストコードは Hello 関数のパラメータに指定した名前が、返却されたメッセージに含まれていることをチェックしています。

テストが失敗することを確認するため、 パラメータに指定した名前が返却されたメッセージに含まれなくなるように greetings.Hello 関数を変更してみましょう。

greetings/greetings.go コードを変更してみましょう。

$ git diff
diff --git greetings.go greetings.go
index 042e0f4..1bc5a73 100644
--- greetings.go
+++ greetings.go
@@ -12,7 +12,8 @@ func Hello(name string) (string, error) {
                return "", errors.New("empty name")
        }

-       message := fmt.Sprintf(randomFormat(), name)
+       // message := fmt.Sprintf(randomFormat(), name)
+       message := fmt.Sprintf(randomFormat())

        return message, nil
 }

5. greetings ディレクトリで go test コマンドを実行

-v オプション無しで go test コア m ンドを実行してみます。

出力結果には、失敗したテストに関する内容だけが含まれています。大量のテストを実行する場合に便利でしょう。

TestHelloName テストが失敗していますが、 TestHelloEmpty テストは先程ままパスできました。

$ go test
--- FAIL: TestHelloName (0.00s)
    greetings_test.go:13: Hello("genzouw") = "Hi, %!v(MISSING). Welcome!", <nil>, want match for `\bgenzouw\b`, nil
FAIL
exit status 1
FAIL    genzouw/greetings       0.084s

ひとこと

次回のエントリでようやく今回のシリーズも最後になります。

今まで作成したコードをコンパイルし、ローカル環境にインストール してみます。

Posted by genzouw