هل يجب أن أستخدم اختبار "الصندوق الزجاجي" عندما يؤدي ذلك إلى اختبارات *أقل*؟

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

سؤال

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

من خلال اختبار "الصندوق الأسود" للفصل، قمت بفحص أشياء مثل

  • ماذا لو كان الملف غير موجود؟
  • ماذا لو لم يكن لدي إذن بالملف؟
  • ماذا لو كان الملف يحتوي على فواصل أسطر غير تابعة لنظام التشغيل Windows؟

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

لقد رأيت الأسئلة ذات الصلة

سؤالي هو، هل أفتقد المغزى من اختبار "الصندوق الزجاجي" إذا استخدمت ما أعرفه يتجنب هذا النوع من العمل؟

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

المحلول

يعتمد هذا حقًا على واجهة CsvReader، وعليك أن تأخذ في الاعتبار ما يتوقعه مستخدم الفصل.

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

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

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

نصائح أخرى

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

[تحرير] مثال على حقن التبعية (انظر الرابط أعلاه لمزيد من المعلومات)

عدم استخدام حقن التبعية لدينا:

public class CvsReader {
   private string filename;
   public CvsReader(string filename)
   {
      this.filename = filename;
   }

   public string Read()
   {
      StreamReader reader = new StreamReader( this.filename );
      string contents = reader.ReadToEnd();
      .... do some stuff with contents...
      return contents;
   }
}

مع حقن التبعية (حقن المنشئ) نقوم بما يلي:

public class CvsReader {
   private IStream stream;
   public CvsReader( IStream stream )
   {
      this.stream = stream;
   }

   public string Read()
   {
       StreamReader reader = new StreamReader( this.stream );
       string contents = reader.ReadToEnd();
       ...  do some stuff with contents ...
       return contents;
   }
}

يتيح ذلك إمكانية اختبار CvsReader بسهولة أكبر.نقوم بتمرير مثيل لتنفيذ الواجهة التي نعتمد عليها في المُنشئ، في هذه الحالة IStream.ولهذا السبب يمكننا إنشاء فئة أخرى (ربما فئة وهمية) تقوم بتنفيذ IStream، ولكنها لا تقوم بالضرورة بإدخال/إخراج الملف.يمكننا استخدام هذه الفئة لتغذية القارئ بأي بيانات نريدها دون إشراك أي من الإطار الأساسي.في هذه الحالة، سأستخدم MemoryStream لأننا نقرأ منه للتو.أردنا، على الرغم من ذلك، أن نتمكن من استخدام فئة وهمية ومنحها واجهة أكثر ثراءً تتيح لاختباراتنا تكوين الاستجابات التي تقدمها.بهذه الطريقة يمكننا اختبار الكود الذي نكتبه دون تضمين كود إطار العمل الأساسي على الإطلاق.بدلاً من ذلك، يمكننا أيضًا تمرير TextReader، لكن نمط حقن التبعية العادي يستخدم واجهات وأردت إظهار النمط مع الواجهات.يمكن القول إن تمرير TextReader سيكون أفضل نظرًا لأن الكود أعلاه لا يزال يعتمد على تطبيق StreamReader.

نعم، ولكن ذلك سيكون حصريًا لأغراض اختبار الوحدة:

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

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

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

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

مجرد معلومات، إذا كان هذا هو .NET، فيجب أن تفكر في عدم إعادة اختراع العجلة.

بالنسبة لـ C#

إضافة مرجع إلى microsoft.visualbasic استخدم الفئة الرائعة Microsoft.visualbasic.fileio.textfieldparser () للتعامل مع احتياجات تحليل CSV الخاصة بك.

قامت Microsoft باختباره بالفعل، لذا لن تضطر إلى القيام بذلك.

يتمتع.

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

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