10

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])

Regards

pierallard
  • 3,326
  • 3
  • 21
  • 48

5 Answers5

36

There is a match_array matcher in RSpec which does this:

http://rubydoc.info/github/rspec/rspec-expectations/RSpec/Matchers:match_array

Andy Waite
  • 10,785
  • 4
  • 33
  • 47
12

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
Stefan
  • 109,145
  • 14
  • 143
  • 218
3

This should work.

[:b, :a, :c].sort == [:a, :b, :c].sort
3

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

Swaps
  • 1,450
  • 24
  • 31
2

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
apneadiving
  • 114,565
  • 26
  • 219
  • 213