Soru NUnit - Belirli bir arayüzü uygulayan tüm sınıfları nasıl test edilir


IFoo arayüzüne sahip olsaydım ve bunu uygulayan çeşitli sınıflar varsa, tüm bu sınıfları arayüze karşı test etmenin en iyi / en şık / en akıllı yolu nedir?

Test kodu çoğaltmayı azaltmak istiyorum, ama yine de “test” prensiplerine “doğru” durmak istiyorum.

En iyi uygulamayı ne düşünürsünüz? NUnit kullanıyorum, ama herhangi bir Ünite test çerçevesinden örneklerin geçerli olacağını düşünüyorum.


29
2017-09-02 08:13


Menşei




Cevaplar:


Eğer sınıflarınız herhangi bir arabirimi uygularsa, o zaman bunların hepsi bu arayüzdeki yöntemleri uygulamalıdır. Bu sınıfları test etmek için, her bir sınıf için bir birim test sınıfı oluşturmanız gerekir.

Bunun yerine daha akıllı bir rota ile gidelim; senin amacın koddan kaçın ve kod çoğaltmayı test et bunun yerine soyut bir sınıf oluşturmak isteyebilirsiniz. yinelenen kodu.

Örneğin. aşağıdaki arayüze sahipsiniz:

public interface IFoo {

    public void CommonCode();

    public void SpecificCode();

}

Soyut bir sınıf oluşturmak isteyebilirsiniz:

public abstract class AbstractFoo : IFoo {

    public void CommonCode() {
          SpecificCode();
    }

    public abstract void SpecificCode();

}

Kolay test etme; soyut sınıfı test sınıfında bir iç sınıf olarak uygular:

[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());
    }
}

... ya da test sınıfının, fantazinize uyuyorsa soyut sınıfı kendisinin uzatmasına izin verin.

[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());
    }        

}

Soyut bir sınıfa sahip olmak, bir arabirimin ima ettiği ortak bir kodla ilgilenir, daha temiz bir kod tasarımı sağlar.

Umarım bu sizin için mantıklıdır.


Bir yan not olarak, bu yaygın olarak adlandırılan bir tasarım modelidir. Şablon Yöntemi modeli. Yukarıdaki örnekte, şablon yöntemi CommonCode yöntem ve SpecificCode bir saplama veya kanca denir. Fikir şu ki, herkes sahnelerin arkasındaki şeyleri bilmeden davranışları uzatabilir.

Bir çok çerçeve bu davranış modeline güvenmektedir, ör. ASP.NET Kancaları bir sayfada ya da oluşturulanlar gibi kullanıcı denetimlerini nerede uygulayacağınız Page_Load tarafından çağrılan yöntem Load olay, şablon yöntemi perde arkasındaki kancaları çağırır. Bunun çok daha fazla örneği var. Temelde uygulamak zorunda olduğunuz her şey "load", "init" veya "render" kelimelerini kullanarak bir şablon yöntemi ile çağrılır.


13
2017-09-02 12:16



@Spoike: +1, ancak küçük bir nitrit, kodunuzun C # olmamasıdır. - user7116
@sixlettervariables: Evet, sanal anahtar kelime ekleyip neyi unuttuğumu unuttum. Bu girişi yazdığımda yapmam gereken tüm Java programlamalarında onu suçluyorum;) - Spoike
Güzel cevap! Günümüzde NUnit, jenerik test sınıflarını desteklemektedir ve TestFixture özniteliği, test çalıştırıldığında kullanılacak belirli türleri sağlamak için kullanılabilir. Yazdım Blog yazısı Bu özellikleri sergileyen bir arayüzün her uygulayıcısını nasıl test edeceğiniz hakkında. - Marjan Venema


Katılmıyorum Jon Limjap ne zaman diyor ki

Her iki yöntemde de bir sözleşme değildir.) Yöntemin nasıl uygulanacağı ve b.) Bu yöntemin tam olarak ne yapması gerektiği (sadece geri dönüş türünü garanti eder), bu türden talepte bulunmamın sebebi iki farklı neden olabilir. testin

İade türünde belirtilmeyen sözleşmenin birçok parçası olabilir. Bir dil-agnostik örnek:

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);

}

Ünitenizin LinkedList, ArrayList, CircularlyLinkedList ve diğerlerinin testleri, yalnızca listelerin kendilerinin de döndüğünü değil, aynı zamanda düzgün bir şekilde değiştirildiklerini de test etmelidir.

