Как можно избежать написания повторяющихся модульных тестов для классов, которые реализуют один и тот же интерфейс? - PullRequest
7 голосов
/ 11 ноября 2010

Я только вхожу в модульные тесты с использованием 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 ]

5 голосов
/ 11 ноября 2010

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, но я думаю, что это довольно умная идея и очень простой рабочий процесс.

1 голос
/ 11 ноября 2010

Ваш окончательный фрагмент кода:

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

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

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

PS Думаю, ваш подходс TestAnimal(IAnimal animal) идеально ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...