Help us understand the problem. What is going on with this article?

RSpec 3.4ではエラーが起きた行を出力結果に表示してくれるようになった

More than 3 years have passed since last update.

はじめに

2015年11月にRSpec 3.4がリリースされました。
派手は新機能はありませんが、実践的な機能改善が施され、テストのサイクルを効率よく回せるようになっています。

主な新機能についてはこちらの公式日本語訳(!)をご覧ください。

公式ブログには以下のような新機能が紹介されています。

  • Core: Bisect アルゴリズムの改善
  • Core: 失敗時の出力の改善
    • 複数行のコードスニペット
    • coderayがインストール済みの場合、シンタックスハイライトが有効に
    • 失敗元の行の検出の改善
  • Expectations: 複合エクスペクテーションの失敗時メッセージの改善
  • Expectations: match マッチャへの with_captures の追加
  • Rails: ActiveJob のための新しい have_enqueued_job マッチャ

この中で僕が一番注目したのが「 失敗元の行の検出の改善 」です。
ただ、残念なことにブログにはコードや出力結果の例が載っていなかったので、自分で実際に動かして確認してみました。

この記事ではその内容を紹介します。

テストコード

以下はContactクラスのnameメソッドをテストするテストコードです。
nameメソッドはfirstnameとlastnameを半角スペースで連結します。

spec/models/contact_spec.rb
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 に変えています。

app/models/contact.rb
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)>'

Screen Shot 2015-11-15 at 15.21.30.png

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)>'

Screen Shot 2015-11-15 at 15.21.42.png

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.3についてはこちら

RSpec 3.3で導入された新機能についてはこちらにまとめてあります。

実用的な新機能が盛りだくさん!RSpec 3.3 完全ガイド - Qiita

「RSpec 3.4で改善されたBisectアルゴリズムって何?」と思ったりした人は上の記事を読んでみてください。

サンプルコードはEveryday Railsで使用しているコードです

サンプルコードは電子書籍「 Everyday Rails - RSpecによるRailsテスト入門 」で使用しているコードです。
RSpec初心者の方に最適な一冊ですので、よかったら読んでみてください。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした