جعل طريقة خاصة العامة لوحدة اختبار ذلك ... فكرة جيدة؟ [c#]


Answers

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

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

عليك أن تكون عمليا حول هذا الموضوع، ويجب أن تكون أيضا على بينة من الأسباب التي تجعل الامور صعبة لاختبار.

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

وهنا ما مايكل الريش أن يقول في " العمل بشكل فعال مع القانون القديم "

"كثير من الناس يقضون الكثير من الوقت في محاولة أوت معرفة كيفية التغلب على هذه المشكلة ... الجواب الحقيقي هو أنه إذا كان لديك الرغبة في اختبار طريقة خاصة، يجب أن لا تكون الطريقة الخاصة، وإذا جعل الطريقة العامة يزعجك، وهناك احتمالات، لأن ذلك هو جزء من قابلية مستقلة، وينبغي أن يكون على فئة أخرى ". [ العمل بشكل فعال مع قانون تراث (2005) من قبل M. الريش]

Question

مشرف ملاحظة: هناك بالفعل 39 إجابات نشرت هنا (تم حذف بعض). قبل نشر إجابتك، ضع في اعتبارك ما إذا كان بإمكانك إضافة شيء مفيد للمناقشة أم لا. كنت أكثر من المرجح مجرد تكرار ما قاله شخص آخر بالفعل.

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

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

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

تحديث

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

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




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

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

نعم، هذا سيؤدي إلى ملف-- والطبقة-- سخام.

نعم، هذا يجعل من محددات public private زائدة عن الحاجة.

نعم، هذا هو ألم في الحمار.

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

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




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

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




تحديث : لقد أضفت إجابة موسعة وأكثر اكتمالا على هذا السؤال في أماكن أخرى عديدة. هذا هو يمكن العثور على بلدي بلوق .

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

يجب أن يكون استخدام الطرق العامة / باستخدام الحيل اللغوية مثل رمز الوسم مرئيا لاختبار التجميعات الملاذ الأخير.

فمثلا:

public class SystemUnderTest
{
   public void DoStuff()
   {
      // Blah
      // Call Validate()
   }

   private void Validate()
   {
      // Several lines of complex code...
   }
}

ريفاكتور هذا عن طريق إدخال كائن المصادقة.

public class SystemUnderTest
{
    public void DoStuff()
    {
       // Blah
       validator.Invoke(..)
    }
}

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




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

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




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




استخدام انعكاس للوصول إلى المتغيرات الخاصة إذا كنت بحاجة إلى.

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




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

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




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

  1. أسود اختبار مربع

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

  2. أبيض مربع اختبار.

    وتعتقد المدرسة مربع أبيض أنه من الطبيعي أن استخدام المعرفة حول تنفيذ الطبقة ومن ثم اختبار الطبقة لمعرفة أنه يعمل كما ينبغي.

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




الأساليب الخاصة التي تريد اختبارها في عزلة هي مؤشر على أن هناك "مفهوم" آخر دفن في صفك. استخراج "مفهوم" لفئتها الخاصة واختبارها باعتبارها "وحدة" منفصلة.

نلقي نظرة على هذا الفيديو لاتخاذ مثيرة للاهتمام حقا حول هذا الموضوع.




أنا عموما إبقاء فئات الاختبار في نفس المشروع / التجمع كما الطبقات تحت الاختبار.
وبهذه الطريقة أنا فقط بحاجة إلى الرؤية internal لجعل وظائف / فئات قابلة للاختبار.

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

ينطبق هذا بالطبع على جزء C # / .NET فقط من سؤالك




لا، لأن هناك طرق أفضل من السلخ هذا القط.

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

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

أو تذهب للخيار "صديق". شخصيا هذا هو سمة من سمات C ++ أنا أحب أقل لأنه يكسر قواعد التغليف، ولكن يحدث أن يكون ضروريا لكيفية تنفيذ C ++ بعض الميزات، لذلك مهلا حو.

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




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

وهنا فئة مثال صغير مع طريقة مثيل خاص.

public class A {
    private void doSomething() {
        System.out.println("Doing something private.");
    }
}

وفئة مثال الذي ينفذ طريقة المثيل الخاص.

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class B {
    public static final void main(final String[] args) {
        try {
            Method doSomething = A.class.getDeclaredMethod("doSomething");
            A o = new A();
            //o.doSomething(); // Compile-time error!
            doSomething.setAccessible(true); // If this is not done, you get an IllegalAccessException!
            doSomething.invoke(o);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        }
    }
}

تنفيذ B، سيتم طباعة Doing something private. إذا كنت حقا في حاجة إليها، ويمكن استخدام التفكير في اختبارات وحدة للوصول إلى أساليب المثيل الخاص.




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




شخصيا، لدي نفس المشاكل عند اختبار أساليب خاصة وذلك لأن بعض أدوات اختبار محدودة. انها ليست جيدة التصميم الخاص بك لتكون مدفوعة من قبل أدوات محدودة إذا لم يفعلوا ذلك استجابة للحاجة الخاصة بك تغيير أداة وليس التصميم. لأن برنامجك طلب C # لا أستطيع اقتراح أدوات الاختبار جيدة، ولكن لجاوا هناك نوعان من أدوات قوية: TestNG وPowerMock، ويمكنك العثور على أدوات اختبار المقابلة للمنصة. NET