はじめに
2015年11月にRSpec 3.4がリリースされました。
派手は新機能はありませんが、実践的な機能改善が施され、テストのサイクルを効率よく回せるようになっています。
主な新機能についてはこちらの公式日本語訳(!)をご覧ください。
今回のリリースから日本語訳を書くことにしました :) / RSpec 3.4 がリリースされました! https://t.co/HpJkYyEMV7
— Yuji Nakayama (@nkym37) November 14, 2015
公式ブログには以下のような新機能が紹介されています。
- Core: Bisect アルゴリズムの改善
- Core: 失敗時の出力の改善
- 複数行のコードスニペット
- coderayがインストール済みの場合、シンタックスハイライトが有効に
- 失敗元の行の検出の改善
- Expectations: 複合エクスペクテーションの失敗時メッセージの改善
- Expectations: match マッチャへの with_captures の追加
- Rails: ActiveJob のための新しい have_enqueued_job マッチャ
この中で僕が一番注目したのが「 失敗元の行の検出の改善 」です。
ただ、残念なことにブログにはコードや出力結果の例が載っていなかったので、自分で実際に動かして確認してみました。
この記事ではその内容を紹介します。
テストコード
以下はContactクラスのnameメソッドをテストするテストコードです。
nameメソッドはfirstnameとlastnameを半角スペースで連結します。
describe Contact do
# ...
it "returns a contact's full name as a string" do
contact = build_stubbed(:contact,
firstname: 'Jane',
lastname: 'Smith'
)
expect(contact.name).to eq 'Jane Smith'
end
# ...
end
Contactクラスの実装
以下はContactクラスの実装です。
ただし、テストが失敗するようにわざと join の引数を半角スペースではなく 1 に変えています。
class Contact < ActiveRecord::Base
# ...
def name
# わざと join の引数を 1 に変えた
[firstname, lastname].join(1)
end
# ...
end
RSpec 3.3での実行結果
RSpec 3.3では "Failure/Error:" にテストが失敗したエクスペクテーション(expect(...).to ...
)が表示されています。
Failures:
1) Contact returns a contact's full name as a string
Failure/Error: expect(contact.name).to eq 'Jane Smith'
TypeError:
no implicit conversion of Fixnum into String
# ./app/models/contact.rb:11:in `join'
# ./app/models/contact.rb:11:in `name'
# ./spec/models/contact_spec.rb:18:in `block (2 levels) in <top (required)>'
# ./spec/rails_helper.rb:40:in `block (3 levels) in <top (required)>'
# ./spec/rails_helper.rb:39:in `block (2 levels) in <top (required)>'
RSpec 3.4での実行結果
RSpec 3.4では "Failure/Error:" にエラーが発生した行(Modelのコード)が表示されています。
Failures:
1) Contact returns a contact's full name as a string
Failure/Error: [firstname, lastname].join(1)
TypeError:
no implicit conversion of Fixnum into String
# ./app/models/contact.rb:11:in `join'
# ./app/models/contact.rb:11:in `name'
# ./spec/models/contact_spec.rb:18:in `block (2 levels) in <top (required)>'
# ./spec/rails_helper.rb:40:in `block (3 levels) in <top (required)>'
# ./spec/rails_helper.rb:39:in `block (2 levels) in <top (required)>'
RSpec 3.4で失敗行を表示するルール
RSpec 3.3ではいつでもspecファイル(xxx_spec.rb)内で失敗した行を "Failure/Error:" として表示しています。
RSpec 3.4では config.project_source_dirs
で定義されたディレクトリ内にあるコードが出力対象になります。
config.project_source_dirs
のデフォルト値は ['spec', 'lib', 'app']
です。
上のサンプルコードでは app/models/contact.rb
内でエラーが起きたので、 "Failure/Error:" にModelのコードが表示されています。
Ruby本体やgemのコードは config.project_source_dirs
に含まれないので、 "Failure/Error:" に表示されません。
まとめ
上のコードで示したように、RSpec 3.4ではRSpec 3.3に比べてエラーの発生箇所に近い場所を表示してくれるので、エラーの原因を特定しやすくなりました。
便利ですね!!
参考文献
- RSpec 3.4 がリリースされました!
- Improve logic that finds the failure line to print. · rspec/rspec-core@aadd339
RSpec 3.3についてはこちら
RSpec 3.3で導入された新機能についてはこちらにまとめてあります。
実用的な新機能が盛りだくさん!RSpec 3.3 完全ガイド - Qiita
「RSpec 3.4で改善されたBisectアルゴリズムって何?」と思ったりした人は上の記事を読んでみてください。
サンプルコードはEveryday Railsで使用しているコードです
サンプルコードは電子書籍「 Everyday Rails - RSpecによるRailsテスト入門 」で使用しているコードです。
RSpec初心者の方に最適な一冊ですので、よかったら読んでみてください。