golang测试断言库go-testpredicate提供丰富的诊断输出功能

Golang测试断言库go-testpredicate提供丰富的诊断输出功能

go-testpredicate是一个测试断言风格的库,提供了丰富的诊断输出功能,可以与Go内置的testing包配合使用,减少调试失败测试的需求。

主要特性

  • 提供基本测试:nil、true、false
  • 支持任意类型值的相等性比较
  • 支持数值、字符串和序列的有序比较
  • 支持字符串的正则表达式匹配
  • 支持字符串和序列的子序列匹配
  • 支持无序集合的条件判断
  • 支持代码片段执行的panic条件判断

安装

go get github.com/maargenton/go-testpredicate

使用示例

package example_test

import (
    "testing"

    "github.com/maargenton/go-testpredicate/pkg/bdd"
    "github.com/maargenton/go-testpredicate/pkg/require"
    "github.com/maargenton/go-testpredicate/pkg/verify"
)

func TestExample(t *testing.T) {
    bdd.Given(t, "something", func(t *bdd.T) {
        require.That(t, 123).ToString().Length().Eq(3)

        t.When("doing something", func(t *bdd.T) {
            t.Then("something happens ", func(t *bdd.T) {
                verify.That(t, "123").Eq(123)
                verify.That(t, 123).ToString().Length().Eq(4)
            })
        })
    })
}

诊断输出示例

当测试失败时,会输出详细的诊断信息:

--- FAIL: TestExample (0.00s)
    --- FAIL: TestExample/Given_something (0.00s)
        --- FAIL: TestExample/Given_something/when_doing_something (0.00s)
            --- FAIL: TestExample/Given_something/when_doing_something/then_something_happens_ (0.00s)
                example_test.go:17:
                    expected: value == 123
                    error:    values of type 'string' and 'int' are never equal
                    value:    "123"
                example_test.go:18:
                    expected: length(value.String()) == 4
                    value:    123
                    string:   "123"
                    length:   3

断言API示例

func TestCompareAPI(t *testing.T) {
    verify.That(t, true).IsTrue()
    verify.That(t, false).IsFalse()
    verify.That(t, nil).IsNil()
    verify.That(t, &struct{}{}).IsNotNil()
    verify.That(t, 123).IsEqualTo(123)
    verify.That(t, 123).IsNotEqualTo(124)

    verify.That(t, 123).Eq(123)
    verify.That(t, 123).Ne(124)
}

func TestErrorAPI(t *testing.T) {
    var sentinel = fmt.Errorf("sentinel")
    var err = fmt.Errorf("error: %w", sentinel)
    var re = regexp.MustCompile("^error: sentinel$")

    verify.That(t, nil).IsError(nil)        // No error
    verify.That(t, err).IsError("")         // Any error
    verify.That(t, err).IsError(sentinel)   // Specific error or nested error
    verify.That(t, err).IsError("sentinel") // Message contains string
    verify.That(t, err).IsError(re)         // Message matches regexp
}

func TestStringAPI(t *testing.T) {
    verify.That(t, "123").Matches(`\d+`)
    verify.That(t, 123).ToString().Eq("123")
    verify.That(t, "aBc").ToLower().Eq("abc")
    verify.That(t, "aBc").ToUpper().Eq("ABC")
}

BDD风格测试

func TestBDDStyle(t *testing.T) {
    bdd.Given(t, "something", func(t *bdd.T) {
        t.When("doing something", func(t *bdd.T) {
            t.With("something", func(t *bdd.T) {
                t.Then("something happens", func(t *bdd.T) {
                    // 测试代码
                })
                t.Then("something else happens", func(t *bdd.T) {
                    // 测试代码
                })
            })
        })
    })
}

go-testpredicate提供了丰富的断言功能和详细的诊断输出,可以帮助开发者更高效地编写和维护测试代码。