Vardı önceki soru Bu testler KURUTMA yönteminin bir yolu üzerinde doğru yönde size yardımcı olabilir sözleşme-tasarım, üzerinde.

Eğer sözleşmelerin ek yükünü istemiyorsan, test çizimlerini, Spoike Tavsiye edilen:

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
  }
}

11
2017-09-02 08:41





Bunun en iyi uygulama olduğunu sanmıyorum.

Basit gerçek şu ki, bir arayüz bir yöntemin uygulandığı bir sözleşmeden başka bir şey değildir. Bu değil a) yöntemi nasıl uygulayacağınız ve b) bu ​​yöntemin tam olarak ne yapması gerektiği (sadece dönüş türünü garanti eder), bu tür bir testi istemeniz için gerekçenizin iki sebebi olacaktır.

Metot uygulamanızı gerçekten kontrol etmek istiyorsanız, aşağıdaki seçeneklere sahipsiniz:

  • Soyut bir sınıfta bir yöntem olarak uygulanması ve bundan miras alınması. Bunu hala somut bir sınıfa miras almanız gerekecek, ancak bu yöntemin doğru olanı yapacağı açık bir şekilde geçersiz kılınmadıkça emin olmalısınız.
  • .NET 3.5 / C # 3.0'da, arabirime referans veren bir uzantı yöntemi olarak yöntemin uygulanması

Örnek:

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

Bu uzantı yöntemine düzgün bir şekilde referans veren herhangi bir uygulama, uzantı yöntemini tam olarak ortaya çıkaracaktır, böylece yalnızca bir kez test etmeniz gerekir.


3
2017-09-05 15:36





@Emperor XLII

MbUnit'teki kombinatoryal testlerin sesini seviyorum, NUnit ile soyut temel sınıf arayüz testi tekniğini denedim ve işe yaramasa da, bir sınıfın uyguladığı her arabirim için ayrı bir test fikstürüne sahip olmanız gerekir (çünkü C # Birden fazla kalıtım yoktur - iç sınıflar da kullanılabilir, ancak oldukça serindir. Gerçekte bu iyi, belki de avantajlıdır, çünkü uygulama sınıfına yönelik testlerinizi arayüzle gruplandırır. Ancak çerçeve daha akıllı olabilirse iyi olur. Bir nesneyi bir arabirim için bir 'resmi' test sınıfı olarak işaretlemek için bir öznitelik kullanabilirsem ve çerçeve, arabirimi uygulayan tüm sınıflar için sınamada sınamada arar ve bu sınamaları çalıştırır.

Süper olurdu.


1
2017-09-14 19:01





[TestFixture] sınıflarının hiyerarşisine ne dersiniz? Genel test kodunu temel test sınıfına koyun ve çocuk test derslerine alın.


1
2017-09-03 00:24





Bir arayüz veya temel sınıf sözleşmesini test ederken, test çerçevesinin tüm uygulayıcıları bulmayı otomatik olarak sağlamasına izin vermeyi tercih ediyorum. Bu, test altındaki arayüze konsantre olmanıza ve çok sayıda manuel uygulama yapmak zorunda kalmadan tüm uygulamaların test edileceğinden emin olmanızı sağlar.

  • İçin xUnit.netBen bir Türü Çözümleyici Belirli bir türdeki tüm uygulamaları aramak için kütüphane (xUnit.net uzantıları, Tür Çözümleyicisi işlevselliği üzerinde sadece ince bir sarıcıdır, bu yüzden diğer çerçevelerde kullanılmak üzere uyarlanabilir).
  • İçinde MbUnit, sen bir CombinatorialTest ile UsingImplementations parametrelerdeki özellikler.
  • Diğer çerçeveler için, taban sınıfı kalıbı Spoike belirtilen yararlı olabilir.

Arayüzün temellerini test etmenin ötesinde, her bir uygulamanın kendi özel gereksinimlerini takip ettiğini de test etmelisiniz.


1
2017-09-02 08:16





NUnit kullanmıyorum ama C ++ arayüzlerini test ettim. İlk olarak, genel içeriklerin çalıştığından emin olmak için temel bir uygulaması olan bir TestFoo sınıfını test ederim. Daha sonra her arayüze özgü olan şeyleri test etmeniz yeterlidir.


0