Rspec : is there a matcher to match array of arrays, not testing order
Asked Answered
R

3

8

I try to test if two arrays of arrays contain same elements, without testing order of elements. (Rails 5.2 / Rspec-rails 3.8.2)

exemple :

[['a1', 'a2'], ['b1', 'b2']]
[['b2', 'b1'], ['a2', 'a1']]

I tried with match_array and with contain_exactly but this works only for the first level of my array.


  tab1 = [['a1', 'a2'], ['b1', 'b2']]
  tab2 = [['b1', 'b2'], ['a1', 'a2']]
  tab3 = [['a2', 'a1'], ['b2', 'b1']]
  tab4 = [['b2', 'b1'], ['a2', 'a1']]

  expect(tab1).to match_array tab2  # true
  expect(tab1).to match_array tab3  # false
  expect(tab1).to match_array tab4  # false

Is there a matcher to do this ? Or maybe a simple way with composable matchers ? Thanks

EDIT The solution I find is to do :

expect(tab1).to contain_exactly(contain_exactly('a1', 'a2'),
                                contain_exactly('b1', 'b2'))

but I would like to find something like this

expect(tab1).to ....... tab2
Reglet answered 21/10, 2019 at 8:12 Comment(0)
R
4

I think I found a solution. Thanks to comment if you think that it does not always work.

it 'checks that arrays contain the same elements (do not check order)' do
  tab1 = [['a1', 'a2'], ['b1', 'b2']]
  tab4 = [['b2', 'b1'], ['a2', 'a1']]
  expect(tab1.map(&:sort)).to match_array(tab4.map(&:sort))
end
Reglet answered 21/10, 2019 at 12:17 Comment(0)
H
7

The other answers here are inaccurate. You should use the contain_exactly or match_array matcher, depending on the scenario. See https://rspec.info/documentation/3.12/rspec-expectations/

Harmonia answered 22/10, 2019 at 4:8 Comment(0)
G
5

There are two simple ways to achieve

 describe 'two array with random order' do

    it 'arrays are equals if content is same' do

      tab1 = [['a1', 'a2'], ['b1', 'b2']]
      tab2 = [['b1', 'b2'], ['a1', 'a2']]
      tab3 = [['a2', 'a1'], ['b2', 'b1']]
      tab4 = [['b2', 'b1'], ['a2', 'a1']]

      #option 1
      expect(tab1.sort).to match_array tab2.sort
      expect(tab1.sort).not_to match_array tab3.sort
      expect(tab1.map(&:sort).sort).to match_array tab3.map(&:sort).sort
      expect(tab1.sort).not_to match_array tab4.sort

      # Option 2
      expect(tab1).to include *tab2
      expect(tab1).not_to include *tab3
      expect(tab1.map(&:sort)).to include *tab3.map(&:sort)
      expect(tab1).not_to include *tab4
    end
  end
Gallman answered 21/10, 2019 at 11:11 Comment(3)
I want tab1 to match all tabs (2, 3 and 4)Reglet
@Reglet modified the answer. Checkout map(&:sort) linesGallman
check my answer. I don't think I have to sort tab, just the tabs inside. match_array don't care about order.Reglet
R
4

I think I found a solution. Thanks to comment if you think that it does not always work.

it 'checks that arrays contain the same elements (do not check order)' do
  tab1 = [['a1', 'a2'], ['b1', 'b2']]
  tab4 = [['b2', 'b1'], ['a2', 'a1']]
  expect(tab1.map(&:sort)).to match_array(tab4.map(&:sort))
end
Reglet answered 21/10, 2019 at 12:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.