カスタムマッチャーの定義
rspec-expectationsは、カスタムマッチャーを定義するためのDSLを提供しています。これらは、アプリケーションのドメインでの期待値を表現するのに便利です。
裏側では、RSpec::Matchers.define
はdefine
ブロックをシングルトンクラスのコンテキストで評価します。より複雑なマッチャーを作成し、自分自身でClass
アプローチを使用したい場合は、弊社のAPI
ドキュメントに移動して、MatcherProtocol
についてのドキュメントを読んでください。
デフォルトのメッセージを持つマッチャーの定義
「matcher_with_default_message_spec.rb」という名前のファイルがあるとします。
require 'rspec/expectations'
RSpec::Matchers.define :be_a_multiple_of do |expected|
match do |actual|
actual % expected == 0
end
end
RSpec.describe 9 do
it { is_expected.to be_a_multiple_of(3) }
end
RSpec.describe 9 do
it { is_expected.not_to be_a_multiple_of(4) }
end
# fail intentionally to generate expected output
RSpec.describe 9 do
it { is_expected.to be_a_multiple_of(4) }
end
# fail intentionally to generate expected output
RSpec.describe 9 do
it { is_expected.not_to be_a_multiple_of(3) }
end
次のコマンドを実行すると:
rspec ./matcher_with_default_message_spec.rb --format documentation
次の結果が得られるはずです:
- 終了ステータスは0ではないはずです
- 出力には「is expected to be a multiple of 3」という文言が含まれているはずです
- 出力には「is expected not to be a multiple of 4」という文言が含まれているはずです
- 出力には「Failure/Error: it { is_expected.to be_a_multiple_of(4) }」という文言が含まれているはずです
- 出力には「Failure/Error: it { is_expected.not_to be_a_multiple_of(3) }」という文言が含まれているはずです
- 出力には「4 examples, 2 failures」という文言が含まれているはずです
- 出力には「expected 9 to be a multiple of 4」という文言が含まれているはずです
- 出力には「expected 9 not to be a multiple of 3」という文言が含まれているはずです。
failure_messageのオーバーライド
「matcher_with_failure_message_spec.rb」という名前のファイルがあるとします。
require 'rspec/expectations'
RSpec::Matchers.define :be_a_multiple_of do |expected|
match do |actual|
actual % expected == 0
end
failure_message do |actual|
"expected that #{actual} would be a multiple of #{expected}"
end
end
# fail intentionally to generate expected output
RSpec.describe 9 do
it { is_expected.to be_a_multiple_of(4) }
end
次のコマンドを実行すると:
rspec ./matcher_with_failure_message_spec.rb
次の結果が得られるはずです:
- 終了ステータスは0ではないはずです
- 標準出力には「1 example, 1 failure」という文言が含まれているはずです
- 標準出力には「expected that 9 would be a multiple of 4」という文言が含まれているはずです。
failure_message_when_negatedのオーバーライド
「matcher_with_failure_for_message_spec.rb」という名前のファイルがあるとします。
require 'rspec/expectations'
RSpec::Matchers.define :be_a_multiple_of do |expected|
match do |actual|
actual % expected == 0
end
failure_message_when_negated do |actual|
"expected that #{actual} would not be a multiple of #{expected}"
end
end
# fail intentionally to generate expected output
RSpec.describe 9 do
it { is_expected.not_to be_a_multiple_of(3) }
end
次 のコマンドを実行すると:
rspec ./matcher_with_failure_for_message_spec.rb
次の結果が得られるはずです:
- 終了ステータスは0ではないはずです
- 標準出力には「1 example, 1 failure」という文言が含まれているはずです。
And 標準出力には "expected that 9 would not be a multiple of 3" が含まれている必要があります。
説明の上書き
Given "matcher_overriding_description_spec.rb" という名前のファイルが次の内容であるとき:
require 'rspec/expectations'
RSpec::Matchers.define :be_a_multiple_of do |expected|
match do |actual|
actual % expected == 0
end
description do
"be multiple of #{expected}"
end
end
RSpec.describe 9 do
it { is_expected.to be_a_multiple_of(3) }
end
RSpec.describe 9 do
it { is_expected.not_to be_a_multiple_of(4) }
end
When rspec ./matcher_overriding_description_spec.rb --format documentation
を実行するとき
Then 終了ステータスは 0 である必要があります
And 標準出力には "2 examples, 0 failures" が含まれている必要があります
And 標準出力には "is expected to be multiple of 3" が含まれている必要があります
And 標準出力には "is expected not to be multiple of 4" が含まれている必要があります。
引数なしで
Given "matcher_with_no_args_spec.rb" という名前のファイルが次の内容であるとき:
require 'rspec/expectations'
RSpec::Matchers.define :have_7_fingers do
match do |thing|
thing.fingers.length == 7
end
end
class Thing
def fingers; (1..7).collect {"finger"}; end
end
RSpec.describe Thing do
it { is_expected.to have_7_fingers }
end
When rspec ./matcher_with_no_args_spec.rb --format documentation
を実行するとき
Then 終了ステータスは 0 である必要があります
And 標準出力には "1 example, 0 failures" が含まれている必要があります
And 標準出力には "is expected to have 7 fingers" が含まれている必要があります。
複数の引数で
Given "matcher_with_multiple_args_spec.rb" という名前のファイルが次の内容であるとき:
require 'rspec/expectations'
RSpec::Matchers.define :be_the_sum_of do |a,b,c,d|
match do |sum|
a + b + c + d == sum
end
end
RSpec.describe 10 do
it { is_expected.to be_the_sum_of(1,2,3,4) }
end
When rspec ./matcher_with_multiple_args_spec.rb --format documentation
を実行するとき
Then 終了ステータスは 0 である必要があります
And 標準出力には "1 example, 0 failures" が含まれている必要があります
And 標準出力には "is expected to be the sum of 1, 2, 3, and 4" が含まれている必要があります。
ブロック引数で
Given "matcher_with_block_arg_spec.rb" という名前のファイルが次の内容であるとき:
require 'rspec/expectations'
RSpec::Matchers.define :be_lazily_equal_to do
match do |obj|
obj == block_arg.call
end
description { "be lazily equal to #{block_arg.call}" }
end
RSpec.describe 10 do
it { is_expected.to be_lazily_equal_to { 10 } }
end
When rspec ./matcher_with_block_arg_spec.rb --format documentation
を実行するとき
Then 終了ステータスは 0 である必要があります
And 標準出力には "1 example, 0 failures" が含まれている必要があります
And 標準出力には "is expected to be lazily equal to 10" が含まれている必要があります。
ヘルパーメソッドを使用して
Given "matcher_with_internal_helper_spec.rb" という名前のファイルが次の内容であるとき:
require 'rspec/expectations'
RSpec::Matchers.define :have_same_elements_as do |sample|
match do |actual|
similar?(sample, actual)
end
def similar?(a, b)
a.sort == b.sort
end
end
RSpec.describe "these two arrays" do
specify "should be similar" do
expect([1,2,3]).to have_same_elements_as([2,3,1])
end
end
When rspec ./matcher_with_internal_helper_spec.rb
を実行するとき
Then 終了ステータスは 0 である必要があります
And 標準出力には "1 example, 0 failures" が含まれている必要があります。
モジュール内でスコープ化された場合
Given "scoped_matcher_spec.rb" という名前のファイルが次の内容であるとき:
require 'rspec/expectations'
module MyHelpers
extend RSpec::Matchers::DSL
matcher :be_just_like do |expected|
match {|actual| actual == expected}
end
end
RSpec.describe "group with MyHelpers" do
include MyHelpers
it "has access to the defined matcher" do
expect(5).to be_just_like(5)
end
end
RSpec.describe "group without MyHelpers" do
it "does not have access to the defined matcher" do
expect do
expect(5).to be_just_like(5)
end.to raise_exception
end
end
When rspec ./scoped_matcher_spec.rb
を実行するとき
その後、stdoutには「2つの例、0つの失敗」と表示される必要があります。