سؤال

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

كيف يمكن توثيق اختبارات الوحدات لتحسين فائدتهم عندما تفشل هذه الاختبارات في المستقبل؟ على وجه التحديد، ما الذي يجعل اختبار وحدة جيدة docstring؟

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

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

المحلول

قمت بتوثيق أكثر من اختبارات وحدتي مع اسم الطريقة حصريا:

testInitializeSetsUpChessBoardCorrectly()
testSuccessfulPromotionAddsCorrectPiece()

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

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

testCanMoveStraightUpWhenNotBlocked()
testCanMoveStraightLeftWhenNotBlocked()

ستقوم الأداة بتوليد وثيقة HTML مع محتويات شيء مثل هذا:

Queen requirements:
 - can move straight up when not blocked.
 - can move straight left when not blocked.

نصائح أخرى

ربما لا تكون المشكلة في أفضل التقييد لكتابة ملفات الاختبار، ولكن كيف تكتب الاختبارات نفسها؟ الاختبارات إعادة صياغة هذه الطريقة التي يمكن أن تقطع توثيقها الذاتي شوطا طويلا، ولن يتناقص DocString الخاص بك عندما يتغير الرمز.

هناك بعض الأشياء التي يمكنك القيام بها لجعل الاختبارات أكثر وضوحا:

  • مسح أسماء طرق الاختبار الوصفية (المذكورة بالفعل)
  • يجب أن يكون اختبار الجسم واضحا وموجزا (توثيق الذات)
  • مجردة بعيدا الإعداد المعقدة / الدموع إلخ. في الأساليب
  • أكثر؟

على سبيل المثال، إذا كان لديك اختبار مثل هذا:

def test_widget_run_returns_0():
    widget = Widget(param1, param2, "another param")
    widget.set_option(true)
    widget.set_temp_dir("/tmp/widget_tmp")
    widget.destination_ip = "10.10.10.99"

    return_value = widget.run()

    assert return_value == 0
    assert widget.response == "My expected response"
    assert widget.errors == None

قد تحل محل عبارات الإعداد مع استدعاء طريقة:

def test_widget_run_returns_0():
    widget = create_basic_widget()
    return_value = widget.run()
    assert return_value == 0
    assert_basic_widget(widget)

def create_basic_widget():
    widget = Widget(param1, param2, "another param")
    widget.set_option(true)
    widget.set_temp_dir("/tmp/widget_tmp")
    widget.destination_ip = "10.10.10.99"
    return widget

def assert_basic_widget():
    assert widget.response == "My expected response"
    assert widget.errors == None

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

شيء آخر يجب ملاحظته هو أن طريقة الاختبار الخاصة بك هي أساسا في مستوى واحد من التجريد. شخص يقرأ طريقة الاختبار سترى الخوارزمية هي:

  • إنشاء القطعة
  • استدعاء تشغيل على القطعة
  • تأكيد الكود فعل ما نتوقعه

فهمهم لطريقة الاختبار غير موجزة من خلال تفاصيل إعداد القطعة، وهو مستوى واحد من التجريد أقل من طريقة الاختبار.

النسخة الأولى من طريقة الاختبار تتبع الإعداد المضمنة نمط. النسخة الثانية تتبع طريقة الإنشاء و من المفوض أنماط.

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

لمزيد من ممارسات الاختبار الآلي أفضل الممارسات، هل تحقق أنماط xunit.

يجب أن يصف اسم طريقة الاختبار بالضبط ما تقوم باختباره. يجب أن تقول الوثائق ما الذي يجعل الاختبار فشل.

يجب عليك استخدام مزيج من أسماء الأسلوب الوصف والتعليقات في سلسلة DOC. طريقة جيدة للقيام بذلك بما في ذلك الإجراءات الأساسية والخطوات التحقق في سلسلة DOC. ثم إذا قمت بتشغيل هذه الاختبارات من نوع ما من نوع من الإطار الاختبار الذي يقوم بأتمتة تشغيل الاختبارات وجمع النتائج، فيمكنك تسجيل إطار الإطار محتويات سلسلة DOC لكل طريقة اختبار جنبا إلى جنب مع Stdout + Stderr.

إليك مثال أساسي:

class SimpelTestCase(unittest.TestCase):
    def testSomething(self):
        """ Procedure:
            1. Print something
            2. Print something else
            ---------
            Verification:
            3. Verify no errors occurred
        """
        print "something"
        print "something else"

وجود إجراء مع الاختبار يجعل الأمر أسهل بكثير معرفة ما يفعله الاختبار. وإذا قمت بتضمين DocString مع إخراج الاختبار، فإنه يجعل معرفة ما حدث عند الذهاب إلى النتائج أسهل بكثير. المكان السابق لقد عملت في فعل شيء من هذا القبيل، وقد وضعت بشكل جيد للغاية عندما حدثت الفشل. ركضنا اختبارات الوحدة على كل Checkin تلقائيا، باستخدام CruiseControl.

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

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

لا يحدث إذا كان اسم الترسبات هو Class Rextests واسم الاختبار هو TestMethodx و رسالة الخطأ "من المتوقع صحيح"، خطأ إرجاع ". هذه علامة على كتابة اختبار قذرة.

معظم الوقت يجب ألا تضطر إلى قراءة الاختبار أو أي تعليقات لمعرفة ما حدث.

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