Golang中如何使用Rest-assured和Cucumber进行测试
Golang中如何使用Rest-assured和Cucumber进行测试 你好,我正在测试一个 API,并希望采用 BDD(行为驱动开发)风格进行。
我之前使用过 Java、RestAssured 和 Cucumber,但现在我需要在 Go 语言中完成这项工作,最好是用 Go。有人有经验可以为我指明正确的方向吗?
我搜索了一下,发现一个叫 Baloo 的工具,看起来还不错,还有一个叫 Go-Rest-Assured 的。但这些库好用吗?
还有一个叫 GoDog 的工具,它类似于 Cucumber。但我对 Go 语言和这些库都没有经验。
2 回复
我还没有使用过任何BDD测试库,但我听说大多数项目都使用ginkgo和testify。
onsi/ginkgo
Go语言的BDD测试框架。通过创建GitHub账户为onsi/ginkgo的开发做出贡献。
更多关于Golang中如何使用Rest-assured和Cucumber进行测试的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
在Go语言中实现BDD风格的API测试,可以使用以下组合:
1. 测试框架选择
GoDog + GoRestAssured
这是最接近Java中RestAssured+Cucumber的方案:
// go.mod 依赖
require (
github.com/cucumber/godog v0.13.0
github.com/steinfletcher/apitest v1.5.15
// 或使用:github.com/go-resty/resty/v2 v2.7.0
)
// features/api_test.go
package test
import (
"context"
"encoding/json"
"fmt"
"testing"
"github.com/cucumber/godog"
"github.com/go-resty/resty/v2"
)
type apiFeature struct {
client *resty.Client
response *resty.Response
requestBody map[string]interface{}
}
func (a *apiFeature) iSendRequestTo(method, endpoint string) error {
var err error
switch method {
case "GET":
a.response, err = a.client.R().Get(endpoint)
case "POST":
a.response, err = a.client.R().
SetHeader("Content-Type", "application/json").
SetBody(a.requestBody).
Post(endpoint)
case "PUT":
a.response, err = a.client.R().
SetHeader("Content-Type", "application/json").
SetBody(a.requestBody).
Put(endpoint)
}
return err
}
func (a *apiFeature) theResponseCodeShouldBe(code int) error {
if a.response.StatusCode() != code {
return fmt.Errorf("expected status %d, got %d",
code, a.response.StatusCode())
}
return nil
}
func (a *apiFeature) theResponseShouldContainJSON(key, value string) error {
var result map[string]interface{}
if err := json.Unmarshal(a.response.Body(), &result); err != nil {
return err
}
if val, ok := result[key]; !ok || fmt.Sprintf("%v", val) != value {
return fmt.Errorf("key %s not found or value mismatch", key)
}
return nil
}
func (a *apiFeature) iSetRequestBody(data *godog.DocString) error {
return json.Unmarshal([]byte(data.Content), &a.requestBody)
}
func InitializeScenario(ctx *godog.ScenarioContext) {
api := &apiFeature{
client: resty.New(),
requestBody: make(map[string]interface{}),
}
ctx.BeforeScenario(func(*godog.Scenario) {
api.client = resty.New().
SetBaseURL("http://localhost:8080").
SetTimeout(10)
api.requestBody = make(map[string]interface{})
})
ctx.Step(`^I send (GET|POST|PUT) request to "([^"]*)"$`,
api.iSendRequestTo)
ctx.Step(`^the response code should be (\d+)$`,
api.theResponseCodeShouldBe)
ctx.Step(`^the response should contain JSON "([^"]*)" with value "([^"]*)"$`,
api.theResponseShouldContainJSON)
ctx.Step(`^I set request body:$`, api.iSetRequestBody)
}
func TestFeatures(t *testing.T) {
suite := godog.TestSuite{
ScenarioInitializer: InitializeScenario,
Options: &godog.Options{
Format: "pretty",
Paths: []string{"features"},
TestingT: t,
},
}
if suite.Run() != 0 {
t.Fatal("non-zero status returned, failed to run feature tests")
}
}
2. 特征文件示例
# features/user_api.feature
Feature: User API Testing
Scenario: Get user by ID
Given I send GET request to "/api/users/1"
Then the response code should be 200
And the response should contain JSON "id" with value "1"
And the response should contain JSON "name" with value "John Doe"
Scenario: Create new user
Given I set request body:
"""
{
"name": "Jane Smith",
"email": "jane@example.com"
}
"""
When I send POST request to "/api/users"
Then the response code should be 201
And the response should contain JSON "status" with value "created"
3. 替代方案:Ginkgo + Gomega
如果你更喜欢xUnit风格的BDD:
// go.mod
require (
github.com/onsi/ginkgo/v2 v2.11.0
github.com/onsi/gomega v1.27.10
)
// api_test.go
package api_test
import (
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/go-resty/resty/v2"
"encoding/json"
)
var _ = Describe("User API", func() {
var client *resty.Client
var response *resty.Response
BeforeEach(func() {
client = resty.New().
SetBaseURL("http://localhost:8080")
})
Describe("GET /api/users/{id}", func() {
Context("when user exists", func() {
BeforeEach(func() {
var err error
response, err = client.R().Get("/api/users/1")
Expect(err).NotTo(HaveOccurred())
})
It("should return status 200", func() {
Expect(response.StatusCode()).To(Equal(200))
})
It("should return user data", func() {
var result map[string]interface{}
err := json.Unmarshal(response.Body(), &result)
Expect(err).NotTo(HaveOccurred())
Expect(result["id"]).To(Equal(float64(1)))
})
})
})
})
4. 运行测试
# 安装依赖
go mod init your-project
go get github.com/cucumber/godog
go get github.com/go-resty/resty/v2
# 运行GoDog测试
go test -v ./...
# 或使用标签运行特定测试
go test -v -tags=godog ./...
5. 关于你提到的工具
- GoDog: 是Go语言中最成熟的Cucumber实现,完全支持Gherkin语法
- Go-Resty: 比Baloo更活跃的HTTP客户端,类似RestAssured
- Baloo: 虽然可用,但维护不如Go-Resty活跃
- apitest: 另一个不错的API测试库,更轻量级
推荐使用GoDog + Go-Resty组合,这是目前Go生态中最接近Java RestAssured+Cucumber体验的方案。

