应用 TDD 时是否有无法测试的内容

Are there things that you can't test when applying TDD

我一直在将 TDD 应用于一些新项目以掌握窍门,我了解基本流程:编写失败的测试,编写代码以通过测试,如果需要重构,重复。

为了保持测试的快速和解耦,我抽象出网络请求和文件等内容 I/O。这些通常被抽象为使用依赖注入传递的接口。

通常开发很顺利,直到最后我意识到我需要实现这些抽象接口。将它们抽象化的全部目的是使其易于测试,但是在 TDD 之后我需要在编写实现代码之前编写测试,对吗?

例如,我在看 tdd-tetris-tutorial https://github.com/luontola/tdd-tetris-tutorial/tree/tutorial/src/test/java/tetris。如果我想添加使用键盘的功能,我会将基本控件抽象为控制器 class 内的方法,例如 "rotateBlock"、"moveLeft" 等可以测试的方法。

但最后我需要添加一些逻辑来在实现控制器时检测来自键盘的击键 class。如何编写测试来实现它?

也许有些东西就是无法测试,在某些情况下不可能达到 100% 的代码覆盖率?

您无法使用 TDD 单元测试 测试所有内容。但是如果你也有集成测试,你可以测试那些 I/O 接口。您可以使用 TDD 生成集成测试。

在实践中,有些东西自动测试是不切实际的。一些罕见的错误条件或竞争危险的错误处理是最难的。

Perhaps some things just can't be tested, and reaching 100% code coverage is impossible for some cases?

我使用的拼写略有不同:并非所有事物都可以在相同的成本效益水平上进行测试。

可以说,"trick" 是将您的代码分为两类:易于测试的代码,以及明显不需要测试的代码——或者不那么频繁了。

简单适配器的优点在于(一旦您让它们正常工作)它们通常不需要进行太多更改。所有 逻辑 都存在于其他地方,而其他地方 易于测试

例如,考虑从文件中读取字节。这种接口看起来有点像一个函数,它接受一个文件名作为参数,或者 returns 一个字节数组,或者某种异常。 实现,这在大多数语言中都是一个简单的练习,代码在教科书上非常熟悉,很明显属于 "so simple there are obviously no deficiencies" 的类别。

因为代码简单且稳定,您不需要以接近您定期重构代码的测试频率来测试它。因此,成本效益分析支持这样的结论,即您可以将对此代码的偶尔测试委托给更昂贵的技术。

100% 的语句覆盖率从来都不是 TDD 的目标(尽管很容易理解您和其他无数人是如何得出这个结论的)。它主要是关于推迟详细设计。因此,在某种程度上,开始时很简单且很少更改的代码从一开始就是 "out of bounds"。