Rspec: "array.should == another_array", но без заботы о заказе

Я часто хочу сравнить массивы и убедиться, что они содержат одинаковые элементы в любом порядке. Есть ли краткий способ сделать это в RSpec?

Вот методы, которые не приемлемы:

#to_set

Например:

expect(array.to_set).to eq another_array.to_set

или же

array.to_set.should == another_array.to_set

Это не удается, когда массивы содержат повторяющиеся элементы.

#sort

Например:

expect(array.sort).to eq another_array.sort

или же

array.sort.should == another_array.sort

Это терпит неудачу, когда элементы массива не реализуют #<=>

Ответ 1

Используйте match_array, который принимает другой массив в качестве аргумента, или contain_exactly, который принимает каждый элемент в качестве отдельного аргумента и иногда полезен для удобства чтения. (документы)

Примеры:

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

или же

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

Ответ 2

Попробуйте array.should =~ another_array

Лучшая документация, которую я могу найти, это сам код, который здесь.

Ответ 3

Так как RSpec 2.11 вы также можете использовать match_array.

array.should match_array(another_array)

Что может быть более читаемым в некоторых случаях.

[1, 2, 3].should =~ [2, 3, 1]
# vs
[1, 2, 3].should match_array([2, 3, 1])

Ответ 4

Я обнаружил, что =~ непредсказуем, и он потерпел неудачу без видимых причин. В прошлом 2.14 вы должны, вероятно, использовать

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

Ответ 5

Для RSpec 3 используйте contain_exactly:

См. Https://relishapp.com/rspec/rspec-expectations/v/3-2/docs/built-in-matchers/contain-exactly-matcher для подробностей, но здесь выписка:

Сочетание contains_exactly обеспечивает способ проверки массивов друг против друга таким образом, чтобы игнорировать различия в порядке между фактическим и ожидаемым массивом. Например:

    expect([1, 2, 3]).to    contain_exactly(2, 3, 1) # pass
    expect([:a, :c, :b]).to contain_exactly(:a, :c ) # fail

Как уже отмечали другие, если вы хотите утверждать обратное, что массивы должны соответствовать как содержимому, так и порядку, используйте eq, то есть:

    expect([1, 2, 3]).to    eq([1, 2, 3]) # pass
    expect([1, 2, 3]).to    eq([2, 3, 1]) # fail

Ответ 6

не задокументировано очень хорошо, но я добавил ссылки в любом случае:

Rspec3 docs

expect(actual).to eq(expected)


Rspec2 docs

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