The TDD That Works for Me

The following text is a partial translation of the original English article, performed by ChatGPT (gpt-3.5-turbo) and this Jekyll plugin:

【测试驱动开发】(即TDD)是由肯特·贝克(Kent Beck)重新发现并在2002年的他的著名书籍中解释。2014年,Ruby on Rails的创造者大卫·海尼梅尔·汉松(David Heinemeier Hansson)表示TDD已经死亡,并且只会损害架构。SOLID原则的发明者罗伯特·马丁(Robert Martin)不同意,并解释TDD可能只在某些情况下不起作用。几天后,他甚至将TDD的重要性与医学手卫生的重要性进行了比较,并补充说“如果有一天,TDD成为法律的力量,我不会感到惊讶。”两年后,就在几个月前,他写了更多关于这个话题的文章,还有更多,和更多。这个话题似乎很热门。当然,我对此有自己的看法,让我来分享。

从理论上讲,TDD意味着“先写测试,再写代码”。根据我的经验,在过去四年中与250多名开发人员合作的过程中,实际上意味着我们在心情好且没有其他事情要做的时候才编写测试。这是合乎逻辑的,如果我们按照字面理解TDD,就像书上所描述的那样。

在没有面前的类的情况下编写测试是困难的。我甚至会说,如果我们讨论的是真实的代码而不是计算器示例,那么这是不可能的。这也非常低效,因为测试与其验证的代码相比,定义上更加严格——先创建测试会导致许多重新循环,直到设计稳定下来。

在过去四年中,我个人在Java、Ruby、PHP和JavaScript方面已经编写了近30万行代码,而我从未按照书上所描述的那样进行TDD:“先写一个测试,使其运行,然后使其正确”。

即使我是自动化测试(单元测试或集成测试)的铁杆粉丝,并且完全赞同 Uncle Bob 的观点:那些不写测试的人应该被关进监狱,但我对 TDD 有自己的理解。我的理解如下:

  • 然后,我将其部署到生产环境。是的,它将没有任何测试就被发送给我的“用户”,因为对我而言它是有效的。如果是一个开源项目或我的宠物项目,它们要么是真实的用户,要么是手动测试人员,如果是一个盈利项目。

  • 然后,他们打破它。他们无论是测试还是使用它,都不重要。他们只是发现问题并报告错误。尽可能多地报告。

  • 在一些错误报告之后,我会选择其中最关键的错误…然后!我会创建一个自动化的测试。这个错误对我来说是一个信息,告诉我我的测试不够强大;我首先必须修复它们。一个新的测试将证明代码是有问题的。或者也许我会修复现有的测试。这就是我所谓的“先写测试”。在我成功地破坏了构建并通过新的测试证明问题的存在之前,我不会碰生产代码。然后,我会进行git commit

  • 最后,是时候来解决这个问题了。我对生产代码进行更改,以确保构建再次变为正常状态。然后,我执行git commitgit push操作。接着,我回到“部署”步骤;更新后的产品将发送给我的用户们。

偶尔,我不得不对产品进行重大修改,比如引入新功能或进行大规模重构。在这种情况下,我回到第一步,不进行测试就进行修改。

这种不提前测试的做法背后的理由很简单:我们不需要在出现问题之前进行测试,主要是因为我们理解无法测试所有内容或修复所有错误从技术上讲是不可能的。我们只需要修复业务中可见且无法容忍的问题。如果业务不关心或我们的用户/测试人员看不到我们的错误,我们就不能浪费项目资源来修复它们。

另一方面,当业务或我们的用户/测试人员抱怨时,我们必须对自己非常严格;我们的测试系统薄弱,必须首先修复它。我们不能只修复生产代码并部署,因为在这种情况下,经过一些重构后我们可能会再次犯同样的错误,而我们的测试无法捕捉到。用户会再次发现错误,业务将再次付费来修复它。这将是资源的浪费。

正如你所看到的,这一切都是由金钱驱动的。首先,如果没有人为此付费,就不要修复任何问题。其次,如果他们实际付费了,就一次性解决问题。就是这么简单。

由于采用了“只有在出现问题时才进行测试和修复”的方法,因此在整个项目生命周期中,生产代码和测试代码之间的平衡是不同的。项目开始时几乎没有测试。然后,测试的数量随着错误的数量而增加。最后,情况稳定下来,我们可以将产品从测试版转移到第一个发布版本。

为了证明我的观点,我创建了一个简单的命令行工具,用来展示我几个项目的统计数据。请看一下这些图表:

yegor256/takes(Web框架,Java):

yegor256/xembly(XML构建器,Java):

jcabi/jcabi-aspects(AOP库,Java):

yegor256/s3auth(S3网关,Java):

第一个商业项目:

第二个商业项目:

在每个图表中,有两个部分。顶部部分显示了生产代码行数(绿线)、与测试相关的代码行数(红线)和报告给GitHub的问题数量(橙线)的动态。

底部部分显示了与所有项目活动相比,与测试相关的代码行数占比有多大。换句话说,它显示了项目为自动化测试投入了多少工作量,与总工作量相比。

这是我想让你注意的:在每个项目中,曲线的形状几乎是相同的。它看起来非常类似于学习曲线,我们开始快速学习,然后随着时间的推移而放慢:

这完美地说明了我刚才描述的情况。我在项目开始时不需要测试;只有当用户通过报告错误来表达对测试的需求时,我才会创建它们。对我来说,这种动态看起来只是合乎逻辑的。

你也可以使用我的工具分析你的项目并查看图表。了解你将获得何种曲线将会很有趣。

Translated by ChatGPT gpt-3.5-turbo/42 on 2023-11-17 at 17:00

sixnines availability badge   GitHub stars