Querier

GraphQL(gqlgen)サーバーのE2Eテストをgenqlientを使ってストレスなく書ける環境を作る

2023.02.07に公開 | 2023.02.10に更新

管理画面の構築もWeb上で完結
エンジニアのためのローコードツール

Querierについて詳しく見る

こんにちは、クエリアの吉田です。
現在クエリアでは、gqlgenを使ってGraphQLサーバーを構築しています。そのGraphQLサーバーでE2Eテストを書く際にgenqlientというライブラリがとても便利だったの紹介したいと思います。

スタートアップにおけるテストの課題

クエリアはスタートアップ企業です。スタートアップ企業であればテストをどこまで書くかというのは永遠の課題だと思います。中にはテストを一切書かないという意思決定をしている企業も少なくないと思います。

クエリアもクリティカルな部分だけはE2Eテストを書き、それ以外は手動で動作確認をするにとどめていました。
しかし、UIをドラッグ・アンド・ドロップで構築できたり、様々なAPIと連携してロジックを柔軟に構築できるように設計されたサービスの都合上、コードが複雑化し、お客様が増えれば増えるほど新機能開発もリファクタリングもしづらくなっていってしまいました。

そこで、できるだけスピードを落とさずに、ストレスなくE2Eテストを書ける環境を作ろうと思い、テスト環境の構築に着手し始めました。

GraphQLのクライアントを自動生成してくれるgenqlient

そこで見つけたのがgenqlientというライブラリです。このライブラリはGarphQLのクエリを書いておくと、クライアントコードを自動生成してくれるというものです。

それでは基本的な使い方を紹介していきます。
まずは、以下のコマンドでgenqlientの設定ファイルを生成します。(カレントディレクトリに graphql.schema ファイルがないとエラーになってしましますが、設定ファイルは生成されているので気にしないで大丈夫です)

$ go get github.com/Khan/genqlient
$ go run github.com/Khan/genqlient --init

次に、 genqlient.schema ファイルを作成します。(こちらはinitコマンドがうまくいけば自動で生成されているものです)
作成した genqlient.schema に以下のようにテストで使用したいクエリを書きます。

query getUser($userId: Int!) {
  user(userId: $userId) {
    name
  }
}

クエリを書いたら、以下のコマンドでクライアントコードを自動生成します。

$ go run github.com/Khan/genqlient

データベースとのコネクションを準備する

クエリアではdockertestを使ってコンテナを立ち上げてコネクションを確立しています。dockertestに関する詳しい解説はこちらの記事をご覧ください。

生成されたクライアントを使ってテストを書く

今回はhttptestで立ち上げたサーバーに対してリクエストを送っています。

srv := httptest.NewServer(server.New()) // httptest.NewServerの引数にはアプリケーションで使っているhttp.Handlerを渡す
cleint := graphql.NewClient(srv.URL+"/graphql", http.DefaultClient)
resp, err := getUser(context.Background(), client, 1)
user := resp.User
assert.NoError(t, err)
assert.Equal(t, user.Id, 1)

genqlientを使いこなすためのTips

Fragmentを使ってテストを追加しやすくする

毎回リクエスト内に型を書くのは面倒ですよね。genqlientはFragmentにも対応しており、一度Fragmentを定義しておけば、次回からはそれを使い回せばいい状態にすることができます。

例えば、以下のようなクエリがあったとします。

fragment User on User {
  id
  name
  email
  gender
}

mutation updateUserName($updateUserNameInput: updateUserNameInput!) {
  updateUserName(input: $updateUserNameInput) {
    user {
      ...User
    }
  }
}

ここに updateUserEmail というミューテーションのテストを追加したいときは、以下のように書けばいいだけです。これでだいぶ楽に新しいテストを書きやすくなりました。

mutation updateUserEmail($updateUserEmailInput: updateUserEmailInput!) {
  updateUserEmail(input: $updateUserEmailInput) {
    user {
      ...User
    }
  }
}

認証トークンを詰めてリクエストする

genqlientを使って生成したクライアントに認証トークンを詰めるためには、Transportを上書きします。
まずは、以下のような独自のTransportを定義します。

type customTransport struct {
	wrapped http.RoundTripper
}

func (t *customTransport) RoundTrip(req *http.Request) (*http.Response, error) {
	req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", authToken))
	req.Header.Set("Content-Type", "application/json")
	return t.wrapped.RoundTrip(req)
}

定義したTransportを使ったHTTP Clientを作成し、それをGraphQLクライアントの生成に使ってあげれば完了です。

hc := &http.Client{
  Transport: &customTransport{
    wrapped: http.DefaultTransport,
  },
}
cleint := graphql.NewClient(srv.URL+"/graphql", hc)

オプショナルなフィールドをポインタにする

genqlientはオプショナルなフィールドは基本的にポインタになりません。しかし、gqlgenを使っている場合、gqlgenではオプショナルなフィールドはポインタになるため、ポインタにした方がテストしやすいなと思うことがあります。
そんなときは、最初に生成された genqlient.yaml を以下のように指定してあげるとポインタにすることができます。

schema: ./graph/schema.graphqls
operations:
- ./e2e/genqlient.graphql
generated: ./e2e/generated.go

# optionalを value から pointer に変える
optional: pointer

最後に

今回はgenqlientというライブラリを使ってGraphQLクライアントを自動生成し、E2Eテストを書く方法を紹介しました。
クエリやミューテーションを開発した後に、クライアントを自動で生成して値を詰めて実行するだけであればかなり気軽にテストを書くことができます。
ぜひGraphQLを採用している企業の方々は参考にしてみてください。

また、クエリアはGraphQLなど様々なAPIと連携して、社内向けの管理画面やツールを構築できるローコードツールの『Querier』を開発しています。無料トライアルも実施しておりますので、もし気になる方がいればサイトを覗いてみてください。

最新の記事

【告知】値の参照時の仕様変更のお知らせ

このたび2024年11月11日に値の参照に関する仕様変更を予定しておりますので詳細について報告いたします。

more

管理画面の構築もWeb上で完結
エンジニアのためのローコードツール

Querierについて詳しく見る