golang YATSPEC风格BDD测试框架插件gogiven的使用

golang YATSPEC风格BDD测试框架插件gogiven的使用

gogiven是一个基于"go test"工具和go testing包的替代BDD规范框架。

介绍

Go Givens是一个轻量级的BDD框架,用于直接从您编写的代码生成测试规范。它会解析您的测试文件并生成人类可读的输出,包含所有测试、捕获的数据以及与测试相关的其他信息,如成功或失败。

Go Givens受到YATSPEC的启发,YATSPEC是英国电视公司Sky的网络服务部门广泛使用的BDD框架。

为什么使用它?

在BDD中,系统的输入和输出对业务很重要。捕获数据与系统处理方式之间的关系可以向客户展示。例如,您的系统可能调用第三方服务,您可能希望用存根来建模交互。

示例代码

import (
	"github.com/corbym/gocrest/has"
	"github.com/corbym/gocrest/then"
	"github.com/corbym/gogiven/base"
	"github.com/corbym/gogiven/testdata"
	"testing"
	"github.com/corbym/gocrest/is"
)

func TestMain(testmain *testing.M) {
	runOutput := testmain.Run()
	GenerateTestOutput() // 如果您想生成HTML输出,只需要在test main中调用GenerateTestOutput()
	os.Exit(runOutput)
}

func TestMyFirst(testing *testing.T) {
	Given(testing, someDataSetup).

		When(somethingHappens).

		Then(func(testing base.TestingT, actual testdata.CapturedIO, givens testdata.InterestingGivens) { // 传入的testing应该用于断言
		// 执行断言
		then.AssertThat(testing, actual["actual"], is.EqualTo("some output"))
	})
}

注意您不必使用"gocrest"断言,您仍然可以调用testing.T的所有函数来使测试失败,或者您可以使用任何与testing.T兼容的go测试断言包。

表格测试示例

表格测试的工作方式与普通的go表格测试相同。GoGivens会在您的测试输出中标记哪些测试失败了。

