Rspec: "array.should == another_array" pero sin preocuparse por el orden


235

A menudo quiero comparar matrices y asegurarme de que contengan los mismos elementos, en cualquier orden. ¿Hay una manera concisa de hacer esto en RSpec?

Aquí hay métodos que no son aceptables:

#to_set

Por ejemplo:

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

o

array.to_set.should == another_array.to_set

Esto falla cuando las matrices contienen elementos duplicados.

#sort

Por ejemplo:

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

o

array.sort.should == another_array.sort

Esto falla cuando los elementos de la matriz no se implementan #<=>


77
No es inteligente, pero comparar to_sety en sizerealidad no hace lo que quieres. Por ejemplo, [a, b, b] coincidiría con [a, a, b]. ¡Salud!
Jo Liss

3
Para aquellos que tropezaron aquí preguntándose lo contrario: el orden debería ser el mismo . Use el eqmarcador, por ejemploexpect([1, 2]).to_not eq([2, 1])
Dennis

Respuestas:


263

Tratar array.should =~ another_array

La mejor documentación sobre esto que puedo encontrar es el código en sí, que está aquí .


Esto no tiene en cuenta el orden, por lo que esta no es una respuesta aceptable, ¿verdad? Presupuesto de los documentos : Passes if actual contains all of the expected regardless of order..
Joshua Muheim

16
Título de esta publicación: "Rspec:" array.should == another_array ”pero sin preocuparse por el orden"
x1a4

3
Esto ahora está documentado oficialmente bajo los criterios del operador
Kelvin

77
Si está utilizando la nueva sintaxis "esperar" que se encuentra en rspec 3.0, vea la respuesta de @JoshKovach.
clozach

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

238

Desde RSpec 2.11 también puede usar match_array.

array.should match_array(another_array)

Lo que podría ser más legible en algunos casos.

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

8
sí, acabo de actualizar a los rieles 4 y = ~ dejó de funcionar donde match_array funciona bien, ¡gracias!
opsb

2
No sé si eso es más legible. Ahora parece que debería ser una coincidencia exacta, pero no lo es. El garabato anterior fue lo suficientemente vago como para no significar nada para una matriz, por lo que no tenía la preconcepción. Tal vez solo soy yo.
Trejkaz

1
Para "exacto", siempre lo has hecho eq(), así que supongo que match_array()es lo suficientemente vago para mí.
awendt

Esto no funciona para mí en las listas ordenadas. Piensa que las listas, que tienen los mismos elementos en un orden diferente, son las mismas. :-(
djangofan

FWIW match_arrayes un alias para contain_exactly( documentación )
Ruy Diaz


13

Use match_array, que toma otra matriz como argumento, o contain_exactly, que toma cada elemento como un argumento separado, y a veces es útil para facilitar la lectura. ( documentos )

Ejemplos:

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

o

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

3

Para el uso de RSpec 3 contain_exactly:

Ver https://relishapp.com/rspec/rspec-expectations/v/3-2/docs/built-in-matchers/contain-exactly-matcher para más detalles, pero aquí hay un extracto:

El emparejador contiene_exactamente proporciona una forma de probar matrices entre sí de una manera que ignora las diferencias en el orden entre la matriz real y la esperada. Por ejemplo:

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

Como otros han señalado, si desea afirmar lo contrario, que las matrices deben coincidir tanto con el contenido como con el orden, luego use eq, es decir:

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

1

no documentado muy bien pero agregué enlaces de todos modos:

Rspec3 docs

expect(actual).to eq(expected)


Rspec2 docs

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


12
Ambos esperan (actual) .to eq (esperado) y esperan (actual) .to match_array (esperado) funcionan en rspec3, pero están haciendo cosas diferentes. #match_array ignora el orden, mientras que #eq no.
gucki

1
Esto no responde a la pregunta, ya que el OP solicitó específicamente ignorar la orden.
NobodysNightmare

¡Si! Esto funcionó para mí. Una comparación que falla si el orden de los elementos no es el mismo. ¡Gracias! Me refiero al .to eqmétodo, no al match_array.
djangofan
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.