Pregunta

Estoy buscando una manera de acelerar mi Shoulda + pruebas factorygirl .

El modelo que estoy tratando de probar (StudentExam) tiene asociaciones con otros modelos. deben existir estos objetos asociados antes de que pueda crear un StudentExam. Por esa razón, son creados en setup.

Sin embargo, uno de nuestros modelos (School) toma un tiempo considerable para crear. Debido setup se llama antes de cada declaración should, todo el caso de prueba lleva eones para ejecutar -. Crea un nuevo @school, @student, @topic y @exam para cada instrucción ejecutada debe

Estoy buscando una manera de crear estos objetos una vez y sólo una vez . ¿Hay algo así como un método para startup before_all que me permitiera crear registros, que va a continuar durante el resto del caso de prueba?

Básicamente estoy buscando algo exactamente igual antes de RSpec (: todos) . No estoy preocupado por el tema de las dependencias ya que estas pruebas no modificarán estos objetos caros.

He aquí un ejemplo de caso de prueba. Disculpas por el código largo (También he creado una GIST ):

# A StudentExam represents an Exam taken by a Student.
# It records the start/stop time, room number, etc.
class StudentExamTest < ActiveSupport::TestCase

  should_belong_to :student
  should_belong_to :exam

  setup do
    # These objects need to be created before we can create a StudentExam.  Tests will NOT modify these objects.
    # @school is a very time-expensive model to create (associations, external API calls, etc).
    # We need a way to create the @school *ONCE* -- there's no need to recreate it for every single test.
    @school = Factory(:school)
    @student = Factory(:student, :school => @school)
    @topic = Factory(:topic, :school => @school)
    @exam = Factory(:exam, :topic => @topic)
  end

  context "A StudentExam" do

    setup do
      @student_exam = Factory(:student_exam, :exam => @exam, :student => @student, :room_number => "WB 302")
    end

    should "take place at 'Some School'" do
      assert_equal @student_exam, 'Some School'
    end

    should "be in_progress? when created" do
      assert @student_exam.in_progress?
    end

    should "not be in_progress? when finish! is called" do
      @student_exam.finish!
      assert !@student_exam.in_progress
    end

  end

end
¿Fue útil?

Solución

Si el problema es la creación de estos registros sólo una vez, se puede utilizar una variable de clase. No es un enfoque limpio, pero al menos debería funcionar.

# A StudentExam represents an Exam taken by a Student.
# It records the start/stop time, room number, etc.
class StudentExamTest < ActiveSupport::TestCase

  should_belong_to :student
  should_belong_to :exam

  # These objects need to be created before we can create a StudentExam.  Tests will NOT modify these objects.
  # @school is a very time-expensive model to create (associations, external API calls, etc).
  # We need a way to create the @school *ONCE* -- there's no need to recreate it for every single test.
  @@school = Factory(:school)
  @@student = Factory(:student, :school => @@school)
  @@topic = Factory(:topic, :school => @@school)
  @@exam = Factory(:exam, :topic => @@topic)


  context "A StudentExam" do

    setup do
      @student_exam = Factory(:student_exam, :exam => @@exam, :student => @@student, :room_number => "WB 302")
    end

    should "take place at 'Some School'" do
      assert_equal @student_exam, 'Some School'
    end

    should "be in_progress? when created" do
      assert @student_exam.in_progress?
    end

    should "not be in_progress? when finish! is called" do
      @@student_exam.finish!
      assert !@student_exam.in_progress
    end

  end

end

EDIT: Para solucionar el super-feo solución posponer la evaluación con un método de instancia

.
# A StudentExam represents an Exam taken by a Student.
# It records the start/stop time, room number, etc.
class StudentExamTest < ActiveSupport::TestCase

  ...

  private

    def school
      @@school ||= Factory(:school)
    end

    # use school instead of @@school
    def student
      @@school ||= Factory(:student, :school => school)
    end

end

Otros consejos

¿Qué tipo de pruebas está tratando de escribir? Si realmente quiere asegurarse de que todos estos objetos están coordinando adecuadamente, estás escribiendo una prueba de integración y la velocidad no es su principal preocupación. Sin embargo, si usted está tratando de probar la unidad del modelo, que podría lograr mejores resultados mediante la stubbing agresiva.

Por ejemplo, si usted está tratando de comprobar que un examen utiliza el nombre de su asociación escolar cuando se llama exam.location (o lo que sea que estés llamándolo), que no es necesario un objeto de toda la escuela. Sólo tiene que asegurarse de que el examen está llamando el método correcto en la escuela. Para probar esto, usted podría hacer algo como lo siguiente (utilizando Test :: Unidad y Mocha, porque eso es lo que estoy familiarizado):

test "exam gets location from school name" do
  school = stub_everything
  school.expects(:name).returns(:a_school_name)
  exam = Factory(:exam, :school => school)

  assert_equal :a_school_name, exam.location
end

Básicamente, si usted necesita para acelerar las pruebas unitarias porque los objetos son demasiado caros de construir, usted no está realmente la unidad de pruebas. Todos los casos de prueba anteriores se sienten como si debería estar en el nivel de prueba de unidad, de modo talón talón de recibo!

http: // m .onkey.org / 2009/9/20 / hacer tus shoulda-tests-rápido-con-fast_context es un excelente post sobre cómo hacer sus pruebas shoulda / fábrica-chica más rápido, utilizando una gema llamada fast_context . Que me haga saber si no es lo que necesita.

No es un plugin llamado fast_context ( github enlace ) que combina deben declaraciones en un único contexto, la aceleración de las pruebas .

La otra cosa que he estado utilizando para acelerar mis pruebas es rellenando previamente los datos del accesorio. Factorygirl es lento porque está creando esos registros cada vez que el bloque de configuración ejecuta.

escribí un plugin llamado Fixie que utiliza ActiveRecord para rellenar previamente la base de datos de prueba, por lo que la registros que necesita para sus pruebas ya están creados. Se puede utilizar junto con Fixie factorygirl si desea crear nuevos registros en tiempo de ejecución, también.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top