2018年2月13日

プログラミング

Rails5でRSpec入門

目次

  1. はじめに
  2. RSpecとは
  3. RSpecの設定
  4. RSpecでテストを実行する
  5. RSpecのテスト自動化
  6. まとめ

はじめに

システム開発にはテストが欠かせません。
Ruby on Railsではデフォルトのテスト機能もありますが、より便利で最も多くのRubiestが使用するテストフレームワーク、RSpecの導入方法や簡単な使い方をご紹介します。

今回使用する環境

  • Ruby: 2.3.1
  • Ruby on Rails: 5.1.4
  • RSpec(rspec-rails): 3.6.0

RSpecとは


RSpecはテストフレームワークです。ソースコードが正しい動作をしているか、テストコードを書くことでその確認をすることができます。

公式サイトを見るとこのように書かれています。

Behaviour Driven Development for Ruby.
Making TDD Productive and Fun.

ここで書かれている「Behaviour Driven Development」と「TDD」とは何者でしょうか。
簡単に解説します。

TDDとは

TDDとは、「Test Driven Development」の略です。

通常のウォーターフォール型のシステム開発においては、このような開発フローが一般的です。

  1. 出来るだけ完璧なソースコードを書いて
  2. テストコードを書いて
  3. テストをする、ダメなら1に戻る

TDDでは、このようなフローとなります。

  1. テストコードを書いて
  2. テストを通るソースコードを出来るだけ早く書いて
  3. テストをする、通ったら2に戻りコードを精錬させる(リファクタリング)

TDDを使用することで、バグが早期段階でわかるようになるので、工数の削減や最終的なバグの数が少なくなることがメリットです。

POINT!!

メリットばかりではなく、TDDにはデメリットや失敗事例も多くあります。最も要因として大きいことが、開発者がTDDを理解し慣れるまでに時間がかかるということです。
どうしても急ぐときにテストコードを書くのが難しくなり、そのまま書かない(開発→最後にテストという流れ)に戻ってしまうケースもよく耳にします。

Behaviour Driven Development、BDDについては振る舞い駆動開発、ビヘイビア駆動開発など訳されます。
TDDをより読みやすい(理解しやすい)テストコード化したもので、「何を実現したいのか」など振る舞いを書くものとなります。

RSpecの設定

まずGemfileに以下の設定をしましょう。

group :development, :test do
  gem 'rspec-rails', '~> 3.5'
end

そしてbundle install を実行します。
rspec-railsがインストールされたら、初期化を行います。

rails generate rspec:install

実行結果がこちらです。

create  .rspec
create  spec
create  spec/spec_helper.rb
create  spec/rails_helper.rb

それぞれ役割を見ていきましょう。
.rspecファイル→読み込むヘルパーやドキュメントフォーマットなどを設定するファイル。
specディレクトリ→テストファイルを格納するディレクトリ
spec/spec_helper.rb→あくまでもRSpecに関する設定が書かれているヘルパーファイル
spec/rails_helper.rb→Rails側の設定用ヘルパーファイル。

POINT!!

以前ヘルパーは spec_helper.rb のみ作られていましたが、Rspecのバージョン3以降からrails_helper.rbが作られるようになっています。 確かにrails_helper.rb には ActiveRecord の設定や fixture(テストの事前設定)のRails用のパスなどが書かれていますが、spec_helper.rb にはそのようなRails関係の設定は一切記述されていません。

RSpecでテストを実行する

一旦この状態でRSpecでテストを実行させてみましょう。
bundle exec rspec

するとこのようなメッセージが表示されます。

No examples found.
Finished in 0.00038 seconds (files took 0.3511 seconds to load)
0 examples, 0 failures

見方としては、examples がテスト、failures がその失敗と考えてください。
つまり、0件のテストを実行し0件失敗したよというメッセージです。
(何も書いていないので当然です。)

