استخدام نفس مجموعة الاختبار في تطبيقات مختلفة لواجهة المستودع

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

سؤال

لقد قمت بإنشاء تطبيق ويب صغير للألعاب بلغة C# على غرار واجهة متجر Rob Connery's Asp.net MVC.

وجدت أن لدي واجهة مستودع، أطلق عليها اسم IFooRepository، مع الأساليب، على سبيل المثال

IQueryable<Foo> GetFoo();
void PersistFoo(Foo foo);

ولدي ثلاثة تطبيقات لهذا:ISqlFooRepository، وIFileFooRepostory، وIMockFooRepository.

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

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

[TestMethod]
Public void GetFoo_NotNull_Test()
{
   IFooRepository repository = GetRepository();
   var results = repository. GetFoo();
   Assert.IsNotNull(results);
}

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

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

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

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

المحلول

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

لتتمكن من إجراء الاختبارات بشكل انتقائي لبعض موفري الخدمة دون غيرهم، فكر في استخدام سمة MbUnit '[FixtureCategory]' لتصنيف اختباراتك - الفئات المقترحة هي "سريعة" و"بطيئة" و"db" و"مهمة" و"غير مهمة" ( الأخيرين نكتة - صادقة!)

نصائح أخرى

في MbUnit، قد تتمكن من استخدام سمة RowTest لتحديد المعلمات في الاختبار الخاص بك.

[RowTest]
[Row(new ThisRepository())]
[Row(new ThatRepository())]
Public void GetFoo_NotNull_Test(IFooRepository repository)
{
   var results = repository.GetFoo();
   Assert.IsNotNull(results);
}

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

أي.هذا ما كان يدور في ذهني:

private IRepository GetRepository(RepositoryType repositoryType)
{
    switch (repositoryType)
    {   
          case RepositoryType.Sql:
          // return a SQL repository
          case RepositoryType.Mock:
          // return a mock repository
          // etc
    }
}

private void TestGetFooNotNull(RepositoryType repositoryType)
{
   IFooRepository repository = GetRepository(repositoryType);
   var results = repository.GetFoo();
   Assert.IsNotNull(results);
}

[TestMethod]
public void GetFoo_NotNull_Sql()
{
   this.TestGetFooNotNull(RepositoryType.Sql);
}

[TestMethod]
public void GetFoo_NotNull_File()
{
   this.TestGetFooNotNull(RepositoryType.File);
}

[TestMethod]
public void GetFoo_NotNull_Mock()
{
   this.TestGetFooNotNull(RepositoryType.Mock);
}
[TestMethod]
public void GetFoo_NotNull_Test_ForFile()
{   
   GetFoo_NotNull(new FileRepository().GetRepository());
}

[TestMethod]
public void GetFoo_NotNull_Test_ForSql()
{   
   GetFoo_NotNull(new SqlRepository().GetRepository());
}


private void GetFoo_NotNull(IFooRepository repository)
{
  var results = repository. GetFoo();   
  Assert.IsNotNull(results);
}

خلاصة القول، هناك ثلاث طرق للذهاب:

1) اجعل الاختبارات ذات خطوط واحدة تستدعي الطرق الشائعة (الإجابة بواسطة ريك، وكذلك هالجريم)

2) استخدم ميزة RowTest الخاصة بـ MBUnit لأتمتة هذا (الإجابة بواسطة Jon Limjap).أود أيضًا استخدام التعداد هنا، على سبيل المثال.

[RowTest]
[Row(RepositoryType.Sql)]
[Row(RepositoryType.Mock)]
public void TestGetFooNotNull(RepositoryType repositoryType)
{
   IFooRepository repository = GetRepository(repositoryType);
   var results = repository.GetFoo();
   Assert.IsNotNull(results);
}

3) استخدم فئة أساسية، والإجابة عن طريق belugabob
لقد قمت بعمل عينة بناء على هذه الفكرة

public abstract class TestBase
{
    protected int foo = 0;

    [TestMethod]
    public void TestUnderTen()
    {
        Assert.IsTrue(foo < 10);
    }

    [TestMethod]
    public void TestOver2()
    {
        Assert.IsTrue(foo > 2);
    }
}

[TestClass]
public class TestA: TestBase
{
    public TestA()
    {
        foo = 4;
    }
}

[TestClass]
public class TestB: TestBase
{
    public TestB()
    {
        foo = 6;
    }
}

وينتج عن ذلك أربعة اختبارات اجتياز في فئتين للاختبار.
إيجابيات 3 هي:
1) أقل كود إضافي وأقل صيانة
2) أقل ما يمكن من الكتابة لتوصيل مستودع جديد إذا لزم الأمر - سيتم ذلك في مكان واحد، على عكس الأماكن الأخرى.

السلبيات هي:
1) مرونة أقل في عدم إجراء اختبار ضد مقدم الخدمة إذا لزم الأمر
2) صعوبة القراءة.

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