【发布时间】:2009-02-12 12:45:13
【问题描述】:
我有一个关于单元测试的问题。假设我有几个类从父类继承行为。我不想测试所有子类的这种行为。相反,我会测试父类。但是,我还应该提供一个测试来证明该行为在子类中可用。你认为像 Assert.IsTrue(new ChildClass() is ParentClass) 这样的东西有意义吗?
【问题讨论】:
标签: c# unit-testing tdd
我有一个关于单元测试的问题。假设我有几个类从父类继承行为。我不想测试所有子类的这种行为。相反,我会测试父类。但是,我还应该提供一个测试来证明该行为在子类中可用。你认为像 Assert.IsTrue(new ChildClass() is ParentClass) 这样的东西有意义吗?
【问题讨论】:
标签: c# unit-testing tdd
如果你使用的是最先进的单元测试框架,我不明白这个说法
我不想测试所有子类的这种行为。
如果您将子类的实例交给单元测试(针对父类的实例编写)应该不会发生变化,假设您的子类没有'不要以破坏继承方法契约的方式覆盖父行为的某些方面。这正是您需要测试的内容,不是吗?
如果您担心运行测试所需的时间,我会仔细检查以确保您的测试已分区,以便您可以根据您正在积极处理的内容有选择地运行测试(但仍然定期运行完整的产品组合以捕获意外的依赖关系。)
【讨论】:
让您的测试从基类测试继承,[非常]大致是这样的。
public class MyBaseClass
{
public virtual void DoStuff() { }
public virtual void DoOtherStuff() { }
}
public class MySubClass : MyBaseClass
{
public override void DoOtherStuff()
{
// different to to base
}
}
public abstract class TestOfBaseClass
{
protected abstract MyBaseClass classUnderTest { get; }
[TestMethod]
public void TestDoStuff()
{
classUnderTest.DoStuff();
Assert.StuffWasDone();
}
}
[TestClass]
public class WhenSubclassDoesStuff : TestOfBaseClass
{
protected override MyBaseClass classUnderTest
{
get { return new MySubClass(); }
}
[TestMethod]
public void ShoudDoOtherStuff()
{
classUnderTest.DoOtherStuff();
Assert.OtherStuffDone();
}
}
大多数流行的测试框架在运行子类测试时都会运行基础测试中的测试方法。
【讨论】:
我认为编写继承有效的测试是浪费时间。如果您尝试使用基类方法,编译器将检查它们是否可用,假设您没有使用智能感知。我可能会在一个子类中测试行为,然后只在每个修改行为的子类(或行为所依赖的某些状态)中测试。
【讨论】:
writing a test that inheritance works is a waste of time. The compiler will check... 单元测试捕获的问题和编译器捕获的问题是完全分开的。单元测试需要编译才能成功。 The compiler will check that the base class methods are available if you try to use them 问题不在于遵守基类契约,而是确认(正确继承的方法)内部的 行为 是一致的。
您不想测试对象的类型,除非它来自无类型的工厂方法。否则,您正在针对 C# 编译器编写单元测试,这不是您想要做的。
【讨论】:
C# 编译器会为您处理此类检查。
如果你喜欢,你可以写这样的东西:
ParentClass childClass = new ChildClass()
var testOutput = childClass.ParentMethod();
Assert.IsNotNull(testOutput);
【讨论】:
我的观点是你的测试结构应该反映你的对象结构 所以如果你有继承自 Class Vehicle 的 Class Car
那么你应该有继承自 Class TestVehicle 的 Class TestCar
通过这样做,Test car 会自动继承所有 Vehicle 测试的正确测试,这意味着如果该函数在 Car 中被覆盖,它很可能会破坏测试,突出显示 Car 中需要 Overriden Test 以支持新行为,如果测试没有被破坏,那么覆盖可能首先是多余的
例如
class Vehicle
{
public virtual bool LicenceRequired
{
get{throw new NotImplmentedException()
}
}
class Bicycle:Vehicle
{
public override bool LicenceRequired
{
get{return false;}
}
}
class Car:Vehicle
{
public override bool LicenceRequired
{
get{return true;}
}
}
class TestVehicle
{
public virtual Void LicenceRequiredTest()
{
Try
{
LicenceRequired
Assert.Fail();
}
Catch(){}
}
}
class TestBicycle:TestVehicle
{
public override void LicenceRequiredTest()
{
Assert.IsFalse(LicenceRequired);
}
}
class TestCar:TestVehicle
{
public override void LicenceRequiredTest()
{
Assert.IsTrue(LicenceRequired);
}
}
注意:仅应在测试继承对象时使用继承,而不仅仅是因为您想对 10 个不相关的对象进行相同的测试。如果您想这样做,我建议您使用静态助手类
【讨论】:
您可以使用两种方法来测试基类的行为:
不要费心去验证继承是否真的有效(整个Assert.IsTrue(new ChildClass() is ParentClass) 事情)。你应该只测试行为。这是 .Net 框架的一个结构特征(继承),您应该相信它是有效的,否则您会发现自己在检查框架功能时会陷入螺旋式下降。
【讨论】: