【问题标题】:How to handle the case that a single simple test case will drive the whole implementation?如何处理单个简单测试用例驱动整个实现的情况?
【发布时间】: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()的所有实现,这对我来说似乎太多了。

作者给出了一些建议,我们可以将需求拆分成几个步骤:

  1. 检查数字是否是另一个数字的因数
  2. 提供一种将某些因子收集到集合中的方法
  3. 检查每个较小的数字,看看它是否是给定数字的因数,收集它们
  4. 检查收集的因子的总和是否等于给定的数字

我们可以先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 来获取和测试它们。听起来可能,但我不确定这样做是否是一个好习惯。

我也问了一些朋友,他们给出了一些其他的选择:

  1. 保持方法 isFactor 和 addFactor 为非私有方法,这是可以接受的
  2. 为这 2 个方法提取一个类 FactorChecker 和 FactorCollector
  3. 将它们更改为 private,并删除测试用例,因为它们的功能已在后面的测试用例中进行了测试(用于第 3 步和第 4 步)

我现在真的很困惑,哪种方法是 TDD 的最佳实践?

【问题讨论】:

  • 无答案,但这取决于。这三个都可以与正确的类/方法一起使用。在这种情况下,我认为isFactor 是一个有效的公共方法。
  • 如果我执行new CompleteNumber(1);会发生什么?它会抛出异常吗?你是用 TDD 开发的吗?我认为你应该从那里开始。
  • @Manu 我不认为1 是定义中有效的完整数字,而6 是我找到的最小的数字。对于1,它会返回一个空数组,你可以认为我在6之前已经为无效的情况写了这样一个测试。
  • @Manu,感谢您指出这一点

标签: java unit-testing tdd


【解决方案1】:

在我看来,问题指出这些是完整的数字这一事实有点无关紧要。您可以计算任何整数的因数。因此,鉴于我将从实现 findFactors(1) 开始,然后逐步进行。

这使得这与经典的 Prime Factors Kata 略有不同,唯一的区别是您将 1 添加到因素列表中。

【讨论】:

    猜你喜欢
    • 2023-01-27
    • 1970-01-01
    • 1970-01-01
    • 2010-12-20
    • 2021-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多