Question

Je suis à la recherche d'un moyen d'accélérer mon Shoulda + factorygirl tests de.

Le modèle que je suis en train de tester (StudentExam) a des associations à d'autres modèles. Ces objets associés doivent exister avant que je puisse créer un StudentExam. Pour cette raison, ils sont créés dans setup.

Cependant, l'un de nos modèles (School) prend beaucoup de temps pour créer. Parce que setup est appelée avant chaque instruction should, l'ensemble de cas de test prend éons pour exécuter -. Il crée une nouvelle @school, @student, @topic et @exam pour chaque devrait instruction exécutée

Je cherche un moyen de créer ces objets une fois et une seule fois . Y at-il quelque chose comme un startup pour la méthode de before_all qui me permettrait de créer des enregistrements qui persistera dans le reste du boîtier de test?

En fait, je suis à la recherche de quelque chose exactement comme avant (: tous) . Je ne suis pas préoccupé par la question des dépendances étant donné que ces tests ne modifient jamais ces objets coûteux.

Voici un cas de test par exemple. Toutes mes excuses pour le code long (j'ai aussi créé un essentiel ):

# 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
Était-ce utile?

La solution

Si le problème est la création de ces dossiers une seule fois, vous pouvez utiliser une variable de classe. Ce n'est pas une approche propre, mais au moins il devrait fonctionner.

# 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: Pour fixer la solution de contournement super-laid reporter l'évaluation avec une méthode d'instance

.
# 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

Autres conseils

Quel genre de tests que vous essayez d'écrire? Si vous voulez vraiment vous assurer que tous ces objets coordonnent de façon appropriée, vous écrivez un test d'intégration et la vitesse n'est pas votre principale préoccupation. Toutefois, si vous essayez de test unitaire du modèle, vous pouvez obtenir de meilleurs résultats par stubbing agressivement.

Par exemple, si vous essayez de vérifier qu'un examen utilise le nom de son association scolaire lorsque vous appelez exam.location (ou tout ce que vous appelez), vous n'avez pas besoin d'un objet entier de l'école. Vous devez juste vous assurer que l'examen appelle la bonne méthode à l'école. Pour tester cela, vous pouvez faire quelque chose comme ce qui suit (en utilisant Test :: Unit et Mocha parce que ce que je suis au courant):

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

En gros, si vous avez besoin pour accélérer vos tests unitaires parce que les objets sont trop chers pour construire, vous n'êtes pas vraiment des tests unitaires. Tous les cas de test ci-dessus se sentent comme ils devraient être au niveau de test unitaire, donc talon de talon de talon!

http: // m .onkey.org / 2009/9/20 / make-vos-Shoulda-tests plus rapide avec-fast_context est un excellent article sur la façon de faire vos Shoulda / essais en usine fille plus rapide, en utilisant un petit bijou appelé fast_context . Permettez-moi de savoir si ce ne est pas ce que vous avez besoin.

Il y a un plugin appelé fast_context ( github lien ) qui combine devraient déclarations dans un seul contexte, accélérant les essais .

L'autre chose que j'ai utilisé pour accélérer mes tests est pré-peuplant les données de fixation. Factorygirl est lent parce qu'il est la création de ces enregistrements chaque fois que le bloc de configuration fonctionne.

J'ai écrit un plugin appelé Fixie qui utilise ActiveRecord pour pré-remplir la base de données de test, de sorte que le des documents dont vous avez besoin pour vos tests sont déjà créés. Vous pouvez utiliser Fixie avec factorygirl si vous voulez créer de nouveaux enregistrements à l'exécution, aussi.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top