では、実際にテストを書いてみましょう。
まずmodelを追加してみます。
rails g model User name:string

するとこのような実行結果が出ます。

Running via Spring preloader in process 23586
      invoke  active_record
      create    db/migrate/20170726000503_create_users.rb
      create    app/models/user.rb
      invoke    rspec
      create      spec/models/user_spec.rb

spec/models/user_spec.rb が自動的に作られたことがわかると思います。
rake db:migrate コマンドでmigrationをしておきましょう。

もちろん既存のコードにもテストを適用することができます。
rails g rspec:model user
このようにspec:controller や spec:view などテストを作りたい対象を指定することでspecファイルが作られます。
spec/models/user_spec.rb

 

では、テストを書いてみましょう。
ここではUserのnameは必須という仕様で、 nameの存在チェックに関するバリデーションが正しく動作すること が期待する動作とします。

まず、先程の順番に沿って「1. テストコードを書いて」からはじめましょう。

spec/models/user_spec.rb

require 'rails_helper'

describe User do  # 何のテストをするのか、対象を書く
  it 'is not be valid without name' do # 期待する動作説明を書く
    user = User.new(name: '')
    expect(user).not_to be_valid # 動作をテストする部分
  end
end

解説ですが、user には name が空っぽのデータが入っています。
ここで期待することは「nameの存在チェックに関するバリデーションが正しく動作すること」です。
expect(user).not_to be_valid で「userはバリデーションエラーとなっていること」をテストしています。

では、ここでテストを実行しましょう。
bundle exec rspec

F

Failures:

  1) User is not be valid
     Failure/Error: expect(user).not_to be_valid
       expected #<User id: nil, name: "", created_at: nil, updated_at: nil> not to be valid
     # ./spec/models/user_spec.rb:6:in `block (2 levels) in <top (required)>'

Finished in 0.05656 seconds (files took 5.15 seconds to load)
1 example, 1 failure

Failed examples:

rspec ./spec/models/user_spec.rb:4 # User is not be valid

メッセージでお分かりになるように、テストに失敗しました。
「nameの存在チェックに関するバリデーション」が実装されていないので当然ですよね。

では、次のステップの「2. テストを通るソースコードを出来るだけ早く書いて」を実施しましょう。

「nameの存在チェックに関するバリデーション」を実装してテストすれば、テストは成功するはずです。
models/user.rb

class User < ApplicationRecord
  validates :name, presence: true
end

存在チェックを実装したので次のステップに進みます。
「3. テストをする、通ったら2に戻りコードを精錬させる(リファクタリング)」

ではもう一度テストをしてみましょう。
bundle exec rspec

.

Finished in 0.03041 seconds (files took 4.85 seconds to load)
1 example, 0 failures

failuresが0になり、テストに成功しました!
これで最低限の仕様を満たすコードが実現できました。
ここからテストを成功した状態でコードを精錬させていく(リファクタリング)をしていくことがTDDの簡単な流れです。

RSpecのテスト自動化

毎回 rspec コマンドを打つのは大変ですよね。
そんなときに便利なのはguard というgemです。
gem 'guard-rspec', require: false
をGemfileに記載し、bundle install しましょう。

このコマンドで設定ファイルが作られます。
bundle exec guard init rspec

Guardfile というファイルが出来ているので、そちらに監視対象のファイルなど設定をすることができます。

そして bundle exec guard でguardによる監視がスタートします。
あとは監視ファイルにあるspecファイルを修正することでテストが自動で実行されます。

更に terminal-notifier-guard などの通知Gemを導入することで、ますます便利になるはずです。

まとめ

RSpecを導入することで、口語のような読みやすくわかりやすいテストを書くことができます。
またTDDのサイクルを回すことで、より短期間に品質が担保されたコードを実現することができます。(慣れは必要ですが…)

Ruby on Railsのお仕事に関するご相談

