ruby-on-rails ruby rspec iterator yield

ruby on rails - Coincide con rendimientos mĂșltiples en cualquier orden



ruby-on-rails rspec (2)

Aquí está el emparejador que surgió para este problema, es bastante simple y debería funcionar con un buen grado de eficiencia.

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

He resaltado las líneas que contienen la mayor parte de la lógica importante con # *** . Es una implementación bastante sencilla.

Uso

Simplemente spec/support/matchers/ en un archivo, en spec/support/matchers/ , y asegúrese de que lo requiera de las especificaciones que lo necesitan. La mayoría de las veces, la gente simplemente agrega una línea como esta:

Dir[File.dirname(__FILE__) + "/support/**/*.rb"].each {|f| require f}

a su spec_helper.rb pero si tiene una gran cantidad de archivos de soporte, y no son necesarios en todas partes, esto puede ser bastante spec_helper.rb , por lo que puede incluirlo solo donde se usa.

Luego, en las especificaciones mismas, el uso es como el de cualquier otro equilibrador de rendimiento:

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

Quiero probar un iterador usando rspec. Me parece que la única variable de rendimiento posible es yield_successive_args (según https://www.relishapp.com/rspec/rspec-expectations/v/3-0/docs/built-in-matchers/yield-matchers ). Los otros mezcladores se usan solo para rendimiento individual.

Pero yield_successive_args falla si el rendimiento está en otro orden que el especificado.

¿Hay algún método o buena solución para probar el iterador que cede en cualquier orden?

Algo como lo siguiente:

expect { |b| array.each(&b) }.to yield_multiple_args_in_any_order(1, 2, 3)


Esto se puede resolver en Ruby simple usando una intersección de conjunto de matrices:

array1 = [3, 2, 4] array2 = [4, 3, 2] expect(array1).to eq (array1 & array2) # for an enumerator: enumerator = array1.each expect(enumerator.to_a).to eq (enumerator.to_a & array2)

La intersección ( & ) devolverá elementos que están presentes en ambas colecciones, manteniendo el orden del primer argumento.