سؤال

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

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

فقط أتساءل ما هي آراء الناس في هذا؟

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

المحلول

ستكون هذه هي الطريقة الرسمية للقيام بذلك:

// Act
Exception ex = Record.Exception(() => someCode());

// Assert
Assert.Null(ex);

نصائح أخرى

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

إذا لم يكن هناك تأكيد، فهو ليس اختبارا.

توقف عن الكسل - قد يستغرق الأمر بعض الوقت لمعرفة كيفية الحصول على التأكيد هناك، ولكن من المفيد أن تعرف أنه فعل ما توقعت منه أن يفعله.

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

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

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

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

try
{
  unitUnderTest.DoWork()
}
catch
{
  Assert.Fail("code should never throw exceptions but failed with ...")
}

...لكن هذا لا يزال يبدو كريهًا بعض الشيء بالنسبة لي، ربما لأنه يحاول إثبات كونه سلبيًا.

بمعنى ما، أنت تقدم تأكيدًا ضمنيًا - بأن الكود لا يطرح استثناءً.بالطبع سيكون من المفيد الحصول على الملف والعثور على السطر المناسب، ولكن أعتقد أن شيئًا أفضل من لا شيء.

بشكل عام، أرى أن هذا يحدث في اختبار التكامل، فمجرد حقيقة نجاح شيء ما في الاكتمال يعد أمرًا جيدًا بما فيه الكفاية.في هذه الحالة أنا رائع مع ذلك.

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

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

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

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

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

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

يجب أن يوثق اسم الاختبار ذلك.

void TestLogDoesNotThrowException(void) {
    log("blah blah");
}

كيف يتحقق الاختبار مما إذا كان السجل مكتوبًا بدون تأكيد؟

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

يجب أن تؤكد الاختبارات دائمًا شيئًا ما، وإلا ما الذي تثبته وكيف يمكنك إعادة إنتاج الأدلة باستمرار على أن التعليمات البرمجية الخاصة بك تعمل؟

ونحن نفعل ذلك في كل وقت.نحن نسخر من تبعياتنا باستخدام JMock، لذلك أعتقد أن إطار عمل JMock يقوم بالتأكيد نيابةً عنا...ولكن الأمور تسير على هذا النحو.لدينا وحدة تحكم نريد اختبارها:

Class Controller {
  private Validator validator;

  public void control(){
    validator.validate;
  }

  public setValidator(Validator validator){ this.validator = validator; }
}

الآن، عندما نختبر وحدة التحكم، لا نريد اختبار Validator لأنه يحتوي على اختبارات خاصة به.لذلك لدينا اختبار مع JMock فقط للتأكد من أننا نسميه التحقق من الصحة:

public void testControlShouldCallValidate(){
  mockValidator.expects(once()).method("validate");
  controller.control;
}

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

لدينا هؤلاء في كل مكان.إنه تراجع قليلًا نظرًا لأنك قمت بإعداد التأكيد الخاص بك بشكل أساسي ثم قم بإجراء الاتصال بالطريقة التي تم اختبارها.

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

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

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

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

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