Rspec: "array.should == another_array", mas sem preocupação com a ordem


235

Frequentemente, quero comparar matrizes e garantir que elas contenham os mesmos elementos, em qualquer ordem. Existe uma maneira concisa de fazer isso no RSpec?

Aqui estão métodos que não são aceitáveis:

#to_set

Por exemplo:

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

ou

array.to_set.should == another_array.to_set

Isso falha quando as matrizes contêm itens duplicados.

#sort

Por exemplo:

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

ou

array.sort.should == another_array.sort

Isso falha quando os elementos de matriz não implementam #<=>


7
Não é esperto, mas comparar to_sete sizerealmente não faz o que você deseja. Por exemplo, [a, b, b] corresponderia a [a, a, b]. Felicidades!
precisa saber é o seguinte

3
Para quem tropeçou aqui imaginando o oposto: a ordem deve ser a mesma . Use o eqmarcador, por exemplo,expect([1, 2]).to_not eq([2, 1])
Dennis

Respostas:


263

Experimentar array.should =~ another_array

A melhor documentação sobre isso que posso encontrar é o próprio código, que está aqui .


Isso não leva em conta o pedido, portanto, essa não é uma resposta aceitável, é? Citar os docs : Passes if actual contains all of the expected regardless of order..
Joshua Muheim

16
Título desta publicação: "Rspec:" array.should == another_array ", mas sem preocupação com a ordem"
x1a4 22/01

3
Este é agora oficialmente documentado sob matchers operador
Kelvin

7
Se você estiver usando a nova sintaxe "expect" encontrada no rspec 3.0, consulte a resposta de @JoshKovach.
clozach

46
Rspec 3.0 sintaxe é expect([1, 2, 3]).to match_array([2, 1, 3])ver: stackoverflow.com/a/19436763/33226
Gavin Miller

238

Desde o RSpec 2.11, você também pode usar match_array.

array.should match_array(another_array)

O que poderia ser mais legível em alguns casos.

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

8
Sim, apenas atualizei para os trilhos 4 e = ~ parou de funcionar onde match_array funciona bem, obrigado!
Opsb dec

2
Não sei se isso é mais legível. Agora parece que deve ser uma correspondência exata, mas não é. O rabisco anterior era vago o suficiente para não significar nada para uma matriz, então eu não tinha o preconceito. Talvez seja só eu.
Trejkaz

1
Para "exato", você sempre tem eq(), então acho que match_array()é vago o suficiente para mim.
awendt

Isso não funciona para mim nas listas ordenadas. Ele acha que as listas, que têm os mesmos itens em uma ordem diferente, são iguais. :-(
djangofan

FWIW match_arrayé um alias para contain_exactly( documentação )
Ruy Diaz


13

Use match_array, que aceita outra matriz como argumento, ou contain_exactlyque aceita cada elemento como argumento separado e, às vezes, é útil para facilitar a leitura. ( docs )

Exemplos:

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

ou

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

3

Para o RSpec 3, use contain_exactly:

Consulte https://relishapp.com/rspec/rspec-expectations/v/3-2/docs/built-in-matchers/contain-exactly-matcher para obter detalhes, mas aqui está um extrato:

O match_exactly matcher fornece uma maneira de testar matrizes uns contra os outros de uma maneira que desconsidera diferenças na ordem entre a matriz real e a esperada. Por exemplo:

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

Como outros já apontaram, se você deseja afirmar o contrário, que as matrizes devem corresponder ao conteúdo e à ordem, use eq:

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

1

não está muito bem documentado, mas adicionei links de qualquer maneira:

Docs Rspec3

expect(actual).to eq(expected)


Docs Rspec2

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


11
Ambos esperam (real) .to eq (esperado) e esperam (real) .to match_array (esperado) funcionam no rspec3, mas estão fazendo coisas diferentes. #match_array ignora a ordem, enquanto #eq não.
gucki

1
Isso não responde à pergunta, pois o OP pediu especificamente para desconsiderar o pedido.
NobodysNightmare 19/05

Sim! Isso funcionou para mim. Uma comparação que falha se a ordem dos elementos não for a mesma. Obrigado! Refiro-me ao .to eqmétodo, não ao match_array.
djangofan
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.