65

I use new RSpec syntax (expect instead of should) and I'd like to test if an array includes elements of another array. In the old syntax it would be:

array1.should include(array2)

In the new syntax I tried to write:

expect(array1).to include(array2)

but I got an error (that's quite reasonable):

TypeError: wrong argument type Array (expected Module)

Then I wrote:

expect(array1).to be_include(array2)

but it's ugly and it didn't work: apparently it checks if array2 is element of array1 not if all elements of array2 are included in array1.

Finally I wrote:

expect(array1 & array2).to eq(array2)

but it's not the prettiest solution. Do you know any better?

Stephen Ostermiller
  • 23,933
  • 14
  • 88
  • 109
mrzasa
  • 22,895
  • 11
  • 56
  • 94

3 Answers3

111

You need to splat the arguments when passing them to the array matcher:

expect(array1).to include(*array2)

This is because you usually list out literals, e.g.:

expect([1, 2, 3]).to include(1, 2)

That said, expect(array1).to include(array2) should not fail with a weird error like you got, and in fact it works and passes in an example like:

  it 'includes a sub array' do
    array2 = ["a"]
    array1 = [array2]
    expect(array1).to include(array2)
  end
Myron Marston
  • 21,452
  • 5
  • 64
  • 63
  • how I can test no inclusion? I tried `not_to include` but it raised an error: `expect([1, 2, 3]).not_to include(1)` raises `RSpec::Expectations::ExpectationNotMetError: expected [1, 2, 3] not to include 1` – Iván Cortés Oct 26 '16 at 17:12
  • @IvánCortésRomero Your example is failing because `1` is in fact included in `[1,2,3]`, but you're telling rspec to expect it not to be. This passes: `expect([1, 2, 3]).not_to include(4)`. – Kelvin Mar 29 '17 at 15:57
13

Try this one:

expect(array1).to include *array2
William Hu
  • 15,423
  • 11
  • 100
  • 121
5

To test if one array is subset of another array its perhapse good idea to introduce set. And then you can write it like this... (Solution uses Set#subset?)

require "set"

describe "Small test" do
  let(:array1) { %w{a b c d} }
  let(:array2) { %w{b c} }

  let(:array1_as_set) { array1.to_set }
  let(:array2_as_set) { array2.to_set }

  subject { array2_as_set }

  context "inclusion of w/ \"expect\"" do
    it { expect(subject).to be_subset(array1_as_set) }
  end

  context "inclusion of w/ \"should\"" do
    it { should be_subset(array1_as_set) }
  end

end
Oto Brglez
  • 4,113
  • 1
  • 26
  • 33