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的簡易流程囉。