goldie でAPIテスト Go Golang goldie その1
今回はgoldieというライブラリを使ったGolden testを実装していきます。
Golden Test
Goleden Testとは .golden拡張子のファイルにAPIの結果(jsonなどを)保持しておき、テスト時に出力結果に変更がないかを比較するテスト手法です。
goldie
goldieはGo言語用の Golden Test ライブラリです。 .goldenファイルの生成と比較をしてくれます。
一般的にテストファイルと.goldenファイルは以下のような構成になります。
. ├── main.go ├── test │ ├── testdata │ │ └── TestUsers.golden │ └── user_test.go
APIテスト
Golden Testと goldieについて理解したところでテストを作成していきます。
テストするのはuserを扱う単純なAPIです。
Method | URL | 概要 |
---|---|---|
GET | /users | 全てのユーザーを取得 |
POST | /users | ユーザーを作成 |
まずは上記のうち /users
のテストを行います。
以下がテストコードです。 *FWやDBに依存しているところがありますが見逃してください。
package test_integration import ( ...省略 "github.com/sebdah/goldie/v2" ) func setUp(t *testing.T) *gin.Engine { // TODO change by env conn, err := sql.Open("mysql", "root:@tcp("+os.Getenv("DB_HOST")+":3306)/"+"DB_NAME") if err != nil { t.Fatalf(err.Error()) } tx, err := conn.Begin() if err != nil { t.Fatalf(err.Error()) } infraTx := infrastructure.Tx{ Tx: tx, } userController := controllers.NewUserController(infraTx) _, err = userController.Interactor.UserRepository.Store(domain.User{ ID: 0, FirstName: "firstName", LastName: "lastName", }) if err != nil { t.Fatalf(err.Error()) } r := infrastructure.NewRouter(userController) t.Cleanup(func() { if err := infraTx.RollBack(); err != nil { t.Fatalf("failed RollBack") } }) return r } func TestUsers(t *testing.T) { r := setUp(t) api := "/users" req := httptest.NewRequest(http.MethodGet, api, nil) rec := httptest.NewRecorder() r.ServeHTTP(rec, req) if rec.Code != http.StatusOK { t.Fatal(rec) } ret := regexp.MustCompile(`\"id\":[0-9]+`).ReplaceAllString(rec.Body.String(), `"id":0`) g := goldie.New(t) g.AssertJson(t, t.Name(), ret) }
順に解説していきます。
setUp()
setUp()
関数ではテスト用のDBへの接続とダミーデータの生成を行ない ルーターの構造体(*gin.Engine)を返しています。
テストをトランザクション内で実行している事に注目してください。
// トランザクション開始 tx, err := conn.Begin() // user生成 _, err = userController.Interactor.UserRepository.Store(domain.User{ ID: 0, FirstName: "firstName", LastName: "lastName", }) // 終了後にロールバック t.Cleanup(func() { if err := infraTx.RollBack(); err != nil { t.Fatalf("failed RollBack") } })
テスト毎にロールバックする事で毎回DBを同じ状態からテストする事ができます。
また、本来なら gin
や mysql
に依存しない様に独自の構造体やパッケージに分けるべきですが今回は割愛します。
TestUsers()
つぎに実際のテストコードを見ていきます。
以下のコードでAPIを叩いてレスポンスを取得しています。
api := "/users" req := httptest.NewRequest(http.MethodGet, api, nil) rec := httptest.NewRecorder() r.ServeHTTP(rec, req) if rec.Code != http.StatusOK { t.Fatal(rec) }
次に regexp
パッケージを使用して id
を0
に書き換えています。
これにより取得したすべてのuserのidは "id":0
となります。
これは id
カラムはオートインクリメントになっており、番号が保証されていないからです。
ret := regexp.MustCompile(`\"id\":[0-9]+`).ReplaceAllString(rec.Body.String(), `"id":0`)
最後に goldie
パッケージを使用して比較を行います。
g := goldie.New(t) g.AssertJson(t, t.Name(), ret)
以上がコードの解説となります。
テストの実行
Golden テストの実行は2段階のコマンドにより行われます。
まずは -update
フラグを使用して.goldenファイルを更新します。
go test -v -run ${TARGET} ./test/... -update
これにより、{テスト名}.golden
ファイルにAPIのレスポンスが書き出されます。
[{\"id\":0,\"first_name\":\"firstName\",\"last_name\":\"lastName\",\"full_name\":\"firstName lastName\"}]"
setUp()
関数で生成したuserを取得できました。
以後テストしたい時は -update
フラグを外す事で既存の .goldenファイルと比較を行い、結果が.goldenファイルと異なるか.goldenファイル自体が見つからない場合はエラーを返します。
go test -v ./test/...
以上が goldieを用いたGolden testの流れとなります。 今回はシンプルなGETのAPIを叩いただけでしたが、次回はもう少し実務ベースのテストとgoldenファイルのテクニックを紹介したいと思います。
最後に、 このブログではweb開発について発信していくのでまたご覧頂けると嬉しいです。 最後までお読み頂きありがとうございました。