2018年2月13日
プログラミング
Rails5でRSpec入門
はじめに
システム開発にはテストが欠かせません。
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に戻る
TDDでは、このようなフローとなります。
- テストコードを書いて
- テストを通るソースコードを出来るだけ早く書いて
- テストをする、通ったら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
関連記事
2021年12月23日
RailsアプリにGoogle Mapから緯度経度情報を取得する機能を追加する
2021年12月22日
RDBでセットメニューを表現する方法
2021年12月11日
Railsでツリー構造アプリを作ってみた
2021年12月10日
Dockerで作成したRailsアプリケーションをHerokuにデプロイする
2021年12月9日
モデルに書いていたメソッドをPOROに切り出してみた!
2021年12月7日
gem cancancanを使ってみた!
簡単に自分で作れるWebAR
「palanAR」はオンラインで簡単に作れるWebAR作成ツールです。WebARとはアプリを使用せずに、Webサイト上でARを体験できる新しい技術です。
palanARへpalanでは一緒に働く仲間を募集しています
正社員や業務委託、アルバイトやインターンなど雇用形態にこだわらず、
ベテランの方から業界未経験の方まで様々なかたのお力をお借りしたいと考えております。
運営メンバー
Eishi Saito 総務
SIerやスタートアップ、フリーランスを経て2016年11月にpalan(旧eishis)を設立。 マーケター・ディレクター・エンジニアなど何でも屋。 COBOLからReactまで色んなことやります。
sasakki デザイナー
アメリカの大学を卒業後、日本、シンガポールでデザイナーとして活動。
やまかわたかし デザイナー
フロントエンドデザイナー。デザインからHTML / CSS、JSの実装を担当しています。最近はReactやReact Nativeをよく触っています。
Sayaka Osanai デザイナー
Sketchだいすきプロダクトデザイナー。シンプルだけどちょっとかわいいデザインが得意。 好きな食べものは生ハムとお寿司とカレーです。
はらた エンジニア
サーバーサイドエンジニア Ruby on Railsを使った開発を行なっています
こぼり ともろう エンジニア
サーバーサイドエンジニア。SIerを経て2019年7月に入社。日々学習しながらRuby on Railsを使った開発を行っています。
ささい エンジニア
フロントエンドエンジニア WebGLとReactが強みと言えるように頑張ってます。
Damien
WebAR/VRの企画・開発をやっています。森に住んでいます。
ゲスト bagelee
かっきー
まりな
suzuki
miyagi
ogawa
雑食デザイナー。UI/UXデザインやコーディング、時々フロントエンドやってます。最近はARも。
いわもと
デザイナーをしています。 好きな食べ物はラーメンです。
taishi kobari
フロントエンドの開発を主に担当してます。Blitz.js好きです。
kubota shogo
サーバーサイドエンジニア。Ruby on Railsを使った開発を行いつつ月500kmほど走っています!
nishi tomoya
aihara
グラフィックデザイナーから、フロントエンドエンジニアになりました。最近はWebAR/VRの開発や、Blender、Unityを触っています。モノづくりとワンコが好きです。
nagao
SIerを経てアプリのエンジニアに。xR業界に興味があり、unityを使って開発をしたりしています。
Kainuma
サーバーサイドエンジニア Ruby on Railsを使った開発を行なっています
sugimoto
asama
ando
iwasawa ayane
oshimo
異業界からやってきたデザイナー。 palanARのUIをメインに担当してます。 これからたくさん吸収していきます!