mir*_*lon 7 ruby iterator rspec yield ruby-on-rails
我想使用rspec测试迭代器.在我看来,唯一可能的产量匹配器是yield_successive_args(根据https://www.relishapp.com/rspec/rspec-expectations/v/3-0/docs/built-in-matchers/yield-matchers).其他匹配器仅用于单一屈服.
但是yield_successive_args如果屈服是以指定的其他顺序而失败.
是否有任何方法或很好的解决方法来测试以任何顺序产生的迭代器?
类似于以下内容:
expect { |b| array.each(&b) }.to yield_multiple_args_in_any_order(1, 2, 3)
Run Code Online (Sandbox Code Playgroud)
这是我为这个问题提出的匹配器,它相当简单,并且应该具有很高的效率。
require 'set'
RSpec::Matchers.define :yield_in_any_order do |*values|
expected_yields = Set[*values]
actual_yields = Set[]
match do |blk|
blk[->(x){ actual_yields << x }] # ***
expected_yields == actual_yields # ***
end
failure_message do |actual|
"expected to receive #{surface_descriptions_in expected_yields} "\
"but #{surface_descriptions_in actual_yields} were yielded."
end
failure_message_when_negated do |actual|
"expected not to have all of "\
"#{surface_descriptions_in expected_yields} yielded."
end
def supports_block_expectations?
true
end
end
Run Code Online (Sandbox Code Playgroud)
我用 突出显示了包含大部分重要逻辑的行# ***。这是一个非常简单的实现。
只需将其放入 下的文件中spec/support/matchers/,并确保您从需要它的规范中需要它。大多数时候,人们只是添加这样一行:
Dir[File.dirname(__FILE__) + "/support/**/*.rb"].each {|f| require f}
Run Code Online (Sandbox Code Playgroud)
但spec_helper.rb如果您有很多支持文件,并且并非所有地方都需要它们,那么这可能会有点多,因此您可能只想将其包含在使用它的地方。
然后,在规范本身中,用法与任何其他生成匹配器的用法类似:
class Iterator
def custom_iterator
(1..10).to_a.shuffle.each { |x| yield x }
end
end
describe "Matcher" do
it "works" do
iter = Iterator.new
expect { |b| iter.custom_iterator(&b) }.to yield_in_any_order(*(1..10))
end
end
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
343 次 |
| 最近记录: |