3

感觉自己对TDD很熟练,甚至被我公司认为是“TDD专家”,不过还是有一些情况我觉得不知道怎么处理好,想听听其他人的意见.

我的问题如下:尽管总体上 TDD 帮助我思考一个类的核心职责,并将所有其他职责提取到依赖类,但在某些情况下,一段时间后我意识到其中一个类有多个职责,并且它需要重构并将其拆分为 2 个类。这个结论通常是因为该类的测试开始变得复杂或重复。我可以很容易地进行重构,将这个类拆分为我想要的设计(我分小步进行,保持在绿色栏上)。我的问题是我最终得到了现在一起测试两个类的同样复杂和重复的测试,而我想对每个类进行单独的测试。我能想到的唯一(或多或少安全)的方式,

  1. 复制测试用例
  2. 将测试的一个副本更改为使用模拟而不是第一类,并将测试的另一个副本更改为使用模拟而不是第二类。
  3. 然后,如果我发现其中一个副本已经存在相同的测试,我将其删除。

我认为有时可以执行以下操作:

  1. 首先从头开始创建 2 个类(当然使用 TDD)
  2. 更改旧测试以使用新类而不是旧类
  3. 删除旧类
  4. 删除旧测试

这两种技术看起来都非常麻烦和耗时,所以我想知道:“真正的专家”如何解决这个问题?

4

4 回答 4

2

没有一个实际的例子,我不能确定我知道你的意思。但听起来你试图孤立​​地测试每个类(甚至可能是每个方法)。

当我想要/必须将一个类拆分为多个类时,我仍然倾向于将生成的类集合视为一个单元并作为一个整体进行测试。只有当它们停止构建功能整体并开始成为独立单元时,我才会对它们进行独立测试。

于 2012-09-10T10:44:08.517 回答
1

我首先问自己(就像你一样)一个班级的职责是什么。例如,假设您的班级负责汇总天气数据 生成天气报告

在这一点上,我列出了三 (3) 个列表:

  • 数据聚合成员(属性、行为)
  • 报告生成成员
  • 共同成员

前两个很容易,完全属于一个类的成员完全成为两个新类之一的一部分。我将保留原来的双重职责类作为外观,其成员是新类的传递,因此在重构时不会破坏测试和功能。根据情况,我最终可能会移除外观,并重构测试和依赖对象以使用新类。

至于两个职责共有的成员——我将把它们移到一个帮助类(通常范围为内部),新类(以及任何其他类可能使用)。该功能已被证明可以重复使用,并且可以再次重复使用。请注意,普通成员不一定都属于一个助手类;可以将帮助功能添加到一个新类、多个(当然取决于职责)类中,如果适合的话,可以将某些功能添加到现有帮助器类中。

于 2012-09-11T06:52:34.203 回答
1

我可以很容易地进行重构,将这个类拆分为我想要的设计(我分小步进行,保持在绿色栏上)。我的问题是我最终得到了现在一起测试两个类的同样复杂和重复的测试,而我想对每个类进行单独的测试。

我也走到了这一步。在这里,我开始重构测试,使用与非测试代码相同的技术——将变量转换为字段、移动字段、提取方法、移动变量等。命名当然非常重要,并提供了很多设计指导。

例如http://www.kdgregory.com/index.php?page=junit.refactoring 例如http://www.natpryce.com/articles/000686.html 例如http://www-public.it-sudparis.eu /~gibson/Teaching/CSC7302/ReadingMaterial/vanDeursenMdenBK01.pdf

最后一篇文章有​​一些示例气味和重构常见于重构测试。

于 2012-09-11T05:43:47.020 回答
0

前段时间我想知道这个问题,并没有真正找到令人满意的答案。以下是我发现的关于该主题的一些讨论:

http://tech.groups.yahoo.com/group/testdrivendevelopment/message/27199

http://tech.groups.yahoo.com/group/testdrivendevelopment/message/16227

就个人而言,我采用了一种“一触即发”的方法来将责任转移到依赖关系中,虽然在明确需要新的依赖关系之前“剥离”它有点 YAGNI 的味道,但我发现重新吸收依赖关系事实证明,这太乏力了,不能保证成为一个单独的类,这比从已经为它编写了大量测试的类中分离出一个单独的类所涉及的繁琐工作要容易得多。

编辑:

哦-我可能应该指出我根本不是“真正的专家”;)

于 2012-09-10T10:23:19.817 回答