2010-12-13 17 views
6

Me gustaría saber sobre las expresiones idiomáticas o las mejores prácticas para probar un flujo de trabajo de varios pasos utilizando rspec.probando un flujo de trabajo de varios pasos en rspec

Tomemos como ejemplo un sistema de "carrito de compras", en el que el proceso de compra podría ser

  1. cuando el usuario se somete a la cesta y no utiliza HTTPS, redirección a https
  2. cuando el usuario se somete a cesta y estamos usando https y no hay cookies, crear y mostrar una nueva cesta y enviar una cookie
  3. cuando el usuario envía a la cesta y estamos utilizando https y hay una cookie válida y el nuevo artículo es para una diferente producto que el primer artículo, agregue una línea a la cesta y muestre ambas líneas
  4. cuando el usuario envía a la cesta y estamos usando https y hay una cookie válida y el nuevo artículo es para el mismo producto que el anterior, incrementa la cantidad de la línea de cesta y muestra ambas líneas
  5. cuando el usuario hace clic en 'pagar' en la página de la cesta y está utilizando https y no hay una cookie y la cesta es no vacío y ...
  6. ...

he leído http://eggsonbread.com/2010/03/28/my-rspec-best-practices-and-tips/, que entre otras cosas, informa que cada "se bloquee" debe contener solo una afirmación: en lugar de hacer el cálculo y luego probar varios atributos en el mismo bloque, use un "antes" dentro de un contexto para crear (o recuperar) el objeto bajo prueba y asígnelo a @some_instance_variable, luego escriba cada prueba de atributo como un bloque separado. Eso ayuda un poco, pero en un caso como el descrito anteriormente donde el paso de prueba n requiere hacer toda la configuración para los pasos [1..n-1] me encuentro duplicando el código de configuración (obviamente no es bueno) o creando muchas funciones auxiliares con nombres cada vez más difíciles de manejar (def create_basket_with_three_lines_and_two_products) y llamándolos consecutivamente en cada paso anterior al bloque.

¿Algún consejo sobre cómo hacer esto de forma menos prolija/tediosa? Aprecio el principio general detrás de la idea de que cada ejemplo no debe depender del estado dejado por ejemplos anteriores, pero cuando está probando un proceso de varios pasos y las cosas pueden salir mal en cualquier paso, configurar el contexto para cada paso es inevitablemente va a requerir volver a ejecutar toda la configuración de los n pasos anteriores, así que ...

Respuesta

2

Aquí hay un posible enfoque: definir un objeto que crea el estado necesario para cada paso y pasarlo hacia adelante para cada uno sucesivo. Básicamente lo que necesita para burlarse/ramal del método llama a todas las condiciones de configuración:

class MultiStep 
    def initialize(context) 
    @context = context 
    end 

    def init_vars 
    @cut = @context.instance_variable_get(:@cut) 
    end 

    def setup(step) 
    init_vars 
    method(step).call 
    end 

    def step1 
    @cut.stub(:foo).and_return("bar") 
    end 

    def step2 
    step1 
    @cut.stub(:foo_bar).and_return("baz_baz") 
    end 
end 

class Cut # Class Under Test 
    def foo 
    "foo" 
    end 
    def foo_bar 
    "foo_bar" 
    end 
end 

describe "multiple steps" do 
    before(:each) do 
    @multi_stepper = MultiStep.new(self) 
    @cut = Cut.new 
    end 

    it "should setup step1" do 
    @multi_stepper.setup(:step1) 
    @cut.foo.should == "bar" 
    @cut.foo_bar.should == "foo_bar" 
    end 

    it "should setup step2" do 
    @multi_stepper.setup(:step2) 
    @cut.foo.should == "bar" 
    @cut.foo_bar.should == "baz_baz" 
    end 

end 
1

Ciertamente demasiado tarde para OP, pero esto podría ser útil para otros - la rspec pasos joya parece estar construida para esta situación exacta : https://github.com/LRDesign/rspec-steps

Puede valer la pena mirar https://github.com/railsware/rspec-example_steps y https://github.com/jimweirich/rspec-given también. Me decidí por pasos rápidos, pero estaba apurado y estas otras opciones podrían ser mejores por lo que sé.

+0

ahora que ha usado rspec-steps gem ¿está contento con el resultado para resolver el problema del respeto en varios pasos? – Angela

+0

@Angela: Hmm, buena pregunta. Lo usé brevemente, pero el resto del grupo no estaba interesado en él, así que terminamos abandonándolo y teniendo más duplicaciones. Creo * que el razonamiento era que necesitábamos más legibilidad, pero ha sido mucho tiempo ... En este punto, me parece que las pruebas de integración verdaderas son más fáciles de escribir simplemente como funciones grandes que hacen un solo "flujo de trabajo" por prueba. No es el enfoque más idiomático o popular, pero me gusta la legibilidad. – Nerdmaster

+0

Veo tan solo una sola 'descripción' en el rspec? – Angela