Rspec: "array.should == another_array", але не турбуючись про замовлення


235

Я часто хочу порівнювати масиви і переконайтесь, що вони містять однакові елементи в будь-якому порядку. Чи є лаконічний спосіб зробити це в 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

Це не вдається, коли елементи масивів не реалізуються #<=>


7
Не до розуму, але порівняння to_setі sizeнасправді не робить те, що ти хочеш. Наприклад, [a, b, b] відповідатиме [a, a, b]. Ура!
Жо Лісс

3
Для тих, хто натрапив сюди, дивується навпаки: порядок повинен бути однаковим . Використовуйте eqматч, наприкладexpect([1, 2]).to_not eq([2, 1])
Денніс

Відповіді:


263

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

Найкраща документація щодо цього, яку я можу знайти, - це сам код, який тут .


Це не враховує замовлення, тому це не прийнятна відповідь, чи не так? Цитата з документів : Passes if actual contains all of the expected regardless of order..
Джошуа Мухайм

16
Назва цього допису: "Rspec:" array.should == another_array ", але без занепокоєння щодо замовлення"
x1a4

3
Це зараз офіційно задокументовано в матчах операторів
Келвін

7
Якщо ви використовуєте новий синтаксис "очікуйте", знайдений у rspec 3.0, дивіться відповідь від @JoshKovach.
clozach

46
Синтаксис Rspec 3.0expect([1, 2, 3]).to match_array([2, 1, 3]) див.: Stackoverflow.com/a/19436763/33226
Гавін Міллер

238

Оскільки 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])

8
Так, щойно оновлений до рейки 4 і = ~ перестав працювати там, де match_array працює добре, дякую!
opsb

2
Я не знаю, якщо це читабельніше. Тепер він зазначає, що він повинен відповідати точно, але це не так. Попередня викрутка була досить розпливчастою, щоб нічого не означати для масиву, тому я не мав попереднього уявлення. Можливо, це лише я.
Трежказ

1
Для "точного" ви завжди є eq(), тому я думаю match_array(), що для мене досить розпливчасте.
awendt

Це не працює для мене в упорядкованих списках. Він вважає, що списки, які мають однакові елементи в іншому порядку, однакові. :-(
djangofan

FWIW match_array- псевдонім для contain_exactly( документація )
Ruy Diaz


13

Використовувати match_array, який приймає інший масив як аргумент, або contain_exactly, який сприймає кожен елемент як окремий аргумент, а іноді корисний для читабельності. ( документи )

Приклади:

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

або

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

3

Для RSpec 3 використовуйте contain_exactly:

Докладніше дивіться на https://relishapp.com/rspec/rspec-expeasures/v/3-2/docs/built-in-matchers/contain-exact-matcher , але ось витяг:

Матч містити_Екстрактно надає спосіб перевірити масиви один проти одного таким чином, що не враховує відмінності в упорядкуванні між фактичним і очікуваним масивом. Наприклад:

    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

1

не задокументовано дуже добре, але я все-таки додав посилання:

Документи Rspec3

expect(actual).to eq(expected)


Документи Rspec2

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


11
І очікують (фактично) .to eq (очікується), і очікують (фактично) .to match_array (очікуваний) працювати в rspec3, але вони роблять різні речі. #match_array ігнорує замовлення, тоді як #eq не робить.
gucki

1
Це не дає відповіді на запитання, оскільки ОП спеціально просила проігнорувати наказ.
NobodysNightmare

Так! Це працювало для мене. Порівняння, яке не вдається, якщо порядок елементів не однаковий. Дякую! Я посилаюся на .to eqметод, а не на метод match_array.
djangofan
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.