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.