【发布时间】:2017-01-25 18:00:52
【问题描述】:
我有一个方法,里面有很多条件:
public bool IsLegalSomething(Order order)
{
var item0 = order.Items.SingleOrDefault(x => x.ItemCode == "ItemCode0");
var item1 = order.Items.SingleOrDefault(x => x.ItemCode == "ItemCode1");
...
var itemN = order.Items.SingleOrDefault(x => x.ItemCode == "ItemCodeN");
return ((item0.Status == Status.Open) && (item1.Status == Status.Closed)
&& ...
&& (itemN.Status == Status.Canceled));
}
我想对这个函数进行单元测试,但是如果你考虑每个组合,单元测试的数量太多了,以至于单元测试的数量是疯狂的。该返回语句中有 16 个条件,并且由于每个条件都是真/假,即 2^16 种不同的组合,我需要检查。我真的需要在这里创建 2^16 个不同的单元测试来确保每个条件都被利用吗?请注意,这是一个简单的例子。由于法律要求,我的一些功能具有复杂的条件:
return (condition0 && condition1 && (condition2 || condition3)
&& (condition4 || (condition5 && condition6)) ...)
根据我的一些函数的数学计算,条件可以产生的不同组合的数量是数百万!我研究了数据驱动单元测试 (DDUT) 以及参数化单元测试 (PUT),但这只是让单元测试成为“填空”风格。我仍然必须提供所有各种组合和预期的结果!例如:
// Parameterized Unit Test
[TestCase(..., Result = true)] // Combination 0
[TestCase(..., Result = true)] // Combination 1
[TestCase(..., Result = false)] // Combination 2
public bool GivenInput_IsLegalSomething_ReturnsValidResult(...) { }
如果我使用 MSTest 来提取数据源(例如 csv),我仍然会遇到同样的问题。我有太多的组合会产生不同的结果。有没有我不知道的替代方法?
【问题讨论】:
-
设计可能需要审查和重构。创建单元测试的复杂性/难度是被测试代码干净程度的一个指标。正在测试的方法做得太多了。
-
@Nkosi,可以理解,但我不确定如何“简化”具有这么多组合的法律要求。在一天结束时,某些类将包含“16 个条件驱动一个布尔值”的逻辑。
-
@Nkosi 是正确的。
-
你可以编写一个单一的测试方法来循环生成的组合。否则,我会考虑专注于业务用例。在这种情况下,您可能希望将“IsLegalSomething”重构为多个方法,每个方法都基于这些业务用例测试单个事物。
-
@PeterRitchie:这正是问题所在,IsLegalSomething 是一个代码单元,它需要 16 个条件并返回 1 个结果。如何重构说 16 个输入导致 1 个输出的代码?
标签: c# unit-testing data-driven-tests parameterized-unit-test