RSpec(アールスペック)は「Ruby」言語で利用される代表的なテストツールで、クラスやメソッド単位でテストをおこなうことができます。
RSpecを使ったテスト手法を理解することで、プログラミングしたコードのバグ解消や品質を向上することができますが、「RSpecは難しい」「よくわかならない」といったコメントを見掛けることがあります。
そこで今回は、以下について解説していきます。
・RSpecとは
・RSpecの環境構築
・RSpecのテスト手法
・RSpecの基本的な構文
この記事を読み終える頃には「RSpecは難しい」「よくわかならない」と思っていたあなたも、きっと「RSpecはやさしい」「使いやすい」といった気持ちに変わっていること間違いなしです!
RSpecとは
この項目では、RSpecの特徴や、RSpecのメリット・デメリットについて解説していきます。
RSpecの特徴
RSpecはテストツールのため、「Ruby」や「Ruby on Rails」といった言語、フレームワークと組み合わせて利用します。
RSpecの特徴としては以下があげられます。
「Ruby」を基に作成されたテストフレームワークである
RSpecは「Ruby」をベースに作られているので、「Ruby」を理解しているユーザであれば簡単に習得することができます。
規模が大きいプログラムのテストを実施するのは大変な作業ですが、テストツールを利用することで大幅な作業コストを抑えることができます。
サポート機能が充実している
RSpecは、以下のようなテストのサポート機能が用意されています。
・「Ruby on Rails」のテストサポート機能
・モックやスタブ(疑似的なクラス)によるテスト支援
・テストデータの作成支援
・HTML形式でのテスト結果出力機能
・カバレッジ(プログラムコードが実行された割合チェック)ツールとの連携機能 など
RSpecのメリット
RSpecのメリットとしては以下があげられます。
簡単にバグを発見することができる
RSpecを利用することにより、通常目視で確認するプログラムのバグを自動的に発見することができます。
BDD(Behaviour Driven Development)手法ができる
BDDは「振る舞い駆動開発」という意味で、「プログラムコードより先にテストコードを記述する」という開発手法です。BDDツールであるRSpecを利用することで、プログラムの仕様の検討漏れによるバグを回避することができ、問題発生を最小限に食い止めることが可能です。
言語やフレームワークのバージョンアップ時も安心
言語やフレームワークのバージョンがアップされた時、プログラムが仕様通りに動作してくれるかをRSpecが自動でバグチェックを行ってくれるので、このような心配をする必要がありません。
RSpecのデメリット
RSpecのデメリットとしては以下があげられます。
全てを自動化できるわけではない
RSpecは「バグチェックを自動化できる」と「RSpecのメリット」で記述しましたが、「テストコードの記述」や「テスト実行の命令作業」といったところを自動化できるわけではありません。こちらについては作業する必要があります。
仕様変更になればテストコードを修正する必要がある
仕様変更が発生した場合、テストコードを修正する必要があります。
もし、テストコードを記述しているタイミングで仕様変更が発生した場合、大幅な作業コストがかかる可能性があります。
RSpecの環境構築
この項目では、RSpecのダウンロードからインストール、初期設定、動作確認について解説していきます。
「rspec-rails」パッケージをダウンロードする
下記公式サイトより「rspec-rails」パッケージをzip形式でダウンロードします。
https://github.com/rspec/rspec-rails
所定の場所でzipファイルを解凍後、「Gemfile」を手順(README.md)に沿って編集します。
※上記は「Gemfile」に記述しますが、記述内容は手順(README.md)の内容に合わせます。
インストールする
「Gemfile」の編集が終わったら、プロジェクトディレクトリ直下で「RSpecインストール」コマンド、および「設定ファイル作成」コマンドを実行します。
またRSpecを利用するため、Minitest用の/testディレクトリは削除します。
初期設定する
「設定ファイル作成」コマンドで作成された「.rspec」ファイルに設定内容を記述します。
オプション名 | 説明 |
require | 呼び出すファイルを指定します。 |
color | 出力結果に色を付けます。 |
format | 出力形式を設定します。 |
動作確認する
RSpecのインストール、および初期設定が終わったら、テスト実行ができるのか以下のコマンドで確認してみましょう。
RSpecのテスト手法
この項目では、RSpecのテスト可能な範囲からテストの基本的な流れ、テストコードの書き方・実行について解説していきます。
テスト可能な範囲
テストには「単体テスト」「結合テスト」「システムテスト」の3種類があります。
※RSpecでは「単体テスト」の実施が可能です。
単体テスト:
プログラムを構成するクラスやメソッドの1単位が仕様通りに正しく機能するかを確認するテスト。
結合テスト:
単体テストを終えた各クラスやメソッドを組み合わせて、仕様通りに正しく機能するかを確認するテスト。
システムテスト:
エンドユーザーが実際業務で利用するシーンを想定し、仕様通りに正しく機能するかを確認するテスト。
テストの基本的な流れ
RSpecを利用したテストの基本的な流れは以下となります。
- テストコードを作成する
RSpecを利用する場合、プログラムコードを作成する前にテストコードを作成する必要があります。テストコードは「プログラムコード作成前」に作成することがポイントです! - テストを実行して失敗することを確認する
テストコードを作成する際、一旦全てが失敗(false)するようにしてください。正しいプログラムを記述して、初めて成功(true)することがわかるようにするためです。テストコードが完成したら、まずはテストコードを実行して失敗することを確認しましょう。 - テスト対象プログラムを作成する
テストコードが成功するためのテスト対象プログラムを作成します。
テストの基本的な流れは、上記の繰り返しになります。
テストコードの書き方
RSpecのテストファイルは「Ruby」言語で記述し、ファイル名は「spec/●●/○_spec.rb」とする必要があります。
また、テストファイルの中に必ず「require ‘rails_helper’」のコードを記述し、「describe」「context」「it」を使って記述します。
テストの内容は「it」で記述し、期待する結果を「expect」を使って記述します。1テストケースで「it」「expect」の記述が必要です。
特定条件を想定する場合は「context」を使って、条件の記述をおこないます。
テストコードを実行する
テストコードの作成が終わったら、以下のコマンドでテストコードを実行してみましょう。
以下のような結果が表示されると成功となります。
テストコードの実行コマンドは他にも以下のような方法があります。
<例1>spec/requests/user_pages_spec.rbをテストする場合
$ bundle exec rspec spec/requests/user_pages_spec.rb
<例2>requestsディレクトリ内のテストを一括実行したい場合
$ bundle exec rspec/requests/
<例3>requestsディレクトリの1つ上の階層から実行したい場合
$ bundle exec rspec spec/
<例4>テストをフル実行したい場合
$ bundle exec rake spec
※rakeを利用したテストを実行する場合、テスト環境用データベースを正しく設定する必要があります。
RSpecの基本的な構文
この項目では、RSpecで利用する基本的な構文について解説していきます。
describe / it / expect
「describe」はテスト対象が何か(クラス、メソッド)を記述します。「it」は期待する結果を記述します。この時「正しいこと」などのような表現は避け、「正しいとはどういう状況か」を詳しく記述します。「expect」はテスト対象を検証するためのメソッドで、「expect(X).to eq Y」は「XはYと等しいことを期待する」という意味になります。
以下は「describe」「it」「expect」のサンプルコードです。
context
「context」はテストしようとしている条件が何かを記述します。
以下は「context」のサンプルコードです。
before
「before」は「before do ... end」と記述することで、「before」の後に共通している部分を前もって定義することができます。(インスタンス変数として設定できます。)
以下は「before」を使った場合のサンプルコードです。
以下は「before」を使わなかった場合のサンプルコードです。
見てわかるように、「before」内で記述したコードを「it」内で4回記述する必要があります。
let / let!
「let」は「before」と比べて、インスタンス変数を以下のように置き換えて記述することができます。
以下は①「let」を使わなかった場合、②「let」を使った場合のサンプルコードです。
また「let」は、定義した定数が初めて使われたときに評価される(遅延評価される)のに対し、「let!」は、各テストのブロック実行前に評価されます。(事前評価される)
以下のサンプルコードは「composer_song」がcreateされておらず、「composer.song.first」は空になり、テストは失敗となります。
しかし、以下のサンプルコードのように「let!」を利用することでテストは成功となります。
subject
「subject」はテスト対象のクラスやメソッドの実行結果が明確に決まっている場合に利用し、「let」のように処理を変数に置き換えて記述します。
以下のように「get '/hogehoge', params: param」という箇所をDRY(システム上で同じ情報の重複を行わないようにすること)に記述することができます。
「shared_examples」「shared_context」はプログラミング的には同じものですが、「shared_examples」は「it」を共通化したい場合に利用し、「shared_context」は「context」を共通化したい場合に利用します。
以下は「shared_examples」のサンプルコードです。
以下は「shared_context」のサンプルコードです。
見てわかるように、「shared_examples」「shared_context」ともに定義することで、複数のところで使いまわすことが可能です。
pending / skip
「pending」は該当のプログラムコードのテストを実施したくない場合に利用し、「skip」は「skip」を記述したところ以降のプログラムコードのテストを実施したくない場合に利用します。
以下は「pending」のサンプルコードです。
以下は「skip」のサンプルコードです。
なお、「it」を「xit」にするだけで「skip」と同じ意味になります。
まとめ
この記事では、RSpecの概要から始まり、環境構築、テスト手法、基本的な構文について解説しました。
この記事を読んで、「RSpecはやさしい」「使いやすい」といった気持ちに変わったことでしょう。この記事が今後のスキル向上の一助になっていただけると幸いです。RSpecは「Ruby」を使ったプログラム開発をおこなう上で「単体テスト」をラクにしてくれるテストツールです。「Ruby」「Ruby on Rails」を使った開発をおこなう場合、テストツールとして利用検討をオススメします。