func TestMyFirst(testing *testing.T){
   var someRange = []struct {
		actual   string
		expected int
	}{
		{actual: "", expected: 0},
		{actual: "a", expected: 2},
	}
	for _, test := range someRange {
	   tst.Run(test.actual, func(weAreTesting *testing.T) {
	   	Given(weAreTesting, someDataSetup).
			When(someAction).
			Then(func(t TestingT, actual CapturedIO, givens InterestingGivens) {
			// 执行断言
		AssertThat(t, actual.CapturedIO["actual"], is.EqualTo("some output"))
	   	})
	   }	
	}
}

内容生成

Gogivens默认配置了一个HTML生成器(htmlspec.NewTestOutputGenerator),由文件生成器(generator.FileOutputGenerator)使用。内容生成器实现以下接口:

type GoGivensOutputGenerator interface {
	Generate(data *PageData) (output io.Reader)
	//ContentType是text/html、application/json或其他mime类型
	ContentType() string
}

生成的内容(output io.Reader)然后由OutputListener使用:

type OutputListener interface {
	Notify(testFilePath string, contentType string, output io.Reader)
}

如果您想要自己的输出监听器,只需创建自己的监听器,并在TestMain中替换和/或附加到默认监听器:

func TestMain(testmain *testing.M) {
	gogiven.OutputListeners = []generator.OutputListener{new(MyFooListener)}
	// 或者也可以(或者同时!)
	gogiven.OutputListeners = append(OutputListeners, new(MyBarListener))
	runOutput := testmain.Run()
	gogiven.GenerateTestOutput() // 在测试完成后生成输出
	os.Exit(runOutput)
}

设置测试文件输出(对于generator.FileOutputGenerator)

您可以添加环境变量GOGIVENS_OUTPUT_DIR到您的环境属性中,指向您希望goGivens报告测试输出的目录。

默认是操作系统的tmp目录。

预编写的输出生成器列表

GoGiven附带以下输出生成器:

  • HTML Spec: 生成测试示例中使用的输出
  • JSON Spec: 以JSON格式生成输出

更多关于golang YATSPEC风格BDD测试框架插件gogiven的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang YATSPEC风格BDD测试框架插件gogiven的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


使用gogiven实现YATSPEC风格的BDD测试

gogiven是一个Go语言的BDD测试框架,它采用了类似YATSPEC的Given-When-Then风格来编写测试用例。下面我将介绍如何使用gogiven框架编写行为驱动开发(BDD)风格的测试。

安装gogiven

首先安装gogiven包:

go get github.com/corbym/gogiven

基本用法示例

下面是一个简单的gogiven测试示例:

package example

import (
	"testing"
	"github.com/corbym/gogiven"
	. "github.com/corbym/gogiven/base"
)

func TestAddition(t *testing.T) {
	gogiven.Given(t, someTestContextSetup).
		When(func(testContext TestContext, when When) {
			// 执行操作
			result := add(2, 3)
			when.Result = result
		}).
		Then(func(testContext TestContext, then Then) {
			// 验证结果
			then.Expect("result should be 5").
				ThatInt(testContext.Result().(int)).
				IsEqualTo(5)
		})
}

func someTestContextSetup(testContext TestContext) {
	// 测试前的初始化设置
	testContext.Title("Addition Test")
}

func add(a, b int) int {
	return a + b
}

关键组件说明

  1. Given: 设置测试的初始状态和上下文
  2. When: 执行被测操作
  3. Then: 验证结果是否符合预期

更复杂的示例

下面是一个更完整的示例,展示更多gogiven的功能:

package shoppingcart

import (
	"testing"
	"github.com/corbym/gogiven"
	. "github.com/corbym/gogiven/base"
)

type ShoppingCart struct {
	items map[string]int
	total int
}

func TestShoppingCart(t *testing.T) {
	gogiven.Given(t, func(testContext TestContext) {
		testContext.Title("Shopping Cart Test")
		testContext.Given("an empty shopping cart", func(given Given) {
			cart := &ShoppingCart{
				items: make(map[string]int),
				total: 0,
			}
			given.Value("cart", cart)
		})
	}).
	When(func(testContext TestContext, when When) {
		cart := testContext.Value("cart").(*ShoppingCart)
		cart.items["apple"] = 2
		cart.items["banana"] = 3
		cart.total = 5
	}).
	Then(func(testContext TestContext, then Then) {
		cart := testContext.Value("cart").(*ShoppingCart)
		
		then.Expect("cart should have 2 apples").
			ThatInt(cart.items["apple"]).
			IsEqualTo(2)
			
		then.Expect("cart should have 3 bananas").
			ThatInt(cart.items["banana"]).
			IsEqualTo(3)
			
		then.Expect("total items should be 5").
			ThatInt(cart.total).
			IsEqualTo(5)
	})
}

高级特性

  1. 表格驱动测试:
func TestTableDrivenAddition(t *testing.T) {
	testCases := []struct {
		a, b, expected int
	}{
		{1, 1, 2},
		{2, 3, 5},
		{0, 0, 0},
		{-1, 1, 0},
	}

	for _, tc := range testCases {
		gogiven.Given(t, func(testContext TestContext) {
			testContext.Title("Addition of %d and %d", tc.a, tc.b)
		}).
		When(func(testContext TestContext, when When) {
			when.Result = add(tc.a, tc.b)
		}).
		Then(func(testContext TestContext, then Then) {
			then.Expect("result should be %d", tc.expected).
				ThatInt(testContext.Result().(int)).
				IsEqualTo(tc.expected)
		})
	}
}
  1. 异步测试:
func TestAsyncOperation(t *testing.T) {
	gogiven.Given(t, nil).
		When(func(testContext TestContext, when When) {
			done := make(chan bool)
			
			go func() {
				// 模拟异步操作
				time.Sleep(100 * time.Millisecond)
				when.Result = 42
				done <- true
			}()
			
			<-done
		}).
		Then(func(testContext TestContext, then Then) {
			then.Expect("async result should be 42").
				ThatInt(testContext.Result().(int)).
				IsEqualTo(42)
		})
}

生成HTML报告

gogiven可以生成漂亮的HTML测试报告:

func TestMain(m *testing.M) {
	// 配置HTML报告生成
	gogiven.GenerateTestOutput()
	os.Exit(m.Run())
}

运行测试后,会在目录下生成testoutput文件夹,包含HTML格式的测试报告。

最佳实践

  1. 保持Given-When-Then各部分职责单一
  2. 使用有意义的测试标题和期望描述
  3. 对于复杂场景,可以拆分多个Given块
  4. 利用表格驱动测试覆盖多种情况
  5. 合理使用HTML报告分析测试结果

gogiven框架通过其YATSPEC风格的语法,使得Go语言测试代码更加易读和易于维护,特别适合团队协作和复杂业务逻辑的测试。

回到顶部