🥇

【完成版】Goのコード生成を利用してユニットテストを書く方法

2022/07/29に公開

完成コード

https://github.com/nishisuke/example-go-generate-tests

前回

https://zenn.dev/nishisuke/articles/go-generate-unit-test

前回では以下の課題が残ったままでした。

  • モックのDI
  • gotestsをモックが使用できるように生成されてテストテンプレートを編集する必要がある。
  • errが返ってほしいとき、具体的に何のエラーが返ったかのテスト

今回はこれを解決し、完成版として紹介します。

環境

  • macOSMonterey 12.2.1
  • x86_64
  • go1.18

準備

go mod init sample
go get -u github.com/cweill/gotests/...
go install github.com/golang/mock/mockgen@latest
go install github.com/sanposhiho/gomockhandler@latest

やっていること

  • gotestsでテストコードのテンプレートを生成
  • gomockhandlerでモックの生成
  • wireでDI

この3つが go generate ./... 一つで行われます。

説明

これがテスト対象のコードです。

https://github.com/nishisuke/example-go-generate-tests/blob/main/internal/usecases/user_usecase.go

gotestsでテストコードのテンプレートを生成

テスト対象のファイルに以下を記述。

//go:generate gotests -w -all $GOFILE

gomockhandlerでモックを生成

モックが必要なファイルに以下を記述。

//go:generate gomockhandler -config=$EXAMPLE_TESTS_ROOT/gomockhandler.json -source=$GOFILE -destination=mock_$GOPACKAGE/mock_$GOFILE -package=mock_$GOPACKAGE

gomockhandler.jsonのパスを指定しやすいように、レポジトリのルートを環境変数 $EXAMPLE_TESTS_ROOT に指定します

wireについて

wireによってこのコードが生成されます。

https://github.com/nishisuke/example-go-generate-tests/blob/main/internal/usecases/wire_gen.go

重要なのはこの二つの関数を生成してくれる点です。
func NewUserUsecase() UserUsecase
func NewMockUserUsecase(m *mock_usecases.MockUserRepo) UserUsecase

wireについて一から説明すると、記事がひとつ出来上がるので割愛します。
公式のドキュメントがかなり良くできています。おすすめ。

生成されるテストテンプレート

go generate ./... によりこのコードが生成されます。
https://github.com/nishisuke/example-go-generate-tests/blob/03146aceab105681d15b81f64eed6a3886723710/internal/usecases/user_usecase_test.go

人間が必要なことは TODO: Add test cases. に書かれている部分を編集するだけです。
テストケースだけに集中できてとても良いですね!

テストケースの追加

https://github.com/nishisuke/example-go-generate-tests/blob/main/internal/usecases/user_usecase_test.go#L28-L38

テストテンプレートのカスタマイズ

gotestsには生成されるテストコードをカスタマイズする機能があります。

このディレクトリのファイルを全て持ってきて
自分のプロジェクトに配置します。
配置先のディレクトリを環境変数 $GOTESTS_TEMPLATE_DIR に指定します。

注意点としてはgotestsレポジトリのデフォルトブランチではなく、v1.6.0 から持ってくることです。

あとは持ってきたファイルをカスタマイズしましょう。
多くの場合function.tmplを編集すれば事足りると感じました。

カスタマイズ例
https://github.com/nishisuke/example-go-generate-tests/blob/main/testtmpls/function.tmpl

終わりに

今回は前回の課題を解決し、完成版としました。
個人的には今後も使えそうなものができたため、課題を見つけたらブラッシュアップしようと思います。

Discussion