هل يجب علي تغيير اصطلاح التسمية لاختبارات الوحدة الخاصة بي؟

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

سؤال

أستخدم حاليًا اتفاقية بسيطة لاختبارات الوحدة الخاصة بي.إذا كان لدي فصل دراسي باسم "EmployeeReader"، فأنا أقوم بإنشاء فصل اختبار باسم "EmployeeReader.Tests.أقوم بعد ذلك بإنشاء جميع الاختبارات للفصل في فصل الاختبار بأسماء مثل:

  • قراءة_صحيحة_بيانات_الموظف_بشكل_صحيح_توليد_كائن_الموظف
  • قراءة_مفقودة_بيانات_الموظف_الاستثناء_غير صالح_معرف_الموظف

وما إلى ذلك وهلم جرا.

لقد قرأت مؤخرًا عن أ نوع مختلف من اصطلاح التسمية المستخدمة في BDD.تعجبني سهولة قراءة هذه التسمية، لينتهي الأمر بقائمة من الاختبارات مثل:

  • متى_القراءة_صالحة_للموظف (التركيبات)
    • تم إنشاء_كائن_الموظف (الطريقة)
    • الموظف_لديه_معرف_صحيح (الطريقة)
  • متى_القراءة_مفقود_الموظف (اللاعب الثابت)
    • An_Invalid_Employee_ID_Exception_Is_Thrown (الطريقة)

وما إلى ذلك وهلم جرا.

هل استخدم أي شخص كلا الأسلوبين في التسمية؟هل يمكنك تقديم أي نصيحة أو فوائد أو عيوب أو مسكتك وما إلى ذلك؟لمساعدتي في تحديد ما إذا كنت سأقوم بالتبديل لمشروعي القادم أم لا؟

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

المحلول

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

لا تحتاج إلى الاستقرار على أحدهما أو الآخر كمعيار.نحن نستخدم مزيجًا من الاثنين، اعتمادًا على عدد "المهام" المختلفة التي يتعين علينا اختبارها لكل فصل.

نصائح أخرى

اصطلاح التسمية الذي كنت أستخدمه هو:

functionName_shouldDoThis_whenThisIsTheSituation

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

pop_shouldThrowEmptyStackException_whenTheStackIsEmpty

pop_shouldReturnTheObjectOnTheTopOfTheStack_whenIsAnObjectOnTheStack

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

جزء من السبب وراء اصطلاح التسمية الثاني الذي تشير إليه هو أنك تقوم بإنشاء اختبارات ومواصفات سلوكية في نفس الوقت.أنت تحدد السياق الذي تحدث فيه الأشياء وما الذي يجب أن يحدث بالفعل في هذا السياق.(في تجربتي، غالبًا ما تبدأ طرق الملاحظات/الاختبار بـ "should_"، لذلك تحصل على التنسيق القياسي "When_the_invoicing_system_is_told_to_email_the_client،" و"should_initiate_connection_to_mail_server".)

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

اعتمادًا على القصة/الميزة/النظام الفرعي الذي تعمل عليه، يمكن عرض هذه المواصفات وفهمها لأصحاب المصلحة غير المبرمجين للتحقق منها وإبداء التعليقات، وهو ما يقع في قلب Agile وBDD على وجه الخصوص.

أستخدم الطريقة الثانية، وهي تساعد حقًا في وصف ما يجب أن يفعله برنامجك.أستخدم أيضًا الفئات المتداخلة لوصف سياق أكثر تفصيلاً.

في جوهرها، فئات الاختبار هي سياقات، والتي يمكن أن تتداخل، والأساليب كلها تأكيدات سطر واحد.على سبيل المثال،

public class MyClassSpecification
{
    protected MyClass instance = new MyClass();

    public class When_foobar_is_42 : MyClassSpecification 
    {
        public When_foobar_is_42() {
            this.instance.SetFoobar( 42 ); 
        }

        public class GetAnswer : When_foobar_is_42
        {
            private Int32 result;

            public GetAnswer() {
                this.result = this.GetAnswer();
            }

            public void should_return_42() {
                Assert.AreEqual( 42, result );
            }
        }
    }
}

والذي سيعطيني الإخراج التالي في عداء الاختبار الخاص بي:

MyClassSpecification+When_foobar_is_42+GetAnswer
    should_return_42

لقد سلكت الطريقين اللذين تصفهما في سؤالك بالإضافة إلى بعض الطرق الأخرى ...البديل الأول الخاص بك واضح جدًا وسهل الفهم بالنسبة لمعظم الناس.أنا شخصياً أحب أسلوب BDD (مثالك الثاني) أكثر لأنه يعزل سياقات مختلفة ويجمع الملاحظات حول تلك السياقات.الجانب السلبي الوحيد هو أنه يولد المزيد من التعليمات البرمجية، لذا فإن البدء في القيام بذلك يبدو مرهقًا بعض الشيء حتى ترى الاختبارات الدقيقة.أيضًا، إذا كنت تستخدم الميراث لإعادة استخدام إعداد التركيبات، فأنت تريد مُختبرًا يقوم بإخراج سلسلة الميراث.ضع في اعتبارك فئة "An_empty_stack" وتريد إعادة استخدامها حتى تقوم بعد ذلك بفصل دراسي آخر:"عندما يتم_الخمسة_الضغط_على:An_empty_stack" تريد ذلك كإخراج وليس فقط "When_five_is_pushed_on".إذا كان اختبارك لا يدعم هذا، فستحتوي اختباراتك على معلومات زائدة عن الحاجة مثل:"عندما_five_is_pushed_on_empty_stack :An_empty_stack" فقط لجعل الإخراج جميلًا.

أصوت لاستدعاء فئة حالة الاختبار:StaffReaderTestCase واستدعاء الأساليب () مثل http://xunitpatterns.com/Organization.html و http://xunitpatterns.com/Organization.html#Test%20Naming%20Conventions

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