Here is the assistant that I came up with for this problem, it is quite simple and should work with a good degree of efficiency.
require 'set' RSpec::Matchers.define :yield_in_any_order do |*values| expected_yields = Set[*values] actual_yields = Set[] match do |blk| blk[->(x){ actual_yields << x }]
I highlighted lines containing most of the important logic with # *** . This is a fairly simple implementation.
Using
Just put it in a file under spec/support/matchers/ and make sure you require it from the specifications that need it. Most of the time, people simply add a line like this:
Dir[File.dirname(__FILE__) + "/support/**/*.rb"].each {|f| require f}
to their spec_helper.rb , but if you have a lot of support files, and they are not needed everywhere, it can get a little big, so you can only include it where it is used.
Then, in the specs themselves, use is like using any other compliant match:
class Iterator def custom_iterator (1..10).to_a.shuffle.each { |x| yield x } end end describe "Matcher" do it "works" do iter = Iterator.new expect { |b| iter.custom_iterator(&b) }.to yield_in_any_order(*(1..10)) end end
amnn
source share