Reputation: 3371
I'm not sure if its a Rspec question, but I only encountred this problem on Rspec tests.
I want to check if an array is equal to another array, regardless of the elements order :
[:b, :a, :c] =?= [:a, :b, :c]
My current version :
my_array.length.should == 3
my_array.should include(:a)
my_array.should include(:b)
my_array.should include(:c)
Is there any method on Rspec, ruby or Rails for do something like this :
my_array.should have_same_elements_than([:a, :b, :c])
Upvotes: 10
Views: 13612
Reputation: 1548
I think all answers seems to be pretty old.
Latest matcher is contain_exactly
.
You can simply do -
expect([:b, :a, :c]).to contain_exactly(:a, :b, :c)
Please not that in contain_exactly
we don't pass a whole array, instead pass separate
elements.
Ref - Rspec Guide
Upvotes: 3
Reputation: 114138
You can use the =~
operator:
[:b, :a, :c].should =~ [:a, :b, :c] # pass
From the docs:
Passes if actual contains all of the expected regardless of order. This works for collections. Pass in multiple args and it will only pass if all args are found in collection.
For RSpec's expect syntax there's match_array
:
expect([:b, :a, :c]).to match_array([:a, :b, :c]) # pass
or contain_exactly
if you're passing single elements:
expect([:b, :a, :c]).to contain_exactly(:a, :b, :c) # pass
Upvotes: 12
Reputation: 115511
Here was my wrong matcher (thanks @steenslag):
RSpec::Matchers.define :be_same_array_as do |expected_array|
match do |actual_array|
(actual_array | expected_array) - (actual_array & expected_array) == []
end
end
Other solutions:
use the builtin matcher, best solution
use Set
:
Something like:
require 'set'
RSpec::Matchers.define :be_same_array_as do |expected_array|
match do |actual_array|
Set.new(actual_array) == Set.new(expected_array)
end
end
Upvotes: 2
Reputation: 11076
There is a match_array
matcher in RSpec which does this:
http://rubydoc.info/github/rspec/rspec-expectations/RSpec/Matchers:match_array
Upvotes: 37