RailsのテストフレームワークRSpecの基礎知識

実践Ruby on Rails 4 現場のプロから学ぶ本格Webプログラミング顧客管理システムの構築を体験しながら、Railsアプリケーション開発のノウハウを習得!この記事は、書籍『実践Ruby on Rails 4 現場のプロから学ぶ本格Webプログラミング』の内容を、Think IT向けに特別に

黒田 努

2014年7月8日 22:00

実践Ruby on Rails 4 現場のプロから学ぶ本格Webプログラミング
顧客管理システムの構築を体験しながら、Railsアプリケーション開発のノウハウを習得!Amazon詳細ページへ

この記事は、書籍『実践Ruby on Rails 4 現場のプロから学ぶ本格Webプログラミング』の内容を、Think IT向けに特別にオンラインで公開しているものです。詳しくは記事末尾の書籍紹介欄をご覧ください。

RSpecの基礎知識

本記事では、テストフレームワークとしてRSpecを採用します。RSpecをうまく活用すると、簡潔で読みやすいテストコードを書くことができ、Railsアプリケーションの保守性を高めることができます。

しかし、RSpecの用語法や表記法はやや独特で、慣れるまでには時間がかかります。読者の中にはとまどいを覚える方がいらっしゃるかもしれませんが、次章以降を読み進めるうえでの鍵となりますので、是非じっくりと読んで理解してください。

テストとは

Webアプリケーション開発の文脈において、テストという言葉はさまざまな意味で用いられます。日常的な場面では、人がWebアプリケーションの動きを目視でチェックする作業を意味します。たとえば、Webアプリケーションをサーバーコンピュータにインストールし、人が実際にWebブラウザを操作して、仕様どおりの反応を返すかどうか確かめるといった作業です。

しかし、プログラマの間では「テスト」という言葉がしばしば異なる意味で用いられます。私たちは、専用のプログラムによってWebアプリケーションの動作を確認することを「テスト」と呼びます。この意味でのテストは自動で行われます。人間がディスプレイを見守っていなくてもテストが進行し、テストが終わると成功あるいは失敗という結果がディスプレイに表示されます。

本書では「テスト」という言葉を、ソフトウェアによって自動で実施されるテストという意味で用います。

テストを実行するための専用のプログラムを「テスト」と呼ぶ用法もあります。たとえば、私たちはしばしば「テストを書く」という言い方をします。これは、テストを実行するためのプログラムを作ることを意味します。

RSpecとは

前著『改訂新版 基礎Ruby on Rails』では、Railsに標準で組み込まれているテストフレームワークTest::Unitを用いたテストについて解説しましたが、本書ではRSpec(アールスペック)という別のテストフレームワークを採用することにします。

Rails 4では標準のテストフレームワークがTest::UnitからMiniTestに変更されました。MiniTestはTest::Unitの機能強化版で、Test::Unitとの互換性をほぼ保っています。

RSpecを採用した理由は、正直に言えば「私が普段使っているから」ということになります。RSpecはRailsプログラマの間で高い人気を獲得していますが、その独特の用語法や書き方になじめない方も多いようです。私はRSpecにはTest::Unitやその後継のMiniTestにはない優れた特徴があると考えています。

しかし、RSpecがRailsに組み込まれていないことからもわかるように、けっして「事実上の標準(de facto standard)」の地位をRails業界において確立しているわけではありません。

RSpecの初期設定

RailsでRSpecを利用する場合、一度だけ次のコマンドを実行する必要があります。

$ bin/rails g rspec:install

ゲストOSで実行してください。すると、specディレクトリが作られて、その下にspec_helper.rbというファイルが生成されます。初期状態での内容は次のとおりです(コメント行を省略しています)。

spec/spec_helper.rb

ENV["RAILS_ENV"] ||= 'test'
require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'

Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f }

ActiveRecord::Migration.check_pending! if defined?(ActiveRecord::Migration)

RSpec.configure do |config|
  config.fixture_path = "#{::Rails.root}/spec/fixtures"
  config.use_transactional_fixtures = true
  config.order = "random"
end

Rails 4.1に対応するため、このファイルの7行目を次のように書き換えてください。

ActiveRecord::Migration.maintain_test_schema!

RSpec ―― はじめの一歩

RSpecがどんなものであるかを感覚的に理解するため、実際にRSpecによる簡単なテストコードを書いて、実行してみることにしましょう。

