マッチャーの組み合わせ
RSpecのマッチャーは、組み合わせて使用することができるように設計されています。これにより、期待する内容の正確な詳細を表現することができますが、それ以上のことは表現しません。これにより、過剰に指定された脆弱な仕様を書くことを避けることができます。マッチャーを使用して、期待する内容の本質的な側面のみを指定します。
以下のマッチャーは、マッチャーを引数として受け入れます。
- change { }.by(matcher)
- change { }.from(matcher).to(matcher)
- contain_exactly(matcher, matcher, matcher)
- end_with(matcher, matcher)
- include(matcher, matcher)
- include(:key => matcher, :other => matcher)
- match(arbitrary_nested_structure_with_matchers)
- output(matcher).to_stdout
- output(matcher).to_stderr
- raise_error(ErrorClass, matcher)
- start_with(matcher, matcher)
- throw_symbol(:sym, matcher)
- yield_with_args(matcher, matcher)
- yield_successive_args(matcher, matcher)
多くの組み込みマッチャーは、マッチャー引数を受け入れないようになっています。これは、厳密な意味論を持ち、マッチャー引数を許容しないためです。例えば、equal(some_object)は、実際の引数と期待する引数が同じオブジェクトへの参照である場合にのみパスするように設計されています。ここでは、マッチャー引数をサポートすることは意味がありません。
RSpecの組み込みマッチャーは、名詞句を使用して動詞形ではなく使用することができる1つ以上のエイリアスを持っています。また、失敗時の出力もカスタマイズされており、失敗メッセージも読みやすくなっています。
これらのエイリアスの完全なリストはここでは範囲外ですが、以下にいくつかの使用例を示します。
- be < 2=>- a_value < 2
- be > 2=>- a_value > 2
- be_an_instance_of=>- an_instance_of
- be_within=>- a_value_within
- contain_exactly=>- a_collection_containing_exactly
- end_with=>- a_string_ending_with,- ending_with
- match=>- a_string_matching
- start_with=>- a_string_starting_with
完全なリストについては、RSpec::MatchersモジュールのAPIドキュメントを参照してください。
changeを使ったマッチャの組み合わせ
ファイル名が「change_spec.rb」であるファイルが以下の内容であるとき:
RSpec.describe "Passing matchers to `change`" do
  specify "you can pass a matcher to `by`" do
    k = 0
    expect { k += 1.05 }.to change { k }.
      by( a_value_within(0.1).of(1.0) )
  end
  specify "you can pass matchers to `from` and `to`" do
    s = "food"
    expect { s = "barn" }.to change { s }.
      from( a_string_matching(/foo/) ).
      to( a_string_matching(/bar/) )
  end
end
rspec change_spec.rbを実行した場合、
全ての例がパスするはずです。
contain_exactlyを使ったマッチャの組み合わせ
ファイル名が「contain_exactly_spec.rb」であるファイルが以下の内容であるとき:
RSpec.describe "Passing matchers to `contain_exactly`" do
  specify "you can pass matchers in place of exact values" do
    expect(["barn", 2.45]).to contain_exactly(
      a_value_within(0.1).of(2.5),
      a_string_starting_with("bar")
    )
  end
end
rspec contain_exactly_spec.rbを実行した場合、
全ての例がパスするはずです。
end_withを使ったマッチャの組み合わせ
ファイル名が「end_with_spec.rb」であるファイルが以下の内容であるとき:
RSpec.describe "Passing matchers to `end_with`" do
  specify "you can pass matchers in place of exact values" do
    expect(["barn", "food", 2.45]).to end_with(
      a_string_matching("foo"),
      a_value > 2
    )
  end
end
rspec end_with_spec.rbを実行した場合、
全ての例がパスするはずです。
includeを使ったマッチャの組み合わせ
ファイル名が「include_spec.rb」であるファイルが以下の内容であるとき:
RSpec.describe "Passing matchers to `include`" do
  specify "you can use matchers in place of array values" do
    expect(["barn", 2.45]).to include( a_string_starting_with("bar") )
  end
  specify "you can use matchers in place of hash values" do
    expect(:a => "food", :b => "good").to include(:a => a_string_matching(/foo/))
  end
  specify "you can use matchers in place of hash keys" do
    expect("food" => "is good").to include( a_string_matching(/foo/) )
  end
end
rspec include_spec.rbを実行した場合、
全ての例がパスするはずです。
matchを使ったマッチャの組み合わせ
ファイル名が「match_spec.rb」であるファイルが以下の内容であるとき:
RSpec.describe "Passing matchers to `match`" do
  specify "you can match nested data structures against matchers" do
    hash = {
      :a => {
        :b => ["foo", 5.0],
        :c => { :d => 2.05 }
      }
    }
    expect(hash).to match(
      :a => {
        :b => a_collection_containing_exactly(
          a_string_starting_with("f"),
          an_instance_of(Float)
        ),
        :c => { :d => (a_value < 3) }
      }
    )
  end
end
rspec match_spec.rbを実行した場合、
全ての例がパスするはずです。
outputを使ったマッチャの組み合わせ
ファイル名が「output_spec.rb」であるファイルが以下の内容であるとき:
RSpec.describe "Passing matchers to `output`" do
  specify "you can pass a matcher in place of the output (to_stdout)" do
    expect {
      print 'foo'
    }.to output(a_string_starting_with('f')).to_stdout
  end
  specify "you can pass a matcher in place of the output (to_stderr)" do
    expect {
      warn 'foo'
    }.to output(a_string_starting_with('f')).to_stderr
  end
end
rspec output_spec.rbを実行した場合、
全ての例がパスするはずです。
raise_errorを使ったマッチャの組み合わせ
ファイル名が「raise_error_spec.rb」であるファイルが以下の内容であるとき:
RSpec.describe "Passing matchers to `raise_error`" do
  specify "you can pass a matcher in place of the message" do
    expect {
      raise RuntimeError, "this goes boom"
    }.to raise_error(RuntimeError, a_string_ending_with("boom"))
  end
end
rspec raise_error_spec.rbを実行した場合、
全ての例がパスするはずです。
start_withを使ったマッチャの組み合わせ
ファイル名が「start_with_spec.rb」であるファイルが以下の内容であるとき:
RSpec.describe "Passing matchers to `start_with`" do
  specify "you can pass matchers in place of exact values" do
    expect(["barn", "food", 2.45]).to start_with(
      a_string_matching("bar"),
      a_string_matching("foo")
    )
  end
end
rspec start_with_spec.rbを実行した場合、
全ての例がパスするはずです。