Вопрос

Я ищу способ ускорить свой Должен ли + ФабрикаДевушка тесты.

Модель, которую я пытаюсь протестировать (StudentExam) имеет ассоциации с другими моделями.Эти связанные объекты должны существовать, прежде чем я смогу создать StudentExam.По этой причине они создаются в setup.

Однако одна из наших моделей (School) требует значительного времени для создания.Потому что setup звонят перед каждым should оператор, выполнение всего тестового примера занимает целую вечность — он создает новый @school, @student, @topic и @exam для каждого выполненного оператора must.

Я ищу способ создать эти объекты один раз и только один раз.Есть ли что-то вроде startup для before_all метод, который позволил бы мне создавать записи, которые будут сохраняться на протяжении всей остальной части тестового примера?

По сути, я ищу что-то точно такое же, как у RSpec. до(:все).Меня не беспокоит проблема зависимостей, поскольку эти тесты никогда не изменят эти дорогостоящие объекты.

Вот пример тестового примера.Извиняюсь за длинный код (я также создал суть):

# 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
Это было полезно?

Решение

Если проблема заключается в создании этих записей только один раз, вы можете использовать переменную класса.Это не совсем чистый подход, но, по крайней мере, он должен работать.

# 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

РЕДАКТИРОВАТЬ:Чтобы исправить некрасивый обходной путь, отложите вычисление с помощью метода экземпляра.

# 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

Другие советы

Какие тесты вы пытаетесь написать?Если вы действительно хотите убедиться, что все эти объекты координируются должным образом, вы пишете интеграционный тест, и скорость не является вашей главной заботой.Однако, если вы пытаетесь выполнить модульное тестирование модели, вы можете добиться лучших результатов, если будете агрессивно заглушать.

Например, если вы пытаетесь проверить, что экзамен использует имя ассоциации школы, когда вы вызываетеexam.location (или как вы его называете), вам не нужен целый объект школы.Вам просто нужно убедиться, что экзамен вызывает правильный метод в школе.Чтобы проверить это, вы можете сделать что-то вроде следующего (используя Test::Unit и Mocha, потому что это то, с чем я знаком):

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

По сути, если вам нужно ускорить модульные тесты, поскольку создание объектов слишком дорого, вы на самом деле не занимаетесь модульным тестированием.Кажется, что все приведенные выше тестовые примеры должны быть на уровне модульного теста, поэтому заглушка-заглушка!

http://m.onkey.org/2009/9/20/make-your-shoulda-tests-faster-with-fast_context — отличный пост о том, как ускорить тестирование musta/factory-girl с помощью драгоценного камня под названием fast_context.Дайте мне знать, если это не то, что вам нужно.

Есть плагин под названием быстрый_контекст (ссылка на гитхаб), который объединяет операторы must в единый контекст, ускоряя тесты.

Еще одна вещь, которую я использую для ускорения своих тестов, — это предварительное заполнение данных о приспособлениях.FactoryGirl работает медленно, поскольку создает эти записи каждый раз при запуске блока настройки.

Я написал плагин под названием Фиксики который использует ActiveRecord для предварительного заполнения тестовой базы данных, поэтому записи, необходимые для ваших тестов, уже созданы.Вы можете использовать Fixie вместе с FactoryGirl, если хотите также создавать новые записи во время выполнения.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top