使用 TDD 修复 Swift 中的错误
使用 TDD 修复 Swift 中的错误
测试驱动开发 (TDD) 是一种技术,要求你在开始实现解决方案之前先编写一个失败的测试。虽然开发人员在一般开发过程中会使用这种技术,但有一种方法可以仅将其应用于错误修复。
发现错误已经令人失望,但发现错误再次发生会更糟。防止错误在你修复后再次出现是一项重要的开发技能。
测试驱动开发 (TDD) 流程要求你在开始实现解决方案之前先编写一个失败的测试。你可以使用它来定义新功能的所有规范,并确保不会忘记任何预期结果。
例如,假设有以下文章结构:
struct Article {
let title: String
let author: String
let link: URL
}
我们可能希望创建一个新的 计算属性 来返回这篇文章的博客域。在开始编写实际计算属性之前,我们首先定义以下测试用例:
func testArticleDomain() {
let article = Article(
title: "Async await in Swift explained with code examples",
author: "Antoine van der Lee",
link: URL(string: "https://www.avanderlee.com/swift/async-await/")!
)
XCTAssertEqual(article.blogDomain, "avanderlee.com")
}
此代码不会编译,因为 blogDomain 属性不存在。由于我们希望测试首先失败,因此我们可以添加一个返回空字符串的计算属性:
extension Article {
var blogDomain: String {
""
}
}
我们现在可以成功运行单元测试并得出结论,它确实失败了:

使用测试驱动开发,我们首先编写了一个失败的测试。
最后,我们实现实际逻辑,并重新运行测试以确保它成功:
extension Article {
var blogDomain: String {
link.host()?.replacingOccurrences(of: "www.", with: "") ?? ""
}
}
工作流程看起来与许多开发人员所做的事情类似,但主要区别在于从编写测试开始,而不是直接进入功能开发。
TDD 的好处
开发人员往往犹豫在工作流程中开始使用测试驱动开发。编写一个失败的测试感觉多余,而且浪费时间。在我开始列出 TDD 的一些好处之前,我认为强调一下这一点很重要:当它适合你的当前任务时,你可以将此技术用作选择加入的工具集。
我在解决错误时偶尔会使用它,因为我想清除我对预期结果的思考。通过编写测试,你可以确保记住所有边缘情况和预期结果。其次,你将使自己能够完全专注于开发解决方案,而无需不断考虑必须支持的结果:你可以运行测试,并且知道当所有测试都成功时就完成了。
首先编写失败测试的另一个好处是确保你的测试实际上会失败。这听起来很愚蠢,但我看到许多测试即使实现发生变化也会始终成功。换句话说,测试不会捕获任何错误的实现。
最后,通过从测试开始,你将确保你的新代码从一开始就可以进行测试。当你编写没有考虑测试的新代码时,事后编写测试可能会更具挑战性。由于它变得更加困难,因此更容易完全跳过编写测试,从而导致测试覆盖率降低。
