2010-11-10 2 views
7

Я просто участвую в модульных тестах с помощью Visual Studio 2010. Мне интересно, есть ли рабочий процесс, который позволил бы мне создать серию тестов, которые применяются к интерфейсу, а затем применить те тесты интерфейса к любому классу которые реализуют интерфейс.Как избежать дублирования тестов модулей для классов, реализующих один и тот же интерфейс?

Например, у меня есть следующий интерфейс.

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

Возможно, у меня было несколько классов, реализующих этот интерфейс.

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

Так что я хотел бы определить ряд тестов, которые применяются ко всему IAnimals

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

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

Тогда я хотел бы определить TestAnimal() метод мастера, который может быть использован для тестирования любого IAnimal.

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

я мог бы назвать этот метод TestAnimal() при тестировании конкретного типа IAnimal.

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

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

Но когда я пытаюсь сделать это в Visual Studio Asserts в названных методов игнорируются. Я попытался упростить эту проблему с помощью метода ниже и обнаружил, что он прошел, даже если он вызывает метод, который должен привести к ошибке.

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

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

Так как я могу избежать написания множества повторяющихся тестов для классов, которые реализуют один и тот же интерфейс?

+2

wow, что является нарушенным поведением от VS модульного тестирования. если вы используете NUnit, он будет работать так, как вы ожидаете. –

+0

Я бы сказал, что ваша проблема заключается не в написании тестов, они кажутся разумными подходами ко мне. проблема заключается в том, что поведение Busted в VS-модульном тестировании. –

+0

Пока я не знаю ответа, метод «LickBalls» сделал меня LOL. – Scottie

ответ

1

Ваш последний фрагмент кода:

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

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

терпит неудачу, как это означало на моем компьютере. Иногда визуальная студия может запутаться в старых DLL и запускать старые версии ваших тестов (или тестируемых библиотек), если вы переименуете метод тестирования, переименует ли это переименование в тестовом бегуне?

P.S. Я думаю, что ваш подход с TestAnimal(IAnimal animal) идеален ...

+0

Humm yeah, я не знаю, что происходило раньше. Теперь я снова запустил его и возвращаю AssertInCalledMethod, как и следовало ожидать. Так кажется, что процесс, который я описал выше, является правильным ответом? –

+0

Yep - просто создайте любые способы использования полезности для абстракций, с которыми вы хотите работать. Я делаю это (например) для таких вещей, как утверждение о том, что два списка равны (и хорошо распечатывают различия) –

5

Greg Young's Hei Hei Grensesnitt принимает несколько иной подход к этой проблеме, которая мне нравится. Вы можете написать спецификацию интерфейса:

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

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

... и структура автоматически выполняет проверку для всех классов, которые он находит, что реализовать интерфейс. Это использует NUnit, а не MSTest, но я думаю, что это довольно продуманная идея и обеспечивает очень простой рабочий процесс.

+0

Что делать, если [некоторые из] моих классов не имеют конструктора без параметров? Я не могу найти пример использования GrensesnittObjectLocator. – zzandy

Смежные вопросы