godog是Cucumber官方的Golang BDD(Behaviour-Driven Development)框架,它將規範和測試文件二合一,使用 Gherkin 格式的場景,格式為 Given, When, Then。
這裡我就不再介紹BDD囉~
建立一個資料夾 - mkdir godogs
進入資料夾內 - cd godogs
go mod init godog - go mod init godogs
安裝godog執行檔 - go get github.com/cucumber/godog/cmd/godog
建立一個features資料夾 - mkdir features
建立godogs.feature 裡面描述要測試的行爲特徵 - vi features/godogs.feature
以下是我的範例
Feature: write ithome30days
As a happy contestant
Scenario: Write 5 out of 30
Given there are 30 days
When I write 5
Then there should be 25 remaining
執行godog
執行godog run
Feature: write ithome30days
As a happy contestant
Scenario: Write 5 out of 30 # features/godogs.feature:4
Given there are 30 days
When I write 5
Then there should be 25 remaining # godogs_test.go:14 -> thereShouldBeRemaining
1 scenarios (1 undefined)
3 steps (2 undefined, 1 skipped)
455.835µs
You can implement step definitions for undefined steps with these snippets:
func iWrite(arg1 int) error {
return godog.ErrPending
}
func thereAreDays(arg1 int) error {
return godog.ErrPending
}
func thereShouldBeRemaining(arg1 int) error {
return godog.ErrPending
}
func InitializeScenario(ctx *godog.ScenarioContext) {
ctx.Step(`^I write (\d+)$`, iWrite)
ctx.Step(`^there are (\d+) days$`, thereAreDays)
ctx.Step(`^there should be (\d+) remaining$`, thereShouldBeRemaining)
}
然後建個測試檔案,再把剛剛那些未定義的func複製到新的檔案中 - vi godogs_test.go
package main
import "github.com/cucumber/godog"
func iWrite(arg1 int) error {
return godog.ErrPending
}
func thereAreDays(arg1 int) error {
return godog.ErrPending
}
func thereShouldBeRemaining(arg1 int) error {
return godog.ErrPending
}
func InitializeScenario(ctx *godog.ScenarioContext) {
ctx.Step(`^I write (\d+)$`, iWrite)
ctx.Step(`^there are (\d+) days$`, thereAreDays)
ctx.Step(`^there should be (\d+) remaining$`, thereShouldBeRemaining)
}
目前我們的目錄結構長這樣
godogs
- features
- godogs.feature
- go.mod
- go.sum
- godogs_test.go
再執行一次godog - godog
您可以看到該場景處於待pending狀態,其中一個步驟處於pending狀態並且有兩個跳過了步驟:
Feature: write ithome30days
As a happy contestant
Scenario: Write 5 out of 30 # features/godogs.feature:4
Given there are 30 days # godogs_test.go:10 -> thereAreDays
TODO: write pending definition
When I write 5 # godogs_test.go:6 -> iWrite
Then there should be 25 remaining # godogs_test.go:14 -> thereShouldBeRemaining
1 scenarios (1 pending)
3 steps (1 pending, 2 skipped)
259.906µs
你可以直接把 return godog.ErrPending 改為 return nil 讓場景測試成功通過
建立一個godogs.go檔案並將當作main - vi godogs.go
package main
// Godogs available to eat
var Godogs int
func main() { /* usual main func */ }
目前我們的目錄結構長這樣
godogs
- features
- godogs.feature
- go.mod
- go.sum
- godogs.go
- godogs_test.go
讓我們實現步驟的定義,來測試我們的功能需求:
調整一下 godogs_test.go
內容。
package main
import (
"context"
"fmt"
"github.com/cucumber/godog"
)
func thereAreGodogs(available int) error {
Godogs = available
return nil
}
func iEat(num int) error {
if Godogs < num {
return fmt.Errorf("you cannot eat %d godogs, there are %d available", num, Godogs)
}
Godogs -= num
return nil
}
func thereShouldBeRemaining(remaining int) error {
if Godogs != remaining {
return fmt.Errorf("expected %d godogs to be remaining, but there is %d", remaining, Godogs)
}
return nil
}
func InitializeTestSuite(sc *godog.TestSuiteContext) {
sc.BeforeSuite(func() { Godogs = 0 })
}
func InitializeScenario(sc *godog.ScenarioContext) {
sc.Before(func(ctx context.Context, sc *godog.Scenario) (context.Context, error) {
Godogs = 0 // clean the state before every scenario
return ctx, nil
})
sc.Step(`^there are (\d+) godogs$`, thereAreGodogs)
sc.Step(`^I eat (\d+)$`, iEat)
sc.Step(`^there should be (\d+) remaining$`, thereShouldBeRemaining)
}
讓我們再次執行 godog
Feature: write ithome30days
As a happy contestant
Scenario: Write 5 out of 30 # features/godogs.feature:4
Given there are 30 days # godogs_test.go:21 -> thereAreDays
When I write 5 # godogs_test.go:10 -> iWrite
Then there should be 25 remaining # godogs_test.go:25 -> thereShouldBeRemaining
1 scenarios (1 passed)
3 steps (3 passed)
326.79µs
以上基本就完成一個godog BDD的簡易流程囉。