يجب أن + factorygirl: هل يمكنني إجراء اختباراتي بشكل أسرع؟

StackOverflow https://stackoverflow.com/questions/1670699

سؤال

أنا أبحث عن وسيلة لتسريع بلدي صراحة + فتاة المصنع اختبارات.

النموذج الذي أحاول اختباره (StudentExam) لديه جمعيات إلى نماذج أخرى. يجب أن تكون هذه الكائنات المرتبطة موجودة قبل أن أتمكن من إنشاء StudentExam. وبعد لهذا السبب، يتم إنشاؤها في setup.

ومع ذلك، واحدة من نماذجنا (School) يأخذ وقتا كبيرا لإنشاء. لان setup يحصل دعا من قبل كل should البيان، فإن حالة الاختبار بأكملها تأخذ eons لتنفيذ - إنه يخلق جديد @school, @student, @topic و @exam لكل بيان تنفيذها.

أبحث عن طريقة لإنشاء هذه الكائنات مرة واحدة وفقط مرة واحدة فقط. وبعد هل هناك شيء مثل 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

نصائح أخرى

أي نوع من الاختبارات تحاول الكتابة؟ إذا كنت ترغب بالفعل في التأكد من أن كل هذه الكائنات تنسق بشكل مناسب، فأنت تكتب اختبار التكامل والسرعة ليست مصدر قلقك الأساسي. ومع ذلك، إذا كنت تحاول وحدة اختبار النموذج، فيمكنك تحقيق نتائج أفضل من قبل stubbing بقوة.

على سبيل المثال، إذا كنت تحاول التحقق من أن الامتحان يستخدم اسم جمعية مدرسته عند الاتصال بالامتحان. الموقع (أو ما كنت تتصل به)، فلن تحتاج إلى كائن مدرسة بأكمله. تحتاج فقط إلى التأكد من أن الامتحان يدعو الطريقة الصحيحة في المدرسة. لاختبار ذلك، يمكنك القيام بشيء مثل ما يلي (باستخدام الاختبار :: وحدة ومخي لأن هذا ما أعرفه):

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-ast_context. هو منشور ممتاز حول كيفية جعل اختبارات فتات المصنع / المصنع الخاصة بك بشكل أسرع، باستخدام جوهرة يسمى fast_context. اسمحوا لي أن أعرف إذا لم يكن ما تحتاجه.

هناك مكون إضافي يسمى fast_context. (رابط جيثب) يجمع بين التصريحات في سياق واحد، وتسريع الاختبارات.

الشيء الآخر الذي كنت أستخدمه لتسريع اختباراتي هو ما قبل ملء بيانات المباراة. FactoryGirl بطيء لأنه يخلق هذه السجلات في كل مرة يعمل فيها كتلة الإعداد.

كتبت مكونا مكونا يسمى fixie. يستخدم هذا activerecord لملء قاعدة بيانات الاختبار مسبقا، لذلك يتم إنشاء السجلات التي تحتاجها للاختبارات الخاصة بك بالفعل. يمكنك استخدام Fixie جنبا إلى جنب مع FactoryGirl إذا كنت ترغب في إنشاء سجلات جديدة في وقت التشغيل، أيضا.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top