单元测试是否应该测试所有通过条件以及所有失败条件?
例如,假设我有一个 test Widget_CannotActiveWidgetIfStateIsCancelled
。
假设有 100 种可能的状态。
我可以只测试当状态 == 取消时我无法激活我的小部件,还是我还必须测试我可以在其他 99 个状态中激活它吗?
是否有一些妥协可以让我避免把所有的时间都花在编写测试上?:)
单元测试是否应该测试所有通过条件以及所有失败条件?
例如,假设我有一个 test Widget_CannotActiveWidgetIfStateIsCancelled
。
假设有 100 种可能的状态。
我可以只测试当状态 == 取消时我无法激活我的小部件,还是我还必须测试我可以在其他 99 个状态中激活它吗?
是否有一些妥协可以让我避免把所有的时间都花在编写测试上?:)
您似乎在问您的测试是否应该详尽无遗:您是否应该测试所有可能的状态。答案是否定的,原因很简单,即使是简单的代码也可能有太多的状态。即使是小程序也可能具有比可测试更多的潜在状态,即使您自大爆炸以来一直使用这些状态。
您应该改为使用等价分区:识别状态组,以便组中的所有状态都可能具有相似的行为,然后每组有一个测试用例。
如果你这样做,你可能会发现你只需要两个测试用例。
在这种情况下,您希望使用一个参数化测试,该测试将所有 99 个值作为输入。
使用 xUnit.net,这可能看起来像这样(未经测试,可能包含小的编译错误):
[Fact]
public void Widget_CannotActiveWidgetIfStateIsCancelled()
{
// Arrange ...
sut.State = State.Cancelled;
Assert.False(sut.CanActivate);
}
[Theory, ValidStatesData]
public void Widget_CanActivateWidgetIfStateIsNotCancelled(State state)
{
// Arrange ...
sut.State = state;
Assert.True(sut.CanActivate);
}
private class ValidStatesDataAttribute : DataAttribute
{
public override IEnumerable<object[]> GetData(
MethodInfo methodUnderTest, Type[] parameterTypes)
{
return Enum.GetValues(typeof(State))
.Cast<State>()
.Except(new [] { State.Cancelled })
.Select(x => new object[] { x });
}
}
如果您使用 NUnit,则可以使用属性,因此您只需编写一个测试代码,但可以测试所有 100 个值。