如何避免为实现相同接口的类编写重复的单元测试?

时间:2010-11-10 22:36:38

标签: c# .net unit-testing visual-studio-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 个答案:

答案 0 :(得分:5)

Greg Young的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 :(得分:1)

您的最终代码段:

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

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

失败就像在我的电脑上一样。有时,visual studio可能会对旧dll感到困惑并运行旧版本的测试(或正在测试的库),如果重命名测试方法,重命名是否会在测试运行器中反映出来?

P.S。我认为你使用TestAnimal(IAnimal animal)的方法是理想的......