💡
この記事は Middleman 時代に書いた古いものです。記録のため、astro-notion-blog に移行していますが、あまり参考にしないでください。
テストはこれまで通り,RSpec を利用する. RSpec は Ruby における BDD(Behavior Driven Development) 手法を実現するシステムである. ここでは,RSpec の設定について記載する.
RSpec のインストール
-
Gemfile の development, test の項目に rspec-rails を追加する
group :development, :test do gem 'rspec-rails' (中略) end
-
bundle する(2行目以降は結果: 変更分のみ)
$ bundle Fetching diff-lcs 1.3 Fetching rspec-support 3.8.0 Installing diff-lcs 1.3 Installing rspec-support 3.8.0 Fetching rspec-core 3.8.0 Fetching rspec-expectations 3.8.2 Fetching rspec-mocks 3.8.0 Installing rspec-expectations 3.8.2 Installing rspec-mocks 3.8.0 Installing rspec-core 3.8.0 Fetching rspec-rails 3.8.1 Installing rspec-rails 3.8.1
-
RSpec をインストールする
$ bin/rails g rspec:install Running via Spring preloader in process 1512 create .rspec create spec create spec/spec_helper.rb create spec/rails_helper.rb
-
試しにテストを実行してみる.Spec を書いてないので,成功する(2行目以降は結果)
$ bin/rails spec /Users/hkob/.rbenv/versions/2.5.3/bin/ruby -I/Users/hkob/rails/attendance/vendor/bundle/ruby/2.5.0/gems/rspec-core-3.8.0/lib:/Users/hkob/rails/attendance/vendor/bundle/ruby/2.5.0/gems/rspec-support-3.8.0/lib /Users/hkob/rails/attendance/vendor/bundle/ruby/2.5.0/gems/rspec-core-3.8.0/exe/rspec --pattern spec/\*\*\{,/\*/\*\*\}/\*_spec.rb No examples found. Finished in 0.00042 seconds (files took 0.12874 seconds to load) 0 examples, 0 failures
Spec の書き方
RSpec の使い方をわかってもらうために,和暦表示のヘルパメソッドを BDD で作ってみる(今回の仕様では和暦表示は必要ではないが).
-
ヘルパメソッドは app/helpers/application_helper.rb に書くことにする.そのため,spec/helpers/application_helper_spec.rb を generator で作成する.
$ bin/rails g rspec:helper application Running via Spring preloader in process 2396 create spec/helpers/application_helper_spec.rb
-
和暦関係の面倒なテストを書いてみた.context はテストの文脈を分けるために使う.subject は通常ではテストターゲットを記載することが多いのだが,今回はテストに必要なパラメータとその答えが入った配列を用意した.各仕様テストのたびに設定される.subject が呼ばれた時に遅延作成され,その後はそれが保持される.it が実際のテストで,その後のメッセージが仕様となる.it の中身で expect によるテストが実行される.今回は記載していないが,it のたびに before で用意された下準備が実行される.オブジェクトの作成・削除が無駄なので,今回は一つの it の中に複数のメソッドテストを記載してしまった.あまりオブジェクトの準備などが重くない場合には,it の中身を expect 一つだけにし,it の後ろのメッセージを省略することも可能である.この場合には,適当なメッセージが仕様として記載される.
require 'rails_helper' RSpec.describe ApplicationHelper, type: :helper do context 'generate date strings' do subject { [ [[1988, 12, 31], '昭和63', 'S63', 63, '12月', '31日'], [[1989, 1, 7], '昭和64', 'S64', 64, '1月', '7日'], [[1989, 1, 8], '平成元', 'H1', 1, '1月', '8日'], [[1989, 12, 31], '平成元', 'H1', 1, '12月', '31日'], [[2018, 4, 1], '平成30', 'H30', 30, '4月', '1日'], ] } # y, m, d がパラメータなメソッド群 it 'wareki, ewareki wareki_num, wareki_ymd and md should have correct values' do subject.each do |ymd, jy, ey, y, jm, jd| expect(wareki(*ymd)).to eq jy expect(ewareki(*ymd)).to eq ey expect(wareki_num(*ymd)).to eq y jymd = "#{jy}年#{jm}#{jd}" expect(wareki_ymd(*ymd)).to eq jymd expect(md(ymd[1], ymd[2])).to eq "#{jm}#{jd}" end end end end
-
テストを実行してみると以下のようになる(2行目以降は結果).分かりにくいが 3 行目の F が失敗を意味している.
$ bin/rails spec /Users/hkob/.rbenv/versions/2.5.3/bin/ruby -I/Users/hkob/rails/attendance/vendor/bundle/ruby/2.5.0/gems/rspec-core-3.8.0/lib:/Users/hkob/rails/attendance/vendor/bundle/ruby/2.5.0/gems/rspec-support-3.8.0/lib /Users/hkob/rails/attendance/vendor/bundle/ruby/2.5.0/gems/rspec-core-3.8.0/exe/rspec --pattern spec/\*\*\{,/\*/\*\*\}/\*_spec.rb F Failures: 1) ApplicationHelper generate date strings wareki, ewareki wareki_num, wareki_ymd and md should have correct values Failure/Error: expect(wareki(*ymd)).to eq jy NoMethodError: undefined method `wareki' for #<RSpec::ExampleGroups::ApplicationHelper::GenerateDateStrings:0x00007f896b5e6248> # ./spec/helpers/application_helper_spec.rb:15:in `block (4 levels) in <top (required)>' # ./spec/helpers/application_helper_spec.rb:14:in `each' # ./spec/helpers/application_helper_spec.rb:14:in `block (3 levels) in <top (required)>' Finished in 0.00677 seconds (files took 2.45 seconds to load) 1 example, 1 failure Failed examples: rspec ./spec/helpers/application_helper_spec.rb:13 # ApplicationHelper generate date strings wareki, ewareki wareki_num, wareki_ymd and md should have correct values /Users/hkob/.rbenv/versions/2.5.3/bin/ruby -I/Users/hkob/rails/attendance/vendor/bundle/ruby/2.5.0/gems/rspec-core-3.8.0/lib:/Users/hkob/rails/attendance/vendor/bundle/ruby/2.5.0/gems/rspec-support-3.8.0/lib /Users/hkob/rails/attendance/vendor/bundle/ruby/2.5.0/gems/rspec-core-3.8.0/exe/rspec --pattern spec/\*\*\{,/\*/\*\*\}/\*_spec.rb failed
-
テストが多くなると現在の表示(progress)の方がよいが,初心者はテストが少ない最初のうちは .rspec の設定を書き換えて documentation 表示にしてみるとよい(2行目を追加).
--require spec_helper --format documentation
-
documentation に変えた時の spec 表示はこうなる.エラーのところにも書かれているが,こちらの方が describe や context による階層構造が見やすい.
ApplicationHelper generate date strings wareki, ewareki wareki_num, wareki_ymd and md should have correct values (FAILED - 1)
テストを通す
-
先ほど記載した spec が通るように実装を記載する.実装することが目的ではないので,別のシステムで使っている実装をそのままコピーしてテストを通すこととする.修正した app/helpers/applicaton_helper.rb は以下のようになった.
module ApplicationHelper # @param [Fixnum] y 年 # @param [Fixnum] m 月 (12) # @param [Fixnum] d 日 (31) # @return [Array<String, Fixnum>] 和暦記号と年度の配列 (例: H21, H1, S43) # @note 昭和は64年1月7日まで,1月8日以降は平成 def warekiSub(y, m, d) return [ 'H', y - 1988 ] if y > 1989 return [ 'H', 1 ] if y == 1989 && m > 1 return [ 'H', 1 ] if y == 1989 && m == 1 && d > 7 return [ 'S', y - 1925 ] end # @param [Fixnum] y 年 # @param [Fixnum] m 月 (12) # @param [Fixnum] d 日 (31) # @return [String] 和暦年度文字列 (例: 平成21, 平成元, 昭和43). def wareki(y, m = 12, d = 31) str, y = warekiSub(y, m, d) { 'H' => '平成', 'S' => '昭和' }[str] + ((y == 1) ? "元" : y.to_s) end # @param [Fixnum] y 年 # @param [Fixnum] m 月 (12) # @param [Fixnum] d 日 (31) # @return [String] 英文和暦記号年度文字列 (例: H21, H1, S43) . def ewareki(y, m = 12, d = 31) warekiSub(y, m, d).join('') end # @param [Fixnum] y 年 # @param [Fixnum] m 月 (12) # @param [Fixnum] d 日 (31) # @return [Fixnum] 和暦年度 (21, 1, 43) def wareki_num(y, m = 12, d = 31) warekiSub(y, m, d)[1] end # @param [Fixnum] y 年 # @param [Fixnum] m 月 (12) # @param [Fixnum] d 日 (31) # @return [String] 和暦年度月日 (例: 平成21年12月7日, 平成元年1月7日, 昭和43年4月25日) def wareki_ymd(y, m = 12, d = 31) "#{wareki(y, m, d)}年#{m}月#{d}日" end # @param [Fixnum] m 月 (12) # @param [Fixnum] d 日 (31) # @return [String] 月日 (例: 12月7日, 1月7日, 4月25日) def md(m = 12, d = 31) "#{m}月#{d}日" end end
-
spec を実行すると無事にテストの通過を確認できた.
$ bin/rails spec /Users/hkob/.rbenv/versions/2.5.3/bin/ruby -I/Users/hkob/rails/attendance/vendor/bundle/ruby/2.5.0/gems/rspec-core-3.8.0/lib:/Users/hkob/rails/attendance/vendor/bundle/ruby/2.5.0/gems/rspec-support-3.8.0/lib /Users/hkob/rails/attendance/vendor/bundle/ruby/2.5.0/gems/rspec-core-3.8.0/exe/rspec --pattern spec/\*\*\{,/\*/\*\*\}/\*_spec.rb ApplicationHelper generate date strings wareki, ewareki wareki_num, wareki_ymd and md should have correct values Finished in 0.00728 seconds (files took 2.51 seconds to load) 1 example, 0 failures
長くなったので今日はここまで