سؤال

بادئ ذي بدء ، أعلم أنه من الممارسات السيئة أن يكون لديك تأكيدات متعددة في اختبار الوحدة.

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

class Account 
  attr_accessor :balance

  def transfer(to_account, amount)
    self.balance -= amount
    to_account.balance += amount
    Audit.create(message: "Transferred #{amount} from #{self.number} to #{to_account.number}."
  end

end

في هذه الحالة أريد أن تحقق 3 أشياء معا:

  1. انخفض رصيد حساب المصدر بمقدار amount
  2. زيادة رصيد حساب الوجهة بمقدار amount
  3. يتم إدراج سجل التدقيق

ما هي أفضل طريقة لاختبار @account.transfer طريقة?

هل كانت مفيدة؟

المحلول

في هذه الحالة أريد أن تحقق 3 أشياء معا:

أود أن أزعم أن ما تريده حقا هو وصف سلوك هذه الأشياء في ظل ظروف معينة ، وبالتالي التأكد من أن السلوك يلبي مواصفاتك.قد يعني ذلك أن الأمور تحدث معا;أو قد يعني ذلك أن بعض الأشياء تحدث فقط في مجموعة واحدة من الشروط وليس غيرها ، أو أن الاستثناء يتسبب في إرجاع كل شيء إلى حالته الأصلية.

لا يوجد سحر لوجود كل تأكيداتك في اختبار واحد ، باستثناء جعل الأمور أسرع.ما لم تكن تواجه عقوبة أداء شديدة (كما يحدث غالبا في اختبارات المكدس الكامل) ، فمن الأفضل بكثير استخدام تأكيد واحد لكل اختبار.

رسبيك يجعل من واضحة لاستخراج مرحلة الإعداد الاختبار بحيث يتكرر لكل مثال:

class Account 
  attr_accessor :balance

  def transfer(to_account, amount)
    self.debit!(amount)
    to_account.credit!(amount)
    Audit.create!(message: "Transferred #{amount} from #{self.number} to #{to_account.number}."
  rescue SomethingBadError
    # undo all of our hard work
  end

end

describe Account do
  context "when a transfer is made to another account" do
    let(:other_account} { other_account }
    context "and the subject account has sufficient funds" do
      subject { account_with_beaucoup_bucks }
      it "debits the subject account"
      it "credits the other account"
      it "creates an Audit entry"
    end
    context "and the subject account is overdrawn" do
      subject { overdrawn_account }
      it "does not debit the subject account"
      it "does not credit the other account"
      it "creates an Audit entry" # to show the attempted transfer failed
    end
  end
end

إذا مرت جميع الاختبارات الثلاثة في "المسار السعيد" ، فكلها "حدثت معا" ، لأن حالة النظام الأولية كانت هي نفسها في كل حالة.

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

نصائح أخرى

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

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

  • 1 لاختبار سلوك الحساب الجاري (أبسط الحالات);
  • 1 لكل مسار مختلف يمكن أن يكون للطريقة (استثناءات ، سلبية التوازن الخ.);
  • 1 لاختبار التدقيق في كل من هذه الاحتمالات;

  • 1 لاختبار سلوك الحساب الحالي (أبسط حالة);

  • 1 لكل مسار مختلف يمكن أن يكون الأسلوب.(استثناءات ، سلبية التوازن الخ.) ;
  • 1 لاختبار التدقيق في كل من هذه الاحتمالات;

نظرا لأن اختبار التدقيق بسيط جدا ولا يتطلب أي إعداد إضافي ، يمكنك أيضا اختباره مع الحساب والحساب.

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