golang可组合的Hamcrest风格断言匹配器插件库gocrest的使用
Golang可组合的Hamcrest风格断言匹配器插件库gocrest的使用
gocrest是一个类似Hamcrest的Go断言库,它的匹配器是可组合的、自描述的,并且可以以更易读的形式串联起来创建灵活的断言。
包导入
import (
"github.com/corbym/gocrest/by"
"github.com/corbym/gocrest/then"
"github.com/corbym/gocrest/is"
"github.com/corbym/gocrest/has"
)
基本示例
then.AssertThat(testing, "hi", is.EqualTo("bye").Reason("we are going"))
输出:
we are going
Expected: value equal to <bye>
but: <hi>
组合使用AllOf
then.AssertThat(t, "abcdef", is.AllOf(is.StringContaining("abc"), is.LessThan("ghi")))
异步匹配(v1.0.8及以上版本)
读取器示例
//Reader
then.WithinFiveSeconds(t, func(eventually gocrest.TestingT) {
then.AssertThat(eventually, by.Reading(slowReader, 1024), is.EqualTo([]byte("abcdefghijklmnopqrstuv")))
})
通道示例
//channels
then.Eventually(t, time.Second*5, time.Second, func(eventually gocrest.TestingT) {
then.AssertThat(eventually, by.Channelling(channel), is.EqualTo(3).Reason("should not fail"))
})
多个断言
// multiple assertions
then.WithinTenSeconds(t, func(eventually gocrest.TestingT) {
then.AssertThat(eventually, by.Channelling(channel), is.EqualTo(3).Reason("should not fail"))
then.AssertThat(eventually, by.Channelling(channelTwo), is.EqualTo("11").Reason("This is unreachable"))
})
v1.1.0 - 泛型支持
所有匹配器现在都使用泛型而不是反射。但仍有一些使用反射,例如TypeName等。
主要变化:
- ValueContaining被拆分为StringContaining、MapContaining、MapContainingValues、MapMatchingValues、ArrayContaining和ArrayMatching
- 不再对未知类型panic,因为类型会在编译时失败
- Map匹配器通常需要显式知道map键值的类型,否则编译器会报错
示例:
then.AssertThat(testing, map[string]bool{"hi": true, "bye": true}, has.AllKeys[string, bool]("hi", "bye"))
has.Length()
对类型要求严格,因为它同时适用于字符串和数组is.LessThan()
和is.GreaterThan()
(以及is.GreaterThanOrEqualTo
和is.LessThanOrEqualTo
)不再适用于复杂类型
现有匹配器
- is.EqualTo(x)
- is.EqualToIgnoringWhitespace(string) - 比较两个字符串,忽略空白字符
- is.Nil() - 值必须为nil
- is.StringContaining(expected) – 类似containsAll
- is.MapContaining(expected) – 类似containsAll
- is.MapContainingValues(expected) – 类似containsAll
- is.MapMatchingValues(expected) – 类似containsAll
- is.ArrayContaining(expected) – 类似containsAll
- is.ArrayMatching(expected) – 类似containsAll
- is.Not(m *Matcher) – 逻辑非
- is.MatchForPattern(regex string) – 字符串正则表达式
- has.FunctionNamed(string x) - 检查接口是否有函数(方法)
- has.FieldNamed(string x) - 检查结构体是否有名为x的字段
- is.AllOf(… *Matcher) - 所有匹配器都匹配时返回true
- is.AnyOf(… *Matcher) - 任一匹配器匹配时返回true
- is.GreaterThan(expected) - 检查actual > expected
- is.LessThan(expected)
- is.Empty() - 匹配actual是""、nil或len(actual)==0
- is.LessThan(x)
- is.LessThanOrEqualTo(x)
- is.GreaterThan(x)
- is.GreaterThanOrEqualTo(x)
- has.Length(x) - 匹配给定值(int或匹配器)与给定值的长度
- has.Prefix(x) - 字符串以x开头
- has.Suffix(x) - 字符串以x结尾
- has.Key(x) - map有键x
- has.AllKeys(T x, T y) (或has.AllKeys([]T{x,y})) - 在map中查找类型为T的键
- has.EveryElement(x1…xn) - 检查actual[i]是否匹配对应的期望值(x[i])
- has.StructWithValues(map[string]*gocrest.Matcher) - 检查actual[key]是否匹配对应的期望值(x[key])
更多关于golang可组合的Hamcrest风格断言匹配器插件库gocrest的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
1 回复
更多关于golang可组合的Hamcrest风格断言匹配器插件库gocrest的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
使用gocrest构建Hamcrest风格的Golang断言
gocrest是一个Golang的断言匹配库,它采用了类似Hamcrest的可组合匹配器风格,提供了更富有表现力的断言方式。下面我将介绍gocrest的核心用法和示例代码。
安装gocrest
go get github.com/corbym/gocrest
基本用法
简单断言
package main
import (
"testing"
"github.com/corbym/gocrest/has"
"github.com/corbym/gocrest/is"
"github.com/corbym/gocrest/then"
)
func TestSimpleAssertions(t *testing.T) {
// 相等断言
then.AssertThat(t, 42, is.EqualTo(42))
// 不相等断言
then.AssertThat(t, "hello", is.Not(is.EqualTo("world")))
// 包含断言
then.AssertThat(t, []int{1, 2, 3}, has.Item(is.EqualTo(2)))
// 长度断言
then.AssertThat(t, "golang", has.Length(is.GreaterThan(4)))
}
常用匹配器
基本匹配器
func TestBasicMatchers(t *testing.T) {
// 空值检查
var nilSlice []int
then.AssertThat(t, nilSlice, is.Nil())
// 非空检查
then.AssertThat(t, "not empty", is.Not(is.Nil()))
// 布尔检查
then.AssertThat(t, true, is.True())
then.AssertThat(t, false, is.False())
// 类型检查
then.AssertThat(t, 3.14, is.AllOf(
is.Not(is.Nil()),
is.InstanceOf(float64(0)),
))
}
数值匹配器
func TestNumberMatchers(t *testing.T) {
// 大于
then.AssertThat(t, 10, is.GreaterThan(5))
// 小于等于
then.AssertThat(t, 3.14, is.LessThanOrEqualTo(3.14))
// 在范围内
then.AssertThat(t, 7, is.AllOf(
is.GreaterThan(5),
is.LessThan(10),
))
}
字符串匹配器
func TestStringMatchers(t *testing.T) {
// 包含子串
then.AssertThat(t, "hello world", contains.String("world"))
// 匹配正则
then.AssertThat(t, "test@example.com", matches.Pattern(`^.+@.+\..+$`))
// 以...开头
then.AssertThat(t, "golang", starts.With("go"))
}
集合匹配器
func TestCollectionMatchers(t *testing.T) {
slice := []int{1, 2, 3, 4, 5}
// 包含特定元素
then.AssertThat(t, slice, has.Item(is.EqualTo(3)))
// 所有元素满足条件
then.AssertThat(t, slice, has.All(
is.GreaterThan(0),
is.LessThan(10),
))
// 长度检查
then.AssertThat(t, slice, has.Length(is.EqualTo(5)))
// 映射检查
m := map[string]int{"a": 1, "b": 2}
then.AssertThat(t, m, has.Key(is.EqualTo("a")))
then.AssertThat(t, m, has.Value(is.EqualTo(2)))
}
组合匹配器
gocrest的强大之处在于可以组合多个匹配器:
func TestCombinedMatchers(t *testing.T) {
value := "Golang is awesome"
then.AssertThat(t, value, is.AllOf(
contains.String("awesome"),
has.Length(is.GreaterThan(10)),
starts.With("Golang"),
is.Not(contains.String("terrible")),
))
}
自定义匹配器
你可以创建自己的匹配器:
func isEven() *is.Matcher {
return &is.Matcher{
Describe: "even number",
Matches: func(actual interface{}) bool {
if num, ok := actual.(int); ok {
return num%2 == 0
}
return false
},
}
}
func TestCustomMatcher(t *testing.T) {
then.AssertThat(t, 42, isEven())
}
错误消息
当断言失败时,gocrest会提供详细的错误信息:
func TestErrorMessage(t *testing.T) {
// 失败时会输出:
// Expected: value equal to <42>
// but: <43> was not equal to <42>
then.AssertThat(t, 43, is.EqualTo(42))
}
与标准testing包的比较
相比标准库的if x != y { t.Error() }
模式,gocrest提供了:
- 更可读的断言语法
- 更详细的错误信息
- 可组合的匹配器
- 丰富的内置匹配器集合
总结
gocrest为Golang测试提供了Hamcrest风格的断言方式,通过可组合的匹配器使测试代码更清晰、更富有表现力。它特别适合需要复杂断言的场景,能够显著提高测试代码的可读性和维护性。
对于简单的测试用例,标准库可能更直接,但对于复杂的断言逻辑,gocrest能提供更好的表达能力和错误信息。