[Rails] RSpecでカバレッジを可視
はじめに
こんにちは、横浜事業所のF.Tです。
最近、Railsで作成されたプロジェクトの単体テストにRSpecを導入しました。
その際に、テストのカバレッジを取得&可視化するためにsimplecovというgemを追加しました。テストについては設計もコーディングもほぼほぼ経験がなく、有識者も周りにいなかったため調べつつなんとか実装を行いました。
というわけで今回は、RSpecの導入とカバレッジ取得についてまとめていきたいと思います。
超ざっくりいうと、「Rubyでテスト自動化のためのコードを書いて、ちゃんとテストできているか可視化して確認する」 ということをしていきます。
RSpecとは
そもそもRSpecとはなんぞやというところを触れます。
RSpecとは、RubyやRuby on Railsで作成されたクラスやメソッドをテストするためのGemパッケージです。
以下公式では、
と記載してあることから、TDD(テスト駆動開発)・BDD(振る舞い駆動開発)を支援するためのツールとして存在しています。
言語はもちろんRubyが使用されています。
導入方法
上記のGitHubを参考に対象のRailsのバージョンに合わせたRSpecのgemをインストールします。今回は、既存でRailsアプリがある前提で進めていきます。
Gemfileに下記コードを追加しましょう。
group :development, :test do
gem 'rspec-rails', '~> 対象version'
end
続いてRSpecのgemパッケージをインストールします。
$ bundle install
gemがインストールできたらRSpecの初期ファイルをインストールします。
$ rails generate rspec:install
以上でRSpecの準備ができました。実際の使用についてはカバレッジ取得の説明の際に触れます。
カバレッジとは
カバレッジとは
「所定の網羅条件がテストによってどれだけ実行されたかを割合で表したもの」です。
テストコードにおけるカバレッジとは、コード網羅率を意味しています。
テストコードが、テスト対象のメソッド等を本当に実行しているのか(網羅しているのか)を計測するために使用します。このカバレッジを取得することで、テストの品質を定量的に測ることができます。
またカバレッジの中でもレベルが細分化されており、
命令網羅(C0 or SC)
分岐網羅(C1 or BC)
条件網羅(C2 or CC)
判定条件/条件網羅(DC/CC)
複合条件網羅(MCC)
経路組み合わせ網羅(path coverage)
があります。
詳しくは以下のSHIFTのメディアやITmediaエンタープライズの情報システム用語事典の参考リンクを参照ください。
RSpecでのカバレッジ取得について
カバレッジ=コード網羅率
と述べましたが、テスト対象のコードがどれだけ網羅されているかを可視化できるパッケージがsimplecovです。
RSpecでテストを実行すると、htmlファイルが作成され、カバレッジが確認できます。
準備
simplecovのインストールは、まずGemfileに以下を記述します。
gem 'simplecov', require: false, group: :test
そしてbundle installを実行します。
インストールしただけだとカバレッジはまだ取得できないので、spec_helper.rbの最上部に以下を記述します。
require 'simplecov'
SimpleCov.start
これでカバレッジ取得の準備はOKです。
テストを書いてカバレッジ取得してみる
では実際に簡単なテストと実施し、カバレッジを見ていきましょう。
まずは以下の簡単なUser classを作成します。
user.rb
class User < ApplicationRecord
def initialize(attributes = {})
@name = attributes[:name]
@age = attributes[:age]
end
def introduction
if @age < 18
"#{@name}は未成人です。"
else
"#{@name}は成人です。"
end
end
end
このclassをテストしてカバレッジを取得します。
spec/models/user_spec.rbに対象のテストコードを書いていきます。
user_spec.rb
RSpec.describe User do
describe '#introduction' do
let(:user) { User.new(**params) }
let(:params) { { name: '未成人太郎', age: age } }
context '18歳未満の場合' do
let(:age) { 17 }
it '未成人が返ること' do
expect(user.introduction).to eq '未成人太郎は未成人です。'
end
end
end
end
上記のテストコードはintroductionメソッドのテストを行なっており、
user.rb
if @age < 18
"#{@name}は未成人です。"
else
age = 17 name = '未成人太郎は未成人です。'の時、つまりこの上記コードのif文がtrueのときの返り値が、期待値('未成人太郎は未成人です。')と等しいかどうかをテストしています。
では下記コマンドでテストを実行します。
$ bundle exec rspec
以下(ターミナルスクショ)が表示されました。上記のテストが期待値通り成功したことを表しています。
続いて上記のテストのカバレッジを見ていく前に、テストが失敗したときを見てみましょう。
同じintroductionメソッドに対して、
user_spec.rb
# 年齢を変更
context '20歳未満の場合' do
let(:age) { 19 }
it '未成人が返ること' do
expect(user.introduction).to eq '未成人太郎は未成人です。'
end
end
上記のように成人年齢の仕様が誤った'てい'でテストをしてみます。
結果は、以下となります。
テストが失敗しています。「テストコードでは成人年齢が20歳以上の仕様だと思って書いていたが、実際のUserモデルでは18歳以上の仕様だった」という現実でもなくはなさそうなケースであえて失敗させてみました。
添付画像内では、expected:でテストの期待値が、got:で実際のテスト対象メソッドの返り値が表示されています。
ではカバレッジを見ていきましょう。
先ほどのテストが成功した時、Coverage report generated ・・・・と表示が出ます。
この表示が出ていれば、coverageディレクトリが新しくプロジェクト内に作成されていることが確認できると思います。そのディレクトリ内の index.htmlから、カバレッジが確認できますので、見てみましょう。
この添付画像がカバレッジを可視化したindex.htmlになります。テスト実行時Userモデルのコードで通った部分が緑ライン、通っていない部分が赤ラインで表示されています。今回はifがfalseの場合に関してテストを記述していなかったため、赤で表示されています。
以下の通り、18歳以上の場合のテストも追加してあげると、Userモデルのカバレッジが100%となります。
user_spec.rb
context '18歳未満の場合' do
let(:age) { 17 }
it '未成人が返ること' do
expect(user.introduction).to eq '未成人太郎は未成人です。'
end
end
context '18歳以上の場合' do
let(:age) { 18 }
it '成人が返ること' do
expect(user.introduction).to eq '未成人太郎は成人です。'
end
end
ここまで簡単にですが、RSpecとsimplecovを導入し、実際にテストを実行してカバレッジを確認する所までを紹介しました。実際はカバレッジをただ100%にすれば良いわけではなく、「テスト対象だけをテストできているか」「テストコードが読みやすいか」「仕様に合ったテストが行えているか」等、意識しないといけないポイントは多いです。その辺のバランスをうまくとって、効率的に品質の高い開発ができるエンジニアになりたいものです。
参考
ALHについて知る
↓ ↓ ↓ 採用サイトはこちら ↓ ↓ ↓
↓ ↓ ↓ コーポレートサイトはこちら ↓ ↓ ↓
↓ ↓ ↓ もっとALHについて知りたい? ↓ ↓ ↓