Bageleeの運営会社、palanではRuby on Railsに関するお仕事のご相談を無料で承っております。
zoomなどのオンラインミーティング、お電話、貴社への訪問、いずれも可能です。
ぜひお気軽にご相談ください。

無料相談フォームへ

3

0

AUTHOR

eishis

Eishi Saito 総務

SIerやスタートアップ、フリーランスを経て2016年11月にpalan(旧eishis)を設立。 マーケター・ディレクター・エンジニアなど何でも屋。 COBOLからReactまで色んなことやります。

アプリでもっと便利に!気になる記事をチェック!

記事のお気に入り登録やランキングが表示される昨日に対応!毎日の情報収集や調べ物にもっと身近なメディアになりました。

簡単に自分で作れるWebAR

「palanAR」はオンラインで簡単に作れるWebAR作成ツールです。WebARとはアプリを使用せずに、Webサイト上でARを体験できる新しい技術です。

palanARへ
palanar

palanはWebARの開発を
行っています

弊社では企画からサービスの公開終了まで一緒に関わらせていただきます。 企画からシステム開発、3DCG、デザインまで一貫して承ります。

webar_waterpark

palanでは一緒に働く仲間を募集しています

正社員や業務委託、アルバイトやインターンなど雇用形態にこだわらず、
ベテランの方から業界未経験の方まで様々なかたのお力をお借りしたいと考えております。

話を聞いてみたい

運営メンバー

eishis

Eishi Saito 総務

SIerやスタートアップ、フリーランスを経て2016年11月にpalan(旧eishis)を設立。 マーケター・ディレクター・エンジニアなど何でも屋。 COBOLからReactまで色んなことやります。

sasakki デザイナー

アメリカの大学を卒業後、日本、シンガポールでデザイナーとして活動。

yamakawa

やまかわたかし デザイナー

フロントエンドデザイナー。デザインからHTML / CSS、JSの実装を担当しています。最近はReactやReact Nativeをよく触っています。

Sayaka Osanai デザイナー

Sketchだいすきプロダクトデザイナー。シンプルだけどちょっとかわいいデザインが得意。 好きな食べものは生ハムとお寿司とカレーです。

はらた

はらた エンジニア

サーバーサイドエンジニア Ruby on Railsを使った開発を行なっています

kobori

こぼり ともろう エンジニア

サーバーサイドエンジニア。SIerを経て2019年7月に入社。日々学習しながらRuby on Railsを使った開発を行っています。

sasai

ささい エンジニア

フロントエンドエンジニア WebGLとReactが強みと言えるように頑張ってます。

damien

Damien

WebAR/VRの企画・開発をやっています。森に住んでいます。

ゲスト bagelee

ゲスト bagelee

かっきー

かっきー

まりな

まりな

suzuki

suzuki

miyagi

ogawa

ogawa

雑食デザイナー。UI/UXデザインやコーディング、時々フロントエンドやってます。最近はARも。

いわもと

いわもと

デザイナーをしています。 好きな食べ物はラーメンです。

kobari

taishi kobari

フロントエンドの開発を主に担当してます。Blitz.js好きです。

shogokubota

kubota shogo

サーバーサイドエンジニア。Ruby on Railsを使った開発を行いつつ月500kmほど走っています!

nishi tomoya

aihara

aihara

グラフィックデザイナーから、フロントエンドエンジニアになりました。最近はWebAR/VRの開発や、Blender、Unityを触っています。モノづくりとワンコが好きです。

nagao

SIerを経てアプリのエンジニアに。xR業界に興味があり、unityを使って開発をしたりしています。

kainuma

Kainuma

サーバーサイドエンジニア Ruby on Railsを使った開発を行なっています

sugimoto

sugimoto

asama

ando

iwasawa ayane

oshimo

oshimo

異業界からやってきたデザイナー。 palanARのUIをメインに担当してます。 これからたくさん吸収していきます!

CONTACT PAGE TOP