Baukisのプロジェクトディレクトリ直下にspecディレクトリがあります。その下にexperimentsというサブディレクトリを作り、string_spec.rbというファイルを作成してください。

spec/experiments/string_spec.rb

require 'spec_helper'

describe String do
  describe '#<<' do
    example '文字の追加' do
      s = "ABC"
      s << "D"
      expect(s.size).to eq(4)
    end
  end
end

RSpecのテストコードは、通常specディレクトリの下に置きます。ファイル名の末尾は_spec.rbで終わるようにしてください。これらのファイルをspecファイルと呼びます。

specファイルはspecディレクトリのサブディレクトリに適宜分類して配置します。どのサブディレクトリにどんなspecファイルを置くかは慣習的に決まっています。たとえば、モデルクラスに関するspecファイルはspec/modelsディレクトリに、APIに関するspecファイルはspec/requestsディレクトリに置くのが一般的です。しかし、独自のサブディレクトリを用意しても構いません。ここでは、RubyもしくはRailsの仕様に関する実験を行うspecファイルを置く場所としてexperimentsサブディレクトリを作成しました。これは本書独自のルールです。

テストコードの本体は次の3行です。

s = "ABC"
s << "D"
expect(s.size).to eq(4)

まず変数sに"ABC"という文字列をセットし、それに"D"という文字を追加しています。最後に、expectメソッドで変数sの状態を調べています。expectメソッドの使い方は後述しますが、ここではsの長さが4であるかどうかをチェックしています。

では、このspecファイルを実行してみましょう。ゲストOSのターミナルで、次のコマンドを実行してください。

$ bin/rspec spec/experiments/string_spec.rb

すると、次のような結果がターミナルに表示されます。

.

Finished in 0.13482 seconds
1 example, 0 failures

Randomized with seed 15657

ただし、3行目の「0.13482」および6行目の「15657」は、実行するたびに値が変化します。この結果の読み方については、後述します。

bin/rspecコマンドの結果の最終行に出力される「Randomized with seed ...」という行は、RSpecが内部的に利用している乱数のシード値(疑似乱数を計算するための係数)を表しています。RSpecは複数のエグザンプルをランダムな順番で実行するために乱数を利用しています。これ以降、テストの結果を掲載する際にはこの行を省略します。

このようにbin/rspecコマンドはspecファイルのパスを指定して個別に実行することも可能ですが、specファイルを含むディレクトリを指定して、そこに含まれるspecファイルを一括して実行することもできます。たとえば、次のコマンドはspecディレクトリ以下にあるすべてのspecファイルを実行します。

$ bin/rspec spec
この記事のキーワード :

人気記事トップ10

人気記事ランキングをもっと見る

企画広告も役立つ情報バッチリ! Sponsored

ClickHouse Cloudが実現した広告運用SaaS「ATOM」のデータ基盤革新、パフォーマンスを向上しながら、運用負荷とコストを削減 11月11日 6:20 AIで開発が加速する時代、品質保証はどう変わる? Tricentisが示すAIエージェント活用の実像 11月9日 6:45 悪用までの猶予が「1分」に迫るフロンティアAI時代に開発と本番を貫く脆弱性管理が必要 10月29日 8:30 欧州CRA対応とSBOM運用。AI生成コードのOSS混入問題の対策とは ――スニペット単位で検出する「FossID」「Insignary Clarity」によるSBOM運用 9月16日 6:40 PostgreSQLからTiDBへ、稼働中SaaSで進める段階的DB移行の実践と再設計への展望 9月7日 6:30 機能安全開発におけるGoogleTestの活用を支援!「Parasoft C/C++test CT」で実現する効率化&AI連携 4月14日 6:30 【CNDW2025】Grafanaが明かす「オブザーバビリティの哲学」ー最小限の労力で実用的なインサイトを得るには 1月23日 6:30 【CNDW2025】プロダクト急増に備える基盤刷新 ーウェルスナビがECSからEKSへの移行で得た知見とは 1月15日 6:30 【CNDW2025】250環境を5人で運用、構築時間は30分に ーKINTOテクノロジーズが語るインフラ基盤組織の作り方 2025年12月18日 6:30 新たな自動化で熱視線! AIエージェントの「推論能力」を支える2つのコンポーネントとは? 2025年11月28日 6:30