yield
マッチャー
メソッドが yield
するかどうか、何回 yield
するか、引数を伴って yield
するか、およびその引数が何であるかを指定するための関連する4つのマッチャーがあります。
yield_control
は、テスト対象のメソッドがyield
する場合にマッチします。引数がyield
されるかどうかは関係ありません。yield_with_args
は、テスト対象のメソッドが引数を伴ってyield
する場合にマッチします。このマッチャーに引数が指定されている場合、実際の引数が期待される引数と一致する場合にのみパスします。一致の判定には===
または==
が使用されます。yield_with_no_args
は、テスト対象のメソッドが引数なしでyield
する場合にマッチします。yield_successive_args
は、イテレータ向けに設計されており、テスト対象のメソッドがこのマッチャーに渡された引数の数と同じ回数だけyield
し、実際の引数が期待される引数と一致する場合にマッチします。一致の判定には===
または==
が使用されます。
注意: あなたの expect
ブロックは、ブロックとしてメソッドに渡される引数を受け入れる必要があります。これは、マッチャーがメ ソッドが yield
するかどうか、そして yield
する場合は何回、どのような引数が yield
されるかを検出するための「プローブ」として機能します。
バックグラウンド
次の内容で "my_class.rb" という名前のファイルがあるとします:
class MyClass
def self.yield_once_with(*args)
yield *args
end
def self.yield_twice_with(*args)
2.times { yield *args }
end
def self.raw_yield
yield
end
def self.dont_yield
end
end
yield_control
マッチャー
次の内容で "yield_control_spec.rb" という名前のファイルがあるとします:
require './my_class'
RSpec.describe "yield_control matcher" do
specify { expect { |b| MyClass.yield_once_with(1, &b) }.to yield_control }
specify { expect { |b| MyClass.dont_yield(&b) }.not_to yield_control }
specify { expect { |b| MyClass.yield_twice_with(1, &b) }.to yield_control.twice }
specify { expect { |b| MyClass.yield_twice_with(1, &b) }.to yield_control.exactly(2).times }
specify { expect { |b| MyClass.yield_twice_with(1, &b) }.to yield_control.at_least(1) }
specify { expect { |b| MyClass.yield_twice_with(1, &b) }.to yield_control.at_most(3).times }
# deliberate failures
specify { expect { |b| MyClass.yield_once_with(1, &b) }.not_to yield_control }
specify { expect { |b| MyClass.dont_yield(&b) }.to yield_control }
specify { expect { |b| MyClass.yield_once_with(1, &b) }.to yield_control.at_least(2).times }
specify { expect { |b| MyClass.yield_twice_with(1, &b) }.not_to yield_control.twice }
specify { expect { |b| MyClass.yield_twice_with(1, &b) }.not_to yield_control.at_least(2).times }
specify { expect { |b| MyClass.yield_twice_with(1, &b) }.not_to yield_control.at_least(1) }
specify { expect { |b| MyClass.yield_twice_with(1, &b) }.not_to yield_control.at_most(3).times }
end
rspec yield_control_spec.rb
を実行すると、
出力には以下のすべてが含まれているはずです:
| 13 の例、7 の失敗 |
| 与えられたブロックがコントロールを yield
することを期待しました |
| 与えられたブロックがコントロールを yield
しないことを期待しました |
| 与えられたブロックが少なくとも2回コントロールを yield
しないことを期待しました |
| 与えられたブロックが最大3回コントロールを yield
しないことを期待しました |
yield_with_args
マッチャー
次の内容で "yield_with_args_spec.rb" という名前のファイルがあるとします:
require './my_class'
RSpec.describe "yield_with_args matcher" do
specify { expect { |b| MyClass.yield_once_with("foo", &b) }.to yield_with_args }
specify { expect { |b| MyClass.yield_once_with("foo", &b) }.to yield_with_args("foo") }
specify { expect { |b| MyClass.yield_once_with("foo", &b) }.to yield_with_args(String) }
specify { expect { |b| MyClass.yield_once_with("foo", &b) }.to yield_with_args(/oo/) }
specify { expect { |b| MyClass.yield_once_with("foo", "bar", &b) }.to yield_with_args("foo", "bar") }
specify { expect { |b| MyClass.yield_once_with("foo", "bar", &b) }.to yield_with_args(String, String) }
specify { expect { |b| MyClass.yield_once_with("foo", "bar", &b) }.to yield_with_args(/fo/, /ar/) }
specify { expect { |b| MyClass.yield_once_with("foo", "bar", &b) }.not_to yield_with_args(17, "baz") }
# deliberate failures
specify { expect { |b| MyClass.yield_once_with("foo", &b) }.not_to yield_with_args }
specify { expect { |b| MyClass.yield_once_with("foo", &b) }.not_to yield_with_args("foo") }
specify { expect { |b| MyClass.yield_once_with("foo", &b) }.not_to yield_with_args(String) }
specify { expect { |b| MyClass.yield_once_with("foo", &b) }.not_to yield_with_args(/oo/) }
specify { expect { |b| MyClass.yield_once_with("foo", "bar", &b) }.not_to yield_with_args("foo", "bar") }
specify { expect { |b| MyClass.yield_once_with("foo", "bar", &b) }.to yield_with_args(17, "baz") }
end
rspec yield_with_args_spec.rb
を実行すると、
出力には以下のすべてが含まれているはずです:
| 14 の 例、6 の失敗 |
| 与えられたブロックが引数を伴って yield
しないことを期待しました |
| 与えられたブロックが引数を伴って yield
しないことを期待しましたが、実際には yield
されました |
| 与えられたブロックが引数を伴って yield
することを期待しましたが、実際には予期しない引数で yield
されました |
yield_with_no_args
マッチャー
Given ファイル名が "yield_with_no_args_spec.rb" のファイルがあるとき:
require './my_class'
RSpec.describe "yield_with_no_args matcher" do
specify { expect { |b| MyClass.raw_yield(&b) }.to yield_with_no_args }
specify { expect { |b| MyClass.dont_yield(&b) }.not_to yield_with_no_args }
specify { expect { |b| MyClass.yield_once_with("a", &b) }.not_to yield_with_no_args }
# deliberate failures
specify { expect { |b| MyClass.raw_yield(&b) }.not_to yield_with_no_args }
specify { expect { |b| MyClass.dont_yield(&b) }.to yield_with_no_args }
specify { expect { |b| MyClass.yield_once_with("a", &b) }.to yield_with_no_args }
end
When rspec yield_with_no_args_spec.rb
を実行すると:
Then 出力には以下のすべてが含まれているはずです:
| 6 つの例、3 つの失敗 | | 引数なしでブロックが yield されないことを期待しましたが、実際には yield されました | | 引数なしでブロックが yield されることを期待しましたが、実際には yield されませんでした | | 引数を伴ってブロックが yield されることを期待しましたが、実際には引数 ["a"] とともに yield されました |
yield_successive_args
マッチャー
Given ファイル名が "yield_successive_args_spec.rb" のファイルがあるとき:
def array
[1, 2, 3]
end
def array_of_tuples
[[:a, :b], [:c, :d]]
end
RSpec.describe "yield_successive_args matcher" do
specify { expect { |b| array.each(&b) }.to yield_successive_args(1, 2, 3) }
specify { expect { |b| array_of_tuples.each(&b) }.to yield_successive_args([:a, :b], [:c, :d]) }
specify { expect { |b| array.each(&b) }.to yield_successive_args(Integer, Integer, Integer) }
specify { expect { |b| array.each(&b) }.not_to yield_successive_args(1, 2) }
# deliberate failures
specify { expect { |b| array.each(&b) }.not_to yield_successive_args(1, 2, 3) }
specify { expect { |b| array_of_tuples.each(&b) }.not_to yield_successive_args([:a, :b], [:c, :d]) }
specify { expect { |b| array.each(&b) }.not_to yield_successive_args(Integer, Integer, Integer) }
specify { expect { |b| array.each(&b) }.to yield_successive_args(1, 2) }
end
When rspec yield_successive_args_spec.rb
を実行すると:
Then 出力には以下のすべてが含まれているはずです:
| 8 つの例、4 つの失敗 | | 引数を連続してブロックが yield されないことを期待しましたが、期待された引数で yield されました | | 引数を連続してブロックが yield されることを期待しましたが、予期しない引数で yield されました |