Rspec: "array.should == another_array" mais sans souci d'ordre


235

Je veux souvent comparer des tableaux et m'assurer qu'ils contiennent les mêmes éléments, dans n'importe quel ordre. Existe-t-il un moyen concis de le faire dans RSpec?

Voici des méthodes qui ne sont pas acceptables:

#to_set

Par exemple:

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

ou

array.to_set.should == another_array.to_set

Cela échoue lorsque les tableaux contiennent des éléments en double.

#sort

Par exemple:

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

ou

array.sort.should == another_array.sort

Cela échoue lorsque les éléments des tableaux ne sont pas implémentés #<=>


7
Pas pour smartass, mais en comparant to_setet en sizefait ne fait pas ce que vous voulez. Par exemple [a, b, b] correspondrait à [a, a, b]. À votre santé!
Jo Liss

3
Pour ceux qui ont trébuché ici se demandant le contraire: l' ordre devrait être le même . Utilisez le eqmatcher, par exempleexpect([1, 2]).to_not eq([2, 1])
Dennis

Réponses:


263

Essayer array.should =~ another_array

La meilleure documentation à ce sujet que je peux trouver est le code lui-même, qui est ici .


Cela ne tient pas compte de la commande, donc ce n'est pas une réponse acceptable, n'est-ce pas? Citation du docs : Passes if actual contains all of the expected regardless of order..
Joshua Muheim

16
Titre de cet article: "Rspec:" array.should == another_array "mais sans souci de commande"
x1a4

3
Ceci est maintenant officiellement documenté sous les opérateurs de correspondance
Kelvin

7
Si vous utilisez la nouvelle syntaxe "expect" trouvée dans rspec 3.0, consultez la réponse de @JoshKovach.
clozach

46
La syntaxe de Rspec 3.0 est la suivante expect([1, 2, 3]).to match_array([2, 1, 3]): stackoverflow.com/a/19436763/33226
Gavin Miller

238

Depuis RSpec 2.11, vous pouvez également utiliser match_array.

array.should match_array(another_array)

Ce qui pourrait être plus lisible dans certains cas.

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

8
yup, juste mis à niveau vers les rails 4 et = ~ a cessé de fonctionner où match_array fonctionne bien, merci!
opsb

2
Je ne sais pas si c'est plus lisible. Maintenant, il semble que ce devrait être une correspondance exacte, mais ce n'est pas le cas. Le squiggle précédent était suffisamment vague pour ne rien signifier pour un tableau, donc je n'avais pas l'idée préconçue. C'est peut-être juste moi.
Trejkaz

1
Pour "exact", vous l'avez toujours fait eq(), donc je suppose que match_array()c'est assez vague pour moi.
awendt

Cela ne fonctionne pas pour moi sur les listes ordonnées. Il pense que les listes, qui ont les mêmes éléments dans un ordre différent, sont les mêmes. :-(
djangofan

FWIW match_arrayest un alias pour contain_exactly( documentation )
Ruy Diaz


13

Utilisez match_array, qui prend un autre tableau comme argument, ou contain_exactly, qui prend chaque élément comme argument séparé, et est parfois utile pour la lisibilité. ( documents )

Exemples:

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

ou

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

3

Pour l'utilisation de RSpec 3 contain_exactly:

Voir https://relishapp.com/rspec/rspec-expectations/v/3-2/docs/built-in-matchers/contain-exactly-matcher pour plus de détails, mais voici un extrait:

Le matcher contain_exactly fournit un moyen de tester les tableaux les uns contre les autres d'une manière qui ne tient pas compte des différences dans l'ordre entre le tableau réel et le tableau attendu. Par exemple:

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

Comme d'autres l'ont souligné, si vous voulez affirmer le contraire, que les tableaux doivent correspondre à la fois au contenu et à l'ordre, alors utilisez eq, c'est-à-dire:

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

1

pas très bien documenté mais j'ai quand même ajouté des liens:

Rspec3 docs

expect(actual).to eq(expected)


Rspec2 docs

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


12
Les deux attendent (réel) .to eq (attendu) et attendent (réel) .to match_array (attendu) fonctionnent dans rspec3, mais ils font des choses différentes. #match_array ignore l'ordre, tandis que #eq ne le fait pas.
gucki

1
Cela ne répond pas à la question, car le PO a expressément demandé de ne pas tenir compte de l'ordonnance.
NobodysNightmare

Oui! Cela a fonctionné pour moi. Une comparaison qui échoue si l'ordre des éléments n'est pas le même. Je vous remercie! Je me réfère à la .to eqméthode, pas à la match_array.
djangofan
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.