Pergunta

Eu estou procurando uma maneira de acelerar o meu Shoulda + noreferrer testes FactoryGirl .

O modelo que eu estou tentando teste (StudentExam) tem associações com outros modelos. Esses objetos associados deve existir antes que eu possa criar um StudentExam. Por essa razão, eles são criados em setup.

No entanto, um dos nossos modelos (School) leva tempo significativo para criar. Porque setup é chamado antes de cada declaração should, todo o caso de teste leva eras para executar -. Ele cria um @school novo, @student, @topic e @exam para cada instrução executada deve

Eu estou procurando uma maneira de criar esses objetos uma vez e somente uma vez . Existe algo como um startup para o método before_all que me permitisse criar registros que persistem em todo o resto do caso de teste?

Basicamente, eu estou procurando algo exatamente como antes do RSpec (: all) . Eu não estou preocupado com a questão de dependências uma vez que esses testes nunca vai modificar esses objetos caros.

Aqui está um exemplo de caso de teste. Desculpas para o longo código (Eu também criou um essência ):

# 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
Foi útil?

Solução

Se o problema está criando esses registros apenas uma vez, você pode usar uma variável de classe. Não é uma abordagem limpa, mas pelo menos ele deve 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 corrigir a solução super-feio adiar a avaliação com um método de instância

# 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

Outras dicas

Que tipo de testes que você está tentando escrever? Se você realmente quer ter certeza de que todos esses objetos estão a coordenar de forma adequada, você está escrevendo um teste de integração e velocidade não é a sua principal preocupação. No entanto, se você está tentando unidade testar o modelo, você pode obter melhores resultados por arrancar de forma agressiva.

Por exemplo, se você está tentando verificar se um exame usa o nome de sua associação escola quando você chamar exam.location (ou o que você está chamando-lo), você não precisa de um objeto de toda a escola. Você só precisa ter certeza de que o exame está chamando o método certo na escola. Para testar isso, você poderia fazer algo como o seguinte (usando Test :: Unit e Mocha, porque é isso que eu estou familiarizado com):

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

Basicamente, se você precisa para acelerar os testes de unidade porque os objetos são muito caros para construir, você não é realmente o teste de unidade. Todos os casos de teste acima sentir como eles devem estar no nível de teste de unidade, de modo esboço esboço esboço!

http: // m .onkey.org / 2009/9/20 / make-your-shoulda-testes-rápido-com fast_context é um excelente post sobre como fazer seus testes shoulda / fábrica-menina mais rápido, usando uma jóia chamada fast_context . Deixe-me saber se não é o que você precisa.

Há um plugin chamado fast_context ( github ligação ) que combina devem declarações em um único contexto, acelerar os testes .

A outra coisa que eu tenho vindo a utilizar para acelerar meus testes é pré-preencher os dados do dispositivo elétrico. FactoryGirl é lento porque está criando os registros cada vez que o bloco de configuração é executado.

Eu escrevi um plugin chamado Fixie que usa ActiveRecord para pré-preencher o banco de dados de teste, de modo que o registra o que você precisa para seus testes já estão criadas. Você pode usar Fixie juntamente com FactoryGirl se você quiser criar novos registros em tempo de execução, também.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top