アクトインディ開発者ブログ

子供とお出かけ情報「いこーよ」を運営する、アクトインディ株式会社の開発者ブログです

CodeBuildのレポート機能を使ってRSpecの結果を見る

morishitaです。

前回のエントリで、CodeBuild 上で RSpec を実行する環境について紹介しました。

tech.actindi.net

その中で RSpec の結果を CodeBuild のレポートで確認できるようにしてみたらなかなか良かったのでそれについて紹介します。

CodeBuild のテストレポート機能とは

1年ほど前に CodeBuild に追加された機能で、CodeBuild で実行したテスティングフレームワークの実行結果を管理し、見やすく表示する機能です。

例えば、複数回のテストの実行時間やエラー数をグラフにして表示できます。それを見れば、テストケースが増えてきたとか、実行時間がどれくらいとか傾向がわかります。

f:id:HeRo:20201222183141p:plain
テスト結果トレンド

また、1回のテスト実行結果を次のように表示できます。

f:id:HeRo:20201222183235p:plain
1回のテスト結果

主に Java 系のテスティングフレームワークをサポートしていますが、RSpec でも利用可能です。

RSpec の結果を表示できるようにする

大前提として CodeBuild 上で RSpec を実行しているということが必要となります。
その上でこのレポート機能を利用するためにすることは次の2つです。

  1. sj26/rspec_junit_formatter 導入して RSpec の結果を JUnit 形式でも出力する
  2. buildspec.yml にレポート設定を追加する

これらをもう少し詳しく説明します。

RSpec の結果を JUnit 形式でも出力する

rspec_junit_formatterは RSpec の結果フォーマッタの1つです。RSpec の結果を JUnitXML 形式で出力できます。 JUnitXML は CodeBuild のレポート機能でサポートされているので表示できるようになるというわけです。
RSpec では複数の形式で結果出力可能なので、他の形式での出力も必要なら、そちらはそのままにして JUnitXML 形式での出力も追加すればいいです。

Rails アプリであれば、まず Gemfilerspec_junit_formatter を追加します。

Gemfile

group :test do
  gem 'rspec'
  gem 'rspec_junit_formatter' # <= 追加
end

そして、spec/spec_helper.rb に次の設定を追加すれば出力されるようになります。

spec/spec_helper.rb

RSpec.configure do |config|
  config.add_formatter('RspecJunitFormatter', 'junit_format/rspec_xml')
end

出力先は任意ですが、できれば結果ファイルだけを保存する専用ディレクトリに分けたほうがいいかと思います。そのほうが buildspec.yml のレポート設定で結果ファイルを指定する際に楽です。

buildspec.yml にレポート設定を追加する

出力した RSpec の結果をレポート機能に読み込ませるために buildspec.yml には次の設定を追加します。

reports:
  rspec:
    files:
      - 'junit_format/*'
    file-format: JUNITXML

files: で結果ファイルを指定するのですが、ファイル名まで指定する必要はありません。junit_format/* のように glob パターンで指定できます。こうすると結果ファイルを出力するディレクトリ以下全部を対象とするようなざっくりした指定が可能です。

結果ファイルが複数でも大丈夫

テストケースが増えてくるとtest-queueなどを使って並行実行してテスト全体の実行時間を短縮することもあるでしょう。並行実行するとテスト結果は各スレッドごとにバラバラに出力されたりします。
CodeBuild のレポート機能は出力結果が複数ファイルに分かれていてもまとめて読み込んでくれます。
前述のように glob パターンにマッチする結果ファイルを全部読み込んでレポートを作成してくれるので自前でマージする必要はありません。

結果の確認

1 回のテストの結果は次のように表示されます。

f:id:HeRo:20201222183358p:plain
テスト結果

テストの総数やエラーの数などがドーナツグラフで表示されます。
レポート時間は複数スレッドで並行実行しているので全スレッドの合計値になっているのか実際よりかなり大きな数字が表示されてしまっています。実際には十数分しかかかっていません。
グラフの下には各テストケースの一覧が表示されます。どのテストで失敗したのかがわかります。
更に、失敗したテストケースを開くと次のような詳細が表示されます。ちょっとモザイクが多いのでわかりにくそうに見えますが、どのように失敗したのかわかります。コード修正に必要な情報はここで得られます。

f:id:HeRo:20201222183442p:plain
failしたテストの結果

CodeBuild のレポート機能を使う前はアーティファクトに含まれるログファイルを開いて確認していました。それに比べるとずっと確認しやすくなりました。

SimpleCov にも対応しているけれど…

CodeBuild のレポート機能はテストレポートだけでなくコードカバレッジレポートもできます。

Ruby でテストのコードカバレッジを計測する場合、simplecovが使われるのではないかと思います。
SimpleCov はデフォルトで JSON 形式の結果ファイル .resultset.json を出力します。CodeBuild のレポート機能はこのファイルをサポートしています。したがって gem や設定の追加は不要です。

CodeBuild の設定ファイル buildspec.xml には次の設定を追加します。

reports:
  simplecov:
    files:
      - 'coverage/.resultset.json'
    file-format: SIMPLECOV

で、レポートはこんな感じです。

f:id:HeRo:20201222183545p:plain
カバレッジレポート

ラインカバレッジとブランチカバレッジが円グラフで表示され、ファイルごとのカバレッジも一覧で表示されます。

残念ながらラインカバレッジは正しく表示されません。
おそらく複数スレッドで並行実行しているためです。
SimpleCov は複数スレッドで実行しても自動的にマージして .resultset.json 1 ファイルに結果をまとめてくれるのですが、一部ファイルの結果が重複して含まれてしまっています。仕方のない仕様なのか、不具合なのか、または設定方法がどこか間違っているのか不明ですが正しくありません(simplecov-htmlsimplecov-jsonでは重複なく正しく結果が出ています)。
なので総コード行数が実際より大きくなって、結果カバレッジが下がっています。実際にはこれよりカバレッジは良いです。
多分、複数スレッドで実行していなければ正しい結果が表示できると思います。

一方で、ブランチカバレッジのほうは正しく結果が表示されています(同じ .resultset.json を読んで表示しているはずですが simplecov-html と同じ結果が出ています)。
ブランチカバレッジはぼっち演算子もブランチ扱いとなります。
ひょっとして nil になるかもと予防的に使っているところも多くテストで全部カバーするのはなかなか難しいですが、もう少し改善できるかなという気がします。

ラインカバレッジが正しくない問題を解決しようと Cobertura XML 形式で結果を出力できるsimplecov-cobertura を試してみました。CodeBuild のカバレッジレポートは Cobertura XML 形式もサポートしているのでもしかすると解決できるのではと思ったのです。
ラインカバレッジを正しく表示できました。が、今度はブランチカバレッジが表示できない…。完全な解決策にはなりませんでした。

ただ、正しく結果が表示できたとしてもカバレッジレポートの方はちょっと機能不足を感じます。
まあ、カバレッジが急に下がってないかを確認するには役立ちます。
しかし、やはりコード上でどこが通っていないのかが見れなくては改善に役立てられません。simplecov-html相当の表示ができるようになるといいのですが…。

まとめ

CodeBuild のレポート機能を Rails アプリケーションで使ってみました。
RSpec のテストレポートは便利です。一方、カバレッジレポートにはコード上でカバレッジを表示する機能が追加されればいいのになぁと思いました。
これが揃えばサードパーティサービスを組み合わせることなくテスト実行からレポーティングまでオールインワンな魅力ある環境となると思います。

最後に

アクトインディではテストを改善し、プロダクトの品質を向上するのが大好きなエンジニアを募集しています。 actindi.net

参考