Rspec:“array.should == another_array”但不关心顺序

Posted

技术标签:

【中文标题】Rspec:“array.should == another_array”但不关心顺序【英文标题】:Rspec: "array.should == another_array" but without concern for order 【发布时间】:2011-02-28 01:35:10 【问题描述】:

我经常想比较数组并确保它们以任意顺序包含相同的元素。在 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

当数组元素没有实现#<=>时,这会失败

【问题讨论】:

不是聪明人,而是比较 to_setsize 实际上并没有达到你想要的效果。例如。 [a, b, b] 将匹配 [a, a, b]。干杯! 对于那些偶然发现相反情况的人:顺序应该相同。使用 eq 匹配器,例如expect([1, 2]).to_not eq([2, 1]) 【参考方案1】:

试试array.should =~ another_array

我能找到的最好的文档是代码本身,即here。

【讨论】:

这不考虑订单,所以这不是一个可以接受的答案,是吗?引用自docs:Passes if actual contains all of the expected regardless of order. 这篇文章的标题:“Rspec: “array.should == another_array” 但不关心顺序” 现在正式记录在operator matchers下 如果您使用的是 rspec 3.0 中的新“expect”语法,请参阅@JoshKovach 的答案。 Rspec 3.0 语法为 expect([1, 2, 3]).to match_array([2, 1, 3]) 参见:***.com/a/19436763/33226【参考方案2】:

从 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])

【讨论】:

是的,刚刚升级到 rails 4 并且 =~ 在 match_array 工作正常的地方停止工作,谢谢! 我不知道这是否更具可读性。现在它看起来应该是完全匹配的,但事实并非如此。之前的花体字很模糊,对数组没有任何意义,所以我没有先入为主的观念。也许只有我。 对于“精确”,你总是有eq(),所以我猜match_array()对我来说已经够模糊了。 这对我来说不适用于有序列表。它认为具有不同顺序的相同项目的列表是相同的。 :-( FWIW match_arraycontain_exactly (documentation) 的别名【参考方案3】:

我发现=~ 是不可预测的,并且它没有明显的原因失败了。过去 2.14,您可能应该使用

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

【讨论】:

在 3.0 之后也有效:expect([1, 2, 3]).to contain_exactly(2, 3, 1)。 relishapp.com/rspec/rspec-expectations/v/3-0/docs/…【参考方案4】:

没有很好地记录,但我还是添加了链接:

Rspec3 docs

expect(actual).to eq(expected)


Rspec2 docs

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

【讨论】:

expect(actual).to eq(expected) 和 expect(actual).to match_array(expected) 都在 rspec3 中工作,但它们做的事情不同。 #match_array 忽略排序,而 #eq 不会。 这没有回答问题,因为 OP 明确要求忽略订单。 是的!这对我有用。如果元素的顺序不同,则比较失败。谢谢!我指的是 .to eq 方法,而不是 match_array【参考方案5】:

对于 RSpec 3,请使用 contain_exactly:

详情请参阅https://relishapp.com/rspec/rspec-expectations/v/3-2/docs/built-in-matchers/contain-exactly-matcher,但这里是摘录:

contain_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】:

使用match_array,它将另一个数组作为参数,或contain_exactly,将每个元素作为一个单独的参数,有时对可读性很有用。 (docs)

例子:

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

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

【讨论】:

以上是关于Rspec:“array.should == another_array”但不关心顺序的主要内容,如果未能解决你的问题,请参考以下文章

ruby [rspec]“使用RSpec测试Rails程序”笔记

RSpec vs Cucumber(RSpec 故事)[关闭]

rspec 3 - 存根类方法

失败/错误:需要'rspec/rails'类型错误:错误的参数类型类(预期模块)Rspec V3

rails-rspec 错误无法加载此类文件 -- rspec/core/formatters/progress_formatter

Rspec: everyday-rspec实操。5:controller test(了解基础)