LoginSignup
28
29

More than 5 years have passed since last update.

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

Last updated at Posted at 2015-11-15

はじめに

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初心者の方に最適な一冊ですので、よかったら読んでみてください。

28
29
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
28
29