2010-11-10 13 views
7

Sto appena entrando nei test unitari utilizzando Visual Studio 2010. Mi chiedo se esiste un flusso di lavoro che mi consenta di creare una serie di test applicabili a un'interfaccia e quindi applicare tali test di interfaccia a qualsiasi classe che implementano l'interfaccia.Come evitare di scrivere test di unità duplicati per classi che implementano la stessa interfaccia?

Ad esempio, ho la seguente interfaccia.

public interface IAnimal 
{ 
    public string Name {get;} 
    public string Speak(); 
} 

Potrei ovviamente avere un numero di classi che implementano questa interfaccia.

public class Dog:IAnimal 
{ 
    public string Name {get{return "Dog";}} 
    public string Speak{return "BARK BARK";} 
    public bool LickBalls(); 
} 

public class Cat:IAnimal 
{ 
    public string Name {get{return "Cat";}} 
    public string Speak{return "MEOW MEOW";} 
    public bool Scratch(); 
} 

Così mi piacerebbe definire una serie di test che si applicano a tutti IAnimals

public TestAnimalName(IAnimal animal) 
    {  
     Assert.IsFalse(string.IsNullorEmpty(animal.Name)); 
    } 

    public TestAnimalSpeak(IAnimal animal) 
    {  
     string sound = animal.Speak(); 
     Assert.IsFalse(string.IsNullOrEmpty(sound)); 
    } 

Poi mi piacerebbe definire un metodo di TestAnimal() maestro che potrebbe essere utilizzato per testare qualsiasi IAnimal.

TestAnimal(IAnimal animal) 
{ 
    TestAnimalName(animal); 
    TestAnimalSpeak(animal); 
} 

ho potuto quindi chiamare questo metodo TestAnimal() quando si verifica un tipo concreto di IAnimal.

[TestMethod] 
TestCat() 
{ 
    Cat c = new Cat(); 
    TestAnimal(c); 
} 

[TestMethod] 
TestDog() 
{ 
    Dog c = new Dog(); 
    TestAnimal(c); 
} 

Eppure, quando provo a fare questa operazione in Visual Studio il Asserts nei cosiddetti metodi vengono ignorati. Ho provato a semplificare il problema con il metodo seguente e ho scoperto che è passato anche se chiama un metodo che dovrebbe causare un errore.

Quindi, come posso evitare di scrivere molti test duplicati per le classi che implementano tutti la stessa interfaccia?

+2

wow che è il comportamento interrotto dal test dell'unità VS. se usi NUnit, funzionerebbe come ti aspetti. –

+0

direi che il tuo problema non è scrivere i test, quelli sembrano approcci ragionevoli per me. il problema è il comportamento interrotto nel test dell'unità VS. –

+0

Mentre non conosco la risposta, il metodo "LickBalls" mi ha fatto LOL. – Scottie

risposta

1

snippet di codice finale:

[TestMethod] 
public void AssertInCalledMethod() //this will pass 
{ 
    Assert.IsTrue(true); 
    Blah(); 
} 

public void Blah() 
{ 
    Assert.IsTrue(false); 
} 

fallisce come è concepito per sul mio computer. A volte lo studio visivo può confondersi con le vecchie DLL ed eseguire vecchie versioni dei test (o librerie in fase di test), se si rinomina il metodo di prova, tale nome si riflette nel test runner?

P.S. Penso che il tuo approccio con TestAnimal(IAnimal animal) sia ideale ...

+0

Humm sì, non so cosa stava succedendo prima. Ora l'ho eseguito di nuovo e AssertInCalledMethod restituito non è riuscito come dovrebbe. Quindi sembra che il processo che ho descritto sopra sia la risposta giusta? –

+0

Sì, crea solo i metodi di utilità che hanno senso per le astrazioni con cui vuoi lavorare. Faccio questo (ad esempio) per cose come affermare che due Liste sono uguali (e stampando le differenze in modo piacevole) –

5

Greg Young's Hei Hei Grensesnitt ha un approccio leggermente diverso a questo problema, che mi piace. È possibile scrivere una specifica di interfaccia:

[InterfaceSpecification] 
public class ICanAddTests : AppliesTo<ICanAdd>{ 

    [Test] 
    public void can_add_two_numbers() { 
      Assert.AreEqual(5, sut.Add(2,3)); 
    } 
} 

... e il quadro esegue automaticamente il test per tutte le classi che trova che implementano l'interfaccia. Questo sta usando NUnit, non MSTest, ma penso che sia un'idea abbastanza intelligente e che rende il flusso di lavoro molto semplice.

+0

Cosa succede se [alcune delle] mie classi non hanno un costruttore senza parametri? Non riesco a trovare un esempio di utilizzo di GrensesNittObjectLocator. – zzandy

Problemi correlati