pockestrap

Programmer's memo

graphql-coverage をリリースした

こんにちは。 id:Pocke です。

graphql-coverage という gem をリリースしました。

github.com

なにこれ

GraphQL-Ruby を使っているときに、テストがすべてのフィールドを網羅して呼んでいることを検査するための gem です。

モチベーション

私は GraphQL-Ruby を使って GraphQL サーバーを実装するときに、テストからはすべてのフィールドを呼ぶようなルールで開発をしています。ですがこれを強制する良いツールはありませんでした。そのためフィールドにテストが書かれていることを開発者自身が確認する必要がありました。

「SimpleCovのようなカバレッジ測定ツールを使えば解決するのでは?」と思う方もいるかもしれません。ですが GraphQL-Ruby の場合は単純なコードカバレッジの測定ではこの問題は解決しません。なぜならば GraphQL-Ruby ではメソッドを定義しない形でのフィールド定義も行えるためです。

# `id` メソッドは type 用のクラスに定義されていなくても良い
field :id, String, null: false

そのため、単純なカバレッジ測定ではこの問題を解決できませんでした。

graphql-coverage とは

graphql-coverage を使うとこの問題を解決できます。

graphql-coverage は GraphQL のフィールド定義に特化したカバレッジ測定ツールです。RSpec などのテストに組み込んで使うことを想定しています。

これを組み込んでテストを実行すると、次のような出力が得られます。

# カバレッジが100%の場合

All fields are covered
100 / 100 fields covered (100.00%)
# 呼ばれていないフィールドがある場合
There are uncovered fields
98 / 100 fields covered (98.00%)
Missing fields:
  Query.bar
  User.name

そしてテストで呼ばれていないフィールドがある場合には、そのテストが異常終了するようになっています(異常終了させずに計測だけすることもできます)。

使い方

使い方は README を参照してください。

https://github.com/pocke/graphql-coverage#usage

注意点として、parallel_tests や CircleCI の parallelism を使ってテストを並列化している場合は使い方が少し変わります。これらの場合はテストのプロセスではカバレッジ結果を一旦ファイルに書き出し、その後のステップで書き出したファイルを1つにまとめてカバレッジを計測します。

設定

GraphQL::Coverage.ignored_fieldsカバレッジ測定から除きたいフィールドを設定できます。

これは Relay が自動的につくるフィールドを測定から除くために実装しました。Relay Connection の Type を作ると、edgesなどのフィールドが自動的に生成されます。ですがこれらのフィールドをテストする必然性はあまりありません。これらのフィールドの影響を除くには、ignored_fieldsを設定します。

その他にも、何らかの事情でテストが書けていないフィールドを指定することもできるでしょう。

詳しい設定方法や Relay の生成するフィールドを除くおすすめの設定値は README を参照してください。

https://github.com/pocke/graphql-coverage#configuration

実際に使ってみて

GraphQL-Ruby を使って開発をしているプロジェクトで使ってみたところ、実際にテストが漏れているフィールドを1件見つけることができました。まだ開発が始まって間もないプロジェクトであるため漏れは多くありませんでしたが、問題を発見できたため価値はあると思います。

graphql-coverage の動作確認の意味が強かったためまだ CI 上で1回走らせたところですが、今後本格的に導入を進めようと思っています。

今後

今後の機能追加予定として、Union Type に含まれる型がすべて返されていることをテストする仕組みを optional で入れようと考えています。pocke/graphql-coverage#3

また CircleCI などでのより具体的な設定例をリポジトリ内に置こうと思っています。 複数プロセス上で計測をしようとすると設定が多少複雑になるため、より設定が分かりやすくなることを目指しています。


graphql-coverage gem の紹介でした。ぜひ試してみていただけると幸いです。