NUnit - كيفية اختبار جميع الطبقات التي تنفذ واجهة خاصة

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

  •  09-06-2019
  •  | 
  •  

سؤال

إذا كان لدي واجهة IFoo ، ولها العديد من الفئات التي تنفيذه ، ما هو أفضل/الأكثر أناقة/أذكى طريقة لاختبار كل تلك الطبقات ضد واجهة ؟

أود أن تقلل من رمز اختبار الازدواجية ، ولكن لا يزال 'البقاء الحقيقي' مبادئ الوحدة الاختبار.

ماذا كنت تنظر في أفضل الممارسات ؟ أنا باستخدام NUnit ، ولكن أعتقد أمثلة من أي اختبار وحدة الإطار أن تكون صالحة

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

المحلول

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

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

E. g.لديك واجهة التالية:

public interface IFoo {

    public void CommonCode();

    public void SpecificCode();

}

قد ترغب في إنشاء فئة مجردة:

public abstract class AbstractFoo : IFoo {

    public void CommonCode() {
          SpecificCode();
    }

    public abstract void SpecificCode();

}

الاختبار سهل ؛ تنفيذ خلاصة الدرجة في الاختبار الدرجة إما باعتبارها الطبقة الداخلية:

[TestFixture]
public void TestClass {

    private class TestFoo : AbstractFoo {
        boolean hasCalledSpecificCode = false;
        public void SpecificCode() {
            hasCalledSpecificCode = true;
        }
    }

    [Test]
    public void testCommonCallsSpecificCode() {
        TestFoo fooFighter = new TestFoo();
        fooFighter.CommonCode();
        Assert.That(fooFighter.hasCalledSpecificCode, Is.True());
    }
}

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

[TestFixture]
public void TestClass : AbstractFoo {

    boolean hasCalledSpecificCode;
    public void specificCode() {
        hasCalledSpecificCode = true;
    }

    [Test]
    public void testCommonCallsSpecificCode() {
        AbstractFoo fooFighter = this;
        hasCalledSpecificCode = false;
        fooFighter.CommonCode();
        Assert.That(fooFighter.hasCalledSpecificCode, Is.True());
    }        

}

وجود فئة مجردة تأخذ الرعاية من واجهة يعني يعطي الكثير من نظافة تصميم التعليمات البرمجية.

آمل أن يكون هذا يجعل الشعور لك.


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

الكثير من أطر تعتمد على هذا النمط السلوكي ، على سبيل المثال ASP.NET حيث لديك لتنفيذ السنانير في صفحة أو عناصر تحكم المستخدم مثل ولدت Page_Load الأسلوب الذي يطلق عليه من قبل Load الحدث, طريقة القالب المكالمات السنانير وراء الكواليس.هناك الكثير من الأمثلة على هذا.أساسا أي شيء لديك لتنفيذ ذلك هو استخدام كلمة "تحميل", "التهيئة" ، أو "تقديم" يسمى قالب الأسلوب.

نصائح أخرى

أنا أختلف مع جون Limjap عندما يقول ،

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

يمكن أن يكون هناك العديد من أجزاء العقد غير المحدد في نوع الإرجاع.اللغة-الملحد على سبيل المثال:

public interface List {

  // adds o and returns the list
  public List add(Object o);

  // removed the first occurrence of o and returns the list
  public List remove(Object o);

}

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

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

إذا كنت لا تريد النفقات العامة من العقود ، أوصي اختبار الحفر ، على غرار ما Spoike الموصى بها:

abstract class BaseListTest {

  abstract public List newListInstance();

  public void testAddToList() {
    // do some adding tests
  }

  public void testRemoveFromList() {
    // do some removing tests
  }

}

class ArrayListTest < BaseListTest {
  List newListInstance() { new ArrayList(); }

  public void arrayListSpecificTest1() {
    // test something about ArrayLists beyond the List requirements
  }
}

أنا لا أعتقد أن هذا هو أفضل الممارسات.

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

إذا كنت تريد حقا أن تكون في السيطرة على طريقة التنفيذ, لديك الخيار:

  • تنفيذ كوسيلة في فئة مجردة و يرث من ذلك.سوف لا تزال بحاجة إلى وراثة إلى فئة محددة ، ولكن كنت متأكدا من أن ما لم يكن ذلك صراحة تنقضها هذا الأسلوب سوف نفعل ذلك الشيء الصحيح.
  • في .NET framework 3.5/C# 3.0 تنفيذ الأسلوب امتدادا لأسلوب الرجوع إلى واجهة

على سبيل المثال:

public static ReturnType MethodName (this IMyinterface myImplementation, SomeObject someParameter)
{
    //method body goes here
}

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

@الامبراطور XLII

أنا أحب صوت اندماجي الاختبارات في MbUnit حاولت مجردة قاعدة الطبقة واجهة اختبار تقنية مع NUnit ، على الرغم من أنها لا تعمل, كنت بحاجة إلى أن يكون منفصل المباراة اختبار لكل واجهة فئة تنفذ (بما في C# لا يوجد وراثة متعددة - على الرغم من أن الطبقات الداخلية يمكن استخدامها ، وهو بارد جدا).في الواقع هذا لا بأس, ربما من المفيد لأنه المجموعات الاختبارات الخاصة بك من أجل تنفيذ الدرجة من واجهة.ولكن سيكون من الجيد إذا كان الإطار يمكن أن تكون أكثر ذكاء.إذا كان بإمكاني استخدام سمة بمناسبة فئة باعتبارها 'الرسمية' اختبار الفصل على واجهة إطار البحث الجمعية تحت الاختبار لجميع الطبقات التي تنفذ واجهة تشغيل تلك الاختبارات على ذلك.

التي من شأنها أن تكون باردة.

ماذا عن الهرمي [TestFixture]s الطبقات ؟ وضع شيوعا اختبار التعليمات البرمجية في قاعدة فئة اختبار وراثة في الاختبار الطفل الطبقات..

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

  • بالنسبة xUnit.net, أنا خلقت نوع محلل مكتبة البحث عن كافة تطبيقات من نوع معين (على xUnit.net امتداد مجرد غلاف رقيق على نوع محلل الأداء الوظيفي ، بحيث يمكن تكييفها للاستخدام في أطر أخرى).
  • في MbUnit, يمكنك استخدام CombinatorialTest مع UsingImplementations السمات على المعلمات.
  • عن أطر أخرى ، قاعدة الطبقة نمط Spoike المذكورة يمكن أن تكون مفيدة.

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

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

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