2011-10-06 14 views
11

Tengo una prueba de controlador simple, que contiene a.o. el siguiente código:Acelerando la prueba de los controladores rspec: ¿usar antes de que todos fallen?

context "POST :create" do 
    before (:each) do 
    post :create, :user_id => @user.id, 
     :account => { .. some data ... } 
    end 
    it { response.status.should == 201 } 
    it { response.location.should be_present } 
end 

Ahora pensado en una forma muy simple para acelerar esta prueba, y el uso de un before(:all) en lugar de un before(:each). En ese caso, la publicación solo se haría una vez.

así que escribí:

context "POST :create" do 
    before (:all) do 
    post :create, :user_id => @user.id, 
     :account => { .. some data ... } 
    end 
    it { response.status.should == 201 } 
    it { response.location.should be_present } 
end 

Pero cuando me siento los siguientes errores:

RuntimeError: 
    @routes is nil: make sure you set it in your test's setup method. 

Es esto por diseño? ¿Hay alguna forma de eludirlo?

+1

¿Ha encontrado una solución a esto? Me he encontrado con el mismo problema. – ktusznio

Respuesta

12

hice esta pregunta en la lista de correo rspec, y tiene la siguiente respuesta del propio @dchelimsky:

Sí. rspec-rails envuelve el marco de prueba de los rieles que no tiene un concepto anterior (: todo), por lo que todos los datos se restablecen antes de cada ejemplo. Incluso si quisiéramos admitir esto en rspec-rails (que no es así), requeriría cambios primero en los rieles.

Al hacer llamadas de controlador no es posible en un before(:all), solo se puede usar para configurar sus variables de base de datos o de instancia.

2

no estoy seguro de si esto es una buena idea, pero estableciendo una variable de clase con ||= en el bloque before(:each) parece funcionar:

describe PagesController do 
    describe "GET 'index'" do 
    before(:each) do 
     @@response ||= begin 
     get :index 
     response 
     end 
    end 
    it { @@response.should redirect_to(root_path) } 
    it { @@response.status.should == 301 } 
    it { @@response.location.should be_present } 
    end 
end 
+0

¿Has probado esto? Cuando probé esto, el POST ni siquiera funcionó, porque todavía no estás en ningún contexto de controlador. – nathanvda

+0

Oops, eso se suponía que dijera _haven't_ intentado esto. Respuesta actualizada con una técnica diferente. – Zubin

+0

Ahora haces un 'before (: each)' de nuevo, que es exactamente lo que quería evitar, y luego hay formas mucho más bonitas/legibles para escribirlo. Si haces el 'antes: cada uno 'puedes escribir' get: index' y usar 'response'. – nathanvda

3

Si quiere ir a la variable global sucia y beneficiarse del aumento de la velocidad, puede usar esto pero precaución. Esta lógica desordenada hace el trabajo, pero frustra el objetivo de conducir con pruebas legibles y claras. La refactorización en un ayudante con rendimiento es más que recomendable.

describe PagesController do 
    describe "GET 'index'" do 
    before(:each) do 
     GLOBAL ||= {} 
     @response = GLOBAL[Time.now.to_f] || begin 
     get :index 
     response 
     end 
    end 
    it { @response.should redirect_to(root_path) } 
    it { @response.status.should == 301 } 
    it { @response.location.should be_present } 
    end 
end 

El refactor se puede poner en un archivo de su elección en spec/apoyo va como sigue

RSPEC_GLOBAL = {} 

def remember_through_each_test_of_current_scope(variable_name) 
    self.instance_variable_set("@#{variable_name}", RSPEC_GLOBAL[variable_name] || begin 
    yield 
    end) 
    RSPEC_GLOBAL[variable_name] ||= self.instance_variable_get("@#{variable_name}") 
end 

Por lo tanto, el código en el archivo de prueba se convierte en:

describe PagesController do 
    describe "GET 'index'" do 
    before(:each) do 
     remember_through_each_test_of_current_scope('memoized_response') do 
     get :index 
     response 
     end 
    end 
    it { @memoized_response.should redirect_to(root_path) } 
    it { @memoized_response.status.should == 301 } 
    it { @memoized_response.location.should be_present } 
    end 
end 

espero que ayuda, y una vez más, use con precaución

Cuestiones relacionadas