更多关于golang测试断言库go-testpredicate提供丰富的诊断输出功能的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang测试断言库go-testpredicate提供丰富的诊断输出功能的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Go-TestPredicate 测试断言库详解

go-testpredicate 是一个功能强大的 Go 测试断言库,它提供了丰富的断言功能和详细的诊断输出,可以帮助开发者更轻松地编写和维护测试代码。

主要特性

  1. 丰富的断言方法:提供多种断言方式,包括相等、不相等、包含、匹配等
  2. 详细的诊断输出:当断言失败时,会提供详细的错误信息,帮助快速定位问题
  3. 链式调用:支持链式调用,使测试代码更易读
  4. 自定义错误消息:可以添加自定义错误消息

安装

go get github.com/maargenton/go-testpredicate

基本用法示例

package main

import (
	"testing"
	"github.com/maargenton/go-testpredicate/pkg/verify"
)

func TestExample(t *testing.T) {
	// 基本相等断言
	verify.That(t, 42).Eq(42)

	// 不相等断言
	verify.That(t, "hello").Not().Eq("world")

	// 包含断言
	verify.That(t, []int{1, 2, 3}).Contains(2)

	// 正则匹配
	verify.That(t, "hello world").Matches("^hello")

	// 类型断言
	verify.That(t, 3.14).IsType(float64(0))

	// 自定义错误消息
	verify.That(t, 10).
		WithMessage("value should be greater than 20").
		Gt(20)
}

高级功能示例

1. 复杂数据结构比较

type Person struct {
	Name string
	Age  int
}

func TestComplexStruct(t *testing.T) {
	expected := Person{Name: "Alice", Age: 30}
	actual := Person{Name: "Alice", Age: 31}

	// 比较结构体,忽略Age字段
	verify.That(t, actual).
		WithOptions(verify.IgnoreFields("Age")).
		Eq(expected)
}

2. 错误诊断输出

当断言失败时,go-testpredicate 会提供详细的诊断信息:

func TestDiagnosticOutput(t *testing.T) {
	expected := map[string]int{"a": 1, "b": 2}
	actual := map[string]int{"a": 1, "b": 3}

	verify.That(t, actual).Eq(expected)
}

失败时会输出类似这样的信息:

--- FAIL: TestDiagnosticOutput (0.00s)
    predicate_test.go:XX: 
        Expected: map[string]int{"a":1, "b":2}
        Actual:   map[string]int{"a":1, "b":3}
        Diff:
        --- Expected
        +++ Actual
        @@ -2,3 +2,3 @@
           "a": 1,
        -  "b": 2,
        +  "b": 3,

3. 集合操作

func TestCollectionOperations(t *testing.T) {
	numbers := []int{1, 2, 3, 4, 5}

	// 检查所有元素都满足条件
	verify.That(t, numbers).All(func(v int) bool { return v > 0 })

	// 检查至少一个元素满足条件
	verify.That(t, numbers).Any(func(v int) bool { return v > 4 })

	// 检查没有元素满足条件
	verify.That(t, numbers).None(func(v int) bool { return v < 0 })
}

4. 异步测试

func TestEventually(t *testing.T) {
	var counter int

	// 模拟异步操作
	go func() {
		time.Sleep(100 * time.Millisecond)
		counter = 10
	}()

	// 最终counter会变成10
	verify.That(t, &counter).
		WithTimeout(1 * time.Second).
		Eventually().Eq(10)
}

最佳实践

  1. 使用描述性断言:选择最能表达意图的断言方法
  2. 利用诊断输出:当测试失败时,详细输出可以帮助快速定位问题
  3. 组合断言:可以将多个断言组合起来测试复杂条件
  4. 自定义错误消息:对于关键断言,添加自定义消息提高可读性

go-testpredicate 通过其丰富的断言方法和详细的诊断输出,可以显著提高 Go 测试代码的质量和可维护性。相比标准库的 testing 包或其他简单断言库,它能提供更友好的测试失败信息和更灵活的断言方式。

回到顶部