首页 >后端开发 >Golang >Go 中的测试驱动 API 开发

Go 中的测试驱动 API 开发

王林
王林原创
2024-07-18 01:18:11545浏览

Test-driven API Development in Go

介绍

测试驱动开发是确保代码经过良好测试和可重构的有效方法。基本思想是通过编写测试开始开发。这些测试清楚地记录了期望并为成功实施创建了标准。如果做得正确,您可以在编写任何代码之前清楚地定义函数的预期输入/输出。这有一些直接的好处:

  • 您仔细考虑与代码交互的界面并将其设计为可测试的
  • 当您开始编写代码时,您的流程不会因手动测试或单步执行执行逻辑来预测结果而中断。相反,您只需运行测试
  • 通过测试成为一个令人满足的目标。将流程分解为一系列明确且可实现的里程碑,使工作变得更加愉快
  • 避免实施后的懒惰和过度自信,这可能会阻止您测试代码

现在您已经确信这些好处,您可以按照以下步骤开始测试驱动开发 (TDD):

  1. 编写或修改测试
  2. 检查测试是否失败
  3. 编写最少数量的代码以使测试通过

这些步骤是循环执行的,因此您总是添加更多测试来挑战当前的实现。

最后一步,指定编写最少量的代码,如果严格遵循,事情可能会变得乏味。在确定何时适合偏离该规则之前,了解该规则存在的原因非常重要。

简单的例子

您的任务是实现函数 Add(x, y int) int。在跳转到实现并返回 x + y 之前,编写最简单的测试:1 + 1 == 2。那么,通过测试的最简单实现是什么?只需返回 2。现在您的测试通过了!

此时,您意识到需要更多测试,因此您加快了步伐并添加了更多测试:

  • 1 + 2 == 3
  • 100 + 5 == 105

现在你的测试失败了,所以你需要修复实现。这次你不能只返回 3 或返回 105,所以你需要找到一个适用于所有测试的解决方案。这导致了实现:return x + y.

虽然在这个简单的示例中感觉过于乏味,但严格遵守此方法会导致您编写多个测试而不是仅仅信任您的实现。当然,您最初返回 x + y 的想法是可行的,但重点是重新训练自己依赖测试而不是您自己对代码的理解。在现实世界中,您并不是唯一一个处理这段代码的人,并且不可避免地会忘记实现细节。这个过程迫使你编写更多的测试并思考更多的方法来打破简单的实现。

最终,您将获得经验并学会找到适合您遇到的不同场景的平衡点。您将恢复全速实现功能,并发现错误更少并编写更多可维护的代码。

HTTP API 的逐步 TDD

让我们进入一个使用 TDD 实现 HTTP REST API 的更复杂的示例。本分步指南使用我的 Go 框架babyapi,但这些概念可以应用于任何地方。

babyapi 使用泛型围绕 Go 结构创建完整的 CRUD API,从而使创建完整的 REST API 和客户端 CLI 变得非常容易。除此之外,babytest 包还提供了一些用于创建端到端 API 表测试的工具。在 API 级别使用 TDD 可以一次性全面测试新 API 或功能的 HTTP 和存储层。

免责声明:由于babyapi 处理大部分实现,并且还用于生成测试样板,因此从技术上讲,我们并不是从 TDD 开始。但是,当我们向 API 添加对 PATCH 请求的支持时,我们将看到它有多么有益。

  1. 创建一个新的 Go 项目


  2. 使用babyapi的简单示例创建初始main.go


  3. 使用 CLI 生成测试样板

  4. 通过使用预期的 JSON 填充占位符来实现每个测试
  5. 运行测试并查看它们是否通过!

    由于 PUT 是幂等的,因此需要包含所有字段。为了避免这种情况,我们希望添加对使用 PATCH 请求切换 Completed 的支持。我们首先添加一个简单的测试来了解我们期望此功能的外观
  6. This test fails since babyapi doesn't support PATCH by default. We can fix it by implementing Patch for the TODO struct. Since we defined our feature with two tests, our simplest implementation isn't just setting Completed = true and we have to use the value from the request

  7. Now we can change the Completed status of a TODO, but we still cannot use PATCH to modify other fields as show by this new set of tests

  8. Update Patch to set the remaining fields

  9. Our tests still fail since we always update the TODO with the request fields, even if they're empty. Fix this by updating the implementation to check for empty values

  10. The new UpdateWithPatch test passes, but our previous tests fail. Since we changed Completed to be *bool, TODOs created with an empty value will show as null

  11. Implement Render for TODO so we can treat nil as false

Implementing the PATCH feature with test-driven development resulted in a robust set of tests and a well-implemented feature. Since we started by defining the expected input and output of a PATCH request in tests, it was easy to see the issues caused by not checking for empty values in the request. Also, our pre-existing tests were able to protect from breaking changes when changing the type of Completed to *bool.

Conclusion

Test-driven development is an effective approach for creating fully tested and correct code. By starting with tests in mind, we can ensure that every piece of code is designed to be testable instead of letting tests be an afterthought.

If you're hesitant about adopting TDD, here are a few ideas to get started:

  • Try it in simple scenarios where a function's input/output is clear and the implementation is not overly complicated. You can write a robust table test for the variety of input/output that could be encountered. Having a clear visual of the different scenarios can simplify implementation
  • If you're fixing a new bug, you have already identified a gap in your testing. Start by writing a test that would have identified this bug in the first place. Then, make this test pass without breaking any existing tests.
  • Similar to the babyapi example, you can use TDD for high-level API tests. Once you have a definition of the expected request/response, you can resume your usual development flow for more detail-oriented parts of the implementation

Even if TDD isn't a good fit for the way you write code, it's still a powerful tool to have in your belt. I encourage you to at least commit some time to trying it out and see how it affects your development process.

以上是Go 中的测试驱动 API 开发的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn