はじめに
Increments × cyma (Ateam Inc.) Advent Calendar 2020 の8日目は、株式会社エイチーム EC事業本部の@hibiheionが担当します。
業務では主に自転車ECサイトcymaのバックエンドをRailsで書いています。
この記事はGitLabでテストコードをレビューしやすくする機能の紹介です。
ここではプログラミング言語としてRuby(Rails)、テストコードとしてRSpecを使用していますが、言語を限定した機能ではないので他のプログラミング言語でも使用可能です。
背景
みなさんはテストコードの運用で課題に感じていることはありませんか?
私がテストコードの運用で課題に感じていることのひとつにコードレビューの手間があります。
理由はテストコードのレビューではテストコードの書き方だけでなく、プロダクトコードをカバーするテストになっているかを確認する必要があるためです。
確認のためにマージリクエストのプロダクトコードとテストコードを見比べるというやり方をこれまで取っていたのですが、これだと単純に時間がかかりますし、複雑なメソッドだと見落としが起きてしまうこともあります。
こんな手間を減らしてくれるのが今回ご紹介するGitLabのTest Coverage Visualizationという機能です。
Test Coverage Visualizationとは
Test Coverage Visualization | GitLab
一言でいうとマージリクエストの行ごとにテストコードの有無を表示する機能です。
使用例を後でお見せしますが、この機能を使うとテストコードの有無がひと目でわかるようになります。
使用可能なGitLabのバージョン
この機能はバージョン12.9から利用可能ですが、バージョン13.4以降での利用をおすすめします。
理由はバージョン13.4より前のバージョンではパフォーマンスに問題があるためです。
This feature comes with the :coverage_report_view feature flag disabled by default. This feature is disabled due to some performance issues with very large data sets.
Test Coverage Visualization | GitLab(version 12.10)より
使用例
消費税を計算する簡単なプログラムを使って使用例をお見せします。
プロダクトコードはこちらです。
class Item
# 消費税を計算する
# @param [Integer] price 本体価格
# @param [Integer] tax_rate 整数の消費税率
# @param [true,false] is_taxable 課税対象の場合はtrue、そうでない場合はfalse
# @return [Integer] 消費税
def self.calc_tax_price(price, tax_rate, is_taxable)
if is_taxable
(BigDecimal(price.to_s) * BigDecimal((tax_rate * 0.01).to_s)).ceil
else
0
end
end
end
次にテストコードはこちらです。
テストコードは課税対象の場合のテストケースのみ動くようにしています。
require "rails_helper"
RSpec.describe Item, type: :model do
describe ".calc_tax_price?" do
context "課税対象の場合" do
it "消費税を算出する" do
tax = Item.calc_tax_price(10_000, 8, true)
expect(tax).to eq 800
end
end
context "課税対象ではない場合" do
it "0を返す" do
skip "後で書く"
end
end
end
end
この2つのソースコードを含んだマージリクエストを作成します。
マージリクエストを作成した段階ではプロダクトコードは以下のような表示内容です。
これがマージリクエストに対するテストの実行が終わると以下のような表示内容に変わります。
テスト実行前の状態と比べると行番号の右側にバーが増えています。
このバーはその行のテストの有無を表していて、テストで通っている行には緑のバー、テストで通っていない行には茶色のバーを表示しています。
サンプルでは0を返すテストケースが通っていないので0を返す行が茶色のバーになっています。
このようにマージリクエスト上でテストコードの有無がひと目でわかるため、テストコードとプロダクトコードを見比べる手間を減らすことができます。
なお、テストコードの有無以外にもテストコードで確認が必要なところはありますので、テストコードとプロダクトコードを見比べる必要がなくなるわけではありません。
導入方法
以下の手順はGitLab-CIでマージリクエストの作成時にテストが動く状態を前提としています。
Rails + RSpecの環境でTest Coverage Visualizationの導入のために必要な修正は次の3点です。
なお、下記のソースコードではこの機能の導入で修正しない部分は省略しています。
例えば、GemfileでのRSpecの記述などです。
- Gemのsimplecov-coberturaの追加
- SimpleCovにCobertura XML形式のフォーマッターを追加するためのGem
group :test do
gem "simplecov"
gem "simplecov-cobertura"
end
- SimpleCovの設定にCobertura XML形式のフォーマッターを追加
- SimpleCov::Formatter::CoberturaFormatterを使用する
- SimpleCovは複数のフォーマッターを指定できるので、他の形式のカバレッジレポートと同時に使用できる
require "simplecov"
require "simplecov-cobertura"
SimpleCov.start do
formatters = [SimpleCov::Formatter::CoberturaFormatter, SimpleCov::Formatter::HTMLFormatter]
formatter SimpleCov::Formatter::MultiFormatter.new(formatters)
end
- gitlab-ci.ymlにCobertura XML形式のカバレッジレポートの出力を追加
- RSpecの設定にartifactsを追加する
rspec:
artifacts:
paths:
- coverage
reports:
cobertura: coverage/coverage.xml
以上の3点の修正でRails + RSpecの環境に導入できます。
Gitlab-CIですでにテストが動いている状態であればそれほど時間をかけずに導入できると思います。
ここではRubyを使っていますが、Cobertura XML形式のカバレッジレポートを出力できるプログラミング言語であればTest Coverage Visualizationを導入できます。
さいごに
Test Coverage Visualizationを導入した結果、テストコードのレビューの手間を減らすという当初の目的は達成できています。
それだけではなく、レビューを依頼する際にテストコードがないことが明確になるため「テストコードを書かなきゃ」という動機付けになる効果も期待できそうです。
ですので、この機能の導入はチームにテストコードを書く習慣を根付かせていくことにも大いにプラスになると私は考えています。
次回予告
Increments × cyma (Ateam Inc.) Advent Calendar 2020 の9日目は、Increments株式会社の@getty104さんがお送りします。