【发布时间】:2015-11-13 14:20:34
【问题描述】:
我在学习“测试驱动开发”的时候,从“The Productive Programmer”一书中发现了一个有趣的案例:
你需要找到一个“完整数字”的所有因数。一个完整的数字是它所有因素的总和(除了等于数字本身的那个)等于这个数字。所以
6是最小的完整数,它的因数是1, 2, 3。
如果要TDD,首先我要测试一个最简单的测试用例:
@Test public void completeNumber6() {
CompleteNumber completeNumber = new CompleteNumber(6)
assertEquals(completeNumber.findFactors(), new Int[] {1,2,3});
}
但是!问题是这个最简单的案例将驱动findFactors()的所有实现,这对我来说似乎太多了。
作者给出了一些建议,我们可以将需求拆分成几个步骤:
- 检查数字是否是另一个数字的因数
- 提供一种将某些因子收集到集合中的方法
- 检查每个较小的数字,看看它是否是给定数字的因数,收集它们
- 检查收集的因子的总和是否等于给定的数字
我们可以先TDD前两个步骤:
@Test public void testIsFactor() {}
@Test public void testAddFactor() {}
因此之后会有 2 个公共(至少非私有)方法:
boolean isFactor(Int n1, Int n2)
void addFactor(Int factor)
问题是这两种方法在整个实现之后应该是private,因为它们应该只在findFactors 内部使用!
但是如果它们被更改为 private,我们应该如何处理它们的现有测试用例?
作者建议我们可以将它们改为private,并使用Java refection API 来获取和测试它们。听起来可能,但我不确定这样做是否是一个好习惯。
我也问了一些朋友,他们给出了一些其他的选择:
- 保持方法
isFactor和addFactor为非私有方法,这是可以接受的 - 为这 2 个方法提取一个类
FactorChecker和FactorCollector - 将它们更改为 private,并删除测试用例,因为它们的功能已在后面的测试用例中进行了测试(用于第 3 步和第 4 步)
我现在真的很困惑,哪种方法是 TDD 的最佳实践?
【问题讨论】:
-
无答案,但这取决于。这三个都可以与正确的类/方法一起使用。在这种情况下,我认为
isFactor是一个有效的公共方法。 -
如果我执行
new CompleteNumber(1);会发生什么?它会抛出异常吗?你是用 TDD 开发的吗?我认为你应该从那里开始。 -
@Manu 我不认为
1是定义中有效的完整数字,而6是我找到的最小的数字。对于1,它会返回一个空数组,你可以认为我在6之前已经为无效的情况写了这样一个测试。 -
@Manu,感谢您指出这一点
标签: java unit-testing tdd