Rails tips: RSpecでコード実行回数をスマートに数える(翻訳)

概要

原著者の許諾を得て翻訳・公開いたします。

Rails tips: RSpecでコード実行回数をスマートに数える(翻訳)

RSpecを使って、指定のメソッドが呼び出される回数をexpectで指定することができます。その方法を説明する前に、呼び出し回数を知ることの重要性についてお話します。これはコードの振る舞いを制御するためのものです。説明のため、わざと誤ったコードを書いてみます。

class SomeClass
  def something
    @something = service.call
  end
end

これのどこが誤りかおわかりでしょうか。ここではメモ化によって、SomeClass#somethingが呼ばれるたびにservice.callが2回以上呼ばれることのないようにしたいと考えています。しかしメモ化の||=演算子ではなく=演算子が使われているため、期待どおりメモ化されていません。

このコードに対して次のようなテストを書くとします。

expect(some_class_instance).to have_received(:something)

このテストでは、メモ化が行われていないという誤りを検出できません。上のようなシンプルな例ならともかく、たとえばservice.callが外部APIを呼び出していて、限りあるリソースを食いつぶしているとしたら非常に残念ことになります。これを回避するには、メソッド呼び出しが何回行われるべきかを指定します。

expect(some_class_instance).to have_received(:something).once

このexpectationを用いることで誤りが検出されます。しかしTDD(テスト駆動開発)アプローチではこのテストは決して作られることはないでしょう。このことから、TDDを用いるとともにexpectationを詳細に書くことの重要性がわかります。

2回以上のメッセージ呼び出しのexpectationをRSpec文法で書くには

コードが2回以上呼び出されたかどうかをテストしたい場合や、少なくとも2回または3回以上呼び出されたかどうかをテストしたい場合はどのように書けばよいでしょうか?RSpecの文法でこれらを指定することもできます。

  • メッセージがn回呼び出されるexpectation:
expect(some_class_instance).to have_received(:something).once
expect(some_class_instance).to have_received(:something).twice
expect(some_class_instance).to have_received(:something).exactly(3).times
  • メッセージがn回以上呼び出されるexpectation:
expect(some_class_instance).to have_received(:something).at_least(:once)
expect(some_class_instance).to have_received(:something).at_least(:twice)
expect(some_class_instance).to have_received(:something).at_last(3).times
  • メッセージの呼び出しが n回以下のexpectation:
expect(some_class_instance).to have_received(:something).at_most(:once)
expect(some_class_instance).to have_received(:something).at_most(:twice)
expect(some_class_instance).to have_received(:something).at_most(3).times

RSpec & TDDの電子書籍を無料でダウンロード

もっと稼ぎたい方や会社をさらに発展させたい方へ: テスティングのスキルの重要性にお気づきでしょうか?テストを正しく書き始めることが、唯一のファーストステップです。無料でダウンロードいただける私の書籍『RSpec & Test Driven Developmentの無料ebook』をどうぞお役立てください。

関連記事

Rails: テスティングアンチパターン –前編(翻訳)

ソフトウェアテストでstubを使うコストを考える(翻訳)

デザインも頼めるシステム開発会社をお探しならBPS株式会社までどうぞ 開発エンジニア積極採用中です! Ruby on Rails の開発なら実績豊富なBPS

この記事の著者

hachi8833

Twitter: @hachi8833、GitHub: @hachi8833 コボラー、ITコンサル、ローカライズ業界、Rails開発を経てTechRachoの編集・記事作成を担当。 これまでにRuby on Rails チュートリアル第2版の半分ほど、Railsガイドの初期翻訳ではほぼすべてを翻訳。その後も折に触れてそれぞれ一部を翻訳。 かと思うと、正規表現の粋を尽くした日本語エラーチェックサービス enno.jpを運営。 実は最近Go言語が好き。 仕事に関係ないすっとこブログ「あけてくれ」は2000年頃から多少の中断をはさんで継続、現在はnote.muに移転。

hachi8833の書いた記事

週刊Railsウォッチ

インフラ

ActiveSupport探訪シリーズ