BDD 在 Go 中:如何编写业务可理解的测试

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

当代码成为故事

\n

想象一下:你用Go编写代码,运行测试——绿色通过。但产品经理看着你的t.Errorf,不明白具体哪里出了问题。业务方说:"让用户能注册",开发者将其翻译成"POST /api/v1/user 带邮箱验证"。技术语言与人类语言之间的鸿沟,是许多项目的主要痛点。

\n

有一个解决方案——BDD(行为驱动开发)在Go中的应用。这不仅仅是测试。它是连接代码与业务逻辑的桥梁。本文将通过实际示例,详细讲解如何在Go中编写BDD测试,以及为什么你的产品经理会感谢你。

\n\n

什么是BDD?为什么选择Go?

\n

行为驱动开发是TDD的演进版本。如果说TDD关注的是"如何"(如何实现某个函数),那么BDD回答的是"什么"(从用户角度看系统应该做什么)。

\n

Go因其简洁性、内置的testing包以及Ginkgo和Godog等强大框架,非常适合BDD。Go社区在微服务、API甚至CLI工具中广泛使用BDD。

\n\n

Go中BDD的关键原则

\n
    \n
  • 通用语言——场景用业务方能理解的英文或中文编写。
  • \n
  • Given-When-Then——任何场景的结构:前置条件→操作→预期结果。
  • \n
  • 自动化——场景被转化为可执行的Go测试。
  • \n
\n\n

Go中BDD的工具

\n

框架的选择取决于你希望如何描述场景。以下是两种主要方法:

\n\n

1. Ginkgo + Gomega(适用于Go开发者)

\n

Ginkgo是一个纯Go编写的BDD框架。场景看起来像是带有可读描述的Go代码。Gomega是一个用于断言的匹配器库。

\n

优点:完全控制代码,与Go工具链完美集成,支持异步测试。

\n\n

2. Godog(Go的Cucumber实现)

\n

Godog是Go的Cucumber实现。你用Gherkin语言(用自然语言编写的Feature文件)编写场景,然后在Go中实现步骤。

\n

优点:非程序员也能读懂场景,无需编辑代码即可轻松修改逻辑。

\n\n

实践:使用Ginkgo编写Go BDD测试

\n

让我们创建一个简单的服务——在线商店购物车。我们将编写一个检查添加商品的BDD测试。

\n\n

第一步:安装Ginkgo

\n
go get github.com/onsi/ginkgo/v2\ngo get github.com/onsi/gomega
\n\n

第二步:初始化测试包

\n
cd mycart\nginkgo bootstrap
\n

创建了文件mycart_suite_test.go。

\n\n

第三步:编写场景

\n

创建文件cart_test.go:

\n
package mycart_test\n\nimport (\n    . "github.com/onsi/ginkgo/v2"\n    . "github.com/onsi/gomega"\n    "mycart"\n)\n\nvar _ = Describe("Cart", func() {\n    var cart *mycart.Cart\n\n    BeforeEach(func() {\n        cart = mycart.NewCart()\n    })\n\n    Describe("Adding an item", func() {\n        Context("with a correct ID and price", func() {\n            It("should increase the number of items by 1", func() {\n                cart.AddItem("sku-123", 100.0)\n                Expect(cart.TotalItems()).To(Equal(1))\n            })\n\n            It("should correctly calculate the total sum", func() {\n                cart.AddItem("sku-123", 100.0)\n                cart.AddItem("sku-456", 250.0)\n                Expect(cart.TotalPrice()).To(BeNumerically("~", 350.0, 0.01))\n            })\n        })\n\n        Context("with an item that already exists", func() {\n            It("should increase the quantity, not add a new item", func() {\n                cart.                

博客

书籍推荐