Go言語のテストでlogの内容に想定した文字列が含まれるかどうかチェックする方法のメモ書きです。
下記サイトを参考にさせて頂きましたが、自分のテストしたい関数だと上手くいかなかったので、少しだけ改修しています。
https://zenn.dev/glassonion1/articles/8ac939208bd455
テストする関数
今回テストする関数の内容。
// テスト対象の関数
func Print (moji1 string, moji2 string) error {
fmt.Print(moji1)
fmt.Print(moji2)
return nil
}
テストコードで使用する標準出力を取得する関数
テスト対象の関数を実行し、出力された標準出力の内容を出力する処理を書いています。
テスト対象の関数を実行する
の部分の関数を任意の関数に書き換えることで、他のテストにも応用できます。
testExec
関数の引数で、テスト対象関数の引数を取得します。
func testExec(t *testing.T, u moji1 string, moji2 string) string {
t.Helper()
// 既存のStdoutを退避する
orgStdout := os.Stdout
defer func() {
// 出力先を元に戻す
os.Stdout = orgStdout
}()
// パイプの作成(r: Reader, w: Writer)
r, w, _ := os.Pipe()
// Stdoutの出力先をパイプのwriterに変更する
os.Stdout = w
// テスト対象の関数を実行する
if err := Print(moji1, moji1); err != nil {
t.Fatalf("想定外のエラー: %v", err)
}
// Writerをクローズする
// Writerオブジェクトはクローズするまで処理をブロックするので注意
w.Close()
// Bufferに書き込こまれた内容を読み出す
var buf bytes.Buffer
if _, err := buf.ReadFrom(r); err != nil {
t.Fatalf("failed to read buf: %v", err)
}
// 文字列を取得する
return strings.TrimRight(buf.String(), "\n")
}
テストの実装
上記で作成したtestExec
関数をテストコード上で呼び出します。
testExec
関数の実行結果に標準出力の内容が格納されています。
// テスト関数
func TestPrint(t *testing.T) {
// テスト対象の関数が出力した文字列を取得する
moji1 := "hoge"
moji2 := "fuga"
result := testExec(t, moji1, moji2)
// 期待されたログが出力されていることを確認
if !strings.Contains(result, "hoge") {
t.Errorf("期待される文字列が出力されませんでした")
}
// 期待されたログが出力されていることを確認
if !strings.Contains(result, "fuga") {
t.Errorf("期待される文字列が出力されませんでした")
}
}