Go语言测试库stretchr/testify

Go语言测试库stretchr/testify

在其他语言中处理测试时,你可能熟悉使用断言和期望。但是,在Go中,我找不到类似的东西,直到我发现了

testify包,Testify的 assert 包为我们的测试提供了各种有用的工具。

Github地址:https://github.com/stretchr/testify

官方文档:https://pkg.go.dev/github.com/stretchr/testify

1、安装

go get github.com/stretchr/testify

2、assert package

package go_testify

import (
	"github.com/stretchr/testify/assert"
	"testing"
)

type Object struct {
	Value string
}

func TestSomething(t *testing.T) {
	var object =  Object{Value: "Something"}
	// assert equality
	assert.Equal(t, 123, 123, "they should be equal")
	// assert inequality
	assert.NotEqual(t, 123, 456, "they should not be equal")
	// assert for nil (good for errors)
	assert.Nil(t, nil)
	// assert for not nil (good when you expect something)
	if assert.NotNil(t, object) {
		// now we know that object isn't nil, we are safe to make
		// further assertions without causing any errors
		assert.Equal(t, "Something", object.Value)
	}
}
$ go test -v 001_test.go
=== RUN   TestSomething
--- PASS: TestSomething (0.00s)
PASS
ok      command-line-arguments  0.290s

如果多次断言,请使用以下命令:

package go_testify

import (
	"github.com/stretchr/testify/assert"
	"testing"
)

type Object struct {
	Value string
}

func TestSomething(t *testing.T) {
	var object = Object{Value: "Something"}
	assert := assert.New(t)
	// assert equality
	assert.Equal(123, 123, "they should be equal")
	// assert inequality
	assert.NotEqual(123, 456, "they should not be equal")
	// assert for nil (good for errors)
	assert.Nil(nil)
	// assert for not nil (good when you expect something)
	if assert.NotNil(object) {
		// now we know that object isn't nil, we are safe to make
		// further assertions without causing any errors
		assert.Equal("Something", object.Value)
	}
}
$ go test -v 002_test.go
=== RUN   TestSomething
--- PASS: TestSomething (0.00s)
PASS
ok      command-line-arguments  0.033s

3、require package

require包提供了与assert包相同的全局函数,但它们并没有返回布尔结果,而是终止了当前测试。

package go_testify

import (
	"github.com/stretchr/testify/require"
	"testing"
)

type Object struct {
	Value string
}

func TestSomething(t *testing.T) {
	var object = Object{Value: "Something"}
	require.Equal(t, 123, 123, "they should be equal")
	require.NotEqual(t, 123, 456, "they should not be equal")
	require.Nil(t, nil)
	require.NotNil(t, object)
}
$ go test -v 003_test.go
=== RUN   TestSomething
--- PASS: TestSomething (0.00s)
PASS
ok      command-line-arguments  0.261s
package go_testify

import (
	"github.com/stretchr/testify/require"
	"testing"
)

type Object struct {
	Value string
}

func TestSomething(t *testing.T) {
	var object = Object{Value: "Something"}
	require := require.New(t)
	require.Equal(123, 123, "they should be equal")
	require.NotEqual(123, 456, "they should not be equal")
	require.Nil(nil)
	require.NotNil(t, object)
}
$ go test -v 004_test.go
=== RUN   TestSomething
--- PASS: TestSomething (0.00s)
PASS
ok      command-line-arguments  0.250s

4、mock package

mock包提供了一种用于轻松编写mock对象的机制,在编写测试代码时可以使用该机制来代替真实对象。

package go_testify

import (
	"fmt"
	"github.com/stretchr/testify/mock"
	"testing"
)

// Test objects
// MyMockedObject是一个模拟对象,它实现了一个接口,该接口描述了我正在测试的代码所依赖的对象
type MyMockedObject struct {
	mock.Mock
}

// DoSomething是MyMockedObject上的一个方法,它实现了一些接口,只记录活动,并返回Mock对象告诉的内容
// 在真实的对象中,这个方法会做一些有用的事情,但由于这是一个模拟对象,我们只需要将其截断
func (m *MyMockedObject) DoSomething(number int) (bool, error) {
	args := m.Called(number)
	return args.Bool(0), args.Error(1)
}

func targetFuncThatDoesSomethingWithObj1(myMockedObject *MyMockedObject) (bool, error) {
	b, err := myMockedObject.DoSomething(123)
	if err != nil {
		return false, fmt.Errorf("failed, error details: %w", err)
	}
	return b, nil
}

// 实际测试功能
// TestSomething是一个如何使用我们的测试对象来断言我们正在测试的一些目标代码的示例
func TestSomething(t *testing.T) {
	testObj := new(MyMockedObject)
	testObj.On("DoSomething", 123).Return(true, nil)
	targetFuncThatDoesSomethingWithObj1(testObj)
	testObj.AssertExpectations(t)
}

// TestSomethingWithPlaceholder是关于如何使用我们的测试对象来断言我们正在测试的一些目标代码的第二个例子
// 这次使用占位符,当传入的数据通常是动态生成的,并且无法预先预测时可能会使用占位符
func TestSomethingWithPlaceholder(t *testing.T) {
	testObj := new(MyMockedObject)
	testObj.On("DoSomething", mock.Anything).Return(true, nil)
	targetFuncThatDoesSomethingWithObj2(testObj)
	testObj.AssertExpectations(t)
}

func targetFuncThatDoesSomethingWithObj2(myMockedObject *MyMockedObject) (bool, error) {
	b, err := myMockedObject.DoSomething(123)
	if err != nil {
		return false, fmt.Errorf("failed, error details: %w", err)
	}
	return b, nil
}

// 展示了如何使用Unset方法清理处理程序,然后添加新的处理程序
func TestSomethingElse2(t *testing.T) {
	testObj := new(MyMockedObject)
	mockCall := testObj.On("DoSomething", mock.Anything).Return(true, nil)
	targetFuncThatDoesSomethingWithObj3(testObj)
	testObj.AssertExpectations(t)
	mockCall.Unset()
	testObj.On("DoSomething", mock.Anything).Return(false, nil)
	testObj.AssertExpectations(t)
}

func targetFuncThatDoesSomethingWithObj3(myMockedObject *MyMockedObject) (bool, error) {
	b, err := myMockedObject.DoSomething(123)
	if err != nil {
		return false, fmt.Errorf("failed, error details: %w", err)
	}
	return b, nil
}
$ go test -v 005_test.go
=== RUN   TestSomething
    005_test.go:36: PASS:       DoSomething(int)
--- PASS: TestSomething (0.00s)
=== RUN   TestSomethingWithPlaceholder
    005_test.go:45: PASS:       DoSomething(string)
--- PASS: TestSomethingWithPlaceholder (0.00s)
=== RUN   TestSomethingElse2
    005_test.go:61: PASS:       DoSomething(string)
    005_test.go:64: PASS:       DoSomething(string)
--- PASS: TestSomethingElse2 (0.00s)
PASS
ok      command-line-arguments  0.262s

5、suite package

suite 包您可以使用结构体构建测试套件,在结构体上定义设置/拆卸和测试方法,并像平常一样使用 go test 运行

它们。

package go_testify

import (
	"testing"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/suite"
)

type ExampleTestSuite struct {
	suite.Suite
	VariableThatShouldStartAtFive int
}

// before each test
func (suite *ExampleTestSuite) SetupTest() {
	suite.VariableThatShouldStartAtFive = 5
}

func (suite *ExampleTestSuite) TestExample() {
	assert.Equal(suite.T(), 5, suite.VariableThatShouldStartAtFive)
}

func TestExampleTestSuite(t *testing.T) {
	suite.Run(t, new(ExampleTestSuite))
}
$ go test -v 006_test.go
=== RUN   TestExampleTestSuite
=== RUN   TestExampleTestSuite/TestExample
--- PASS: TestExampleTestSuite (0.00s)
    --- PASS: TestExampleTestSuite/TestExample (0.00s)
PASS
ok      command-line-arguments  0.371s

要获得一个更完整的示例,使用 suite 包提供的所有功能,请查看我们的示例测试suite :

package go_testify

import (
	"testing"
	"github.com/stretchr/testify/suite"
)

type ExampleTestSuite struct {
	suite.Suite
	VariableThatShouldStartAtFive int
}

// before each test
func (suite *ExampleTestSuite) SetupTest() {
	suite.VariableThatShouldStartAtFive = 5
}

func (suite *ExampleTestSuite) TestExample() {
	suite.Equal(suite.VariableThatShouldStartAtFive, 5)
}

func TestExampleTestSuite(t *testing.T) {
	suite.Run(t, new(ExampleTestSuite))
}
$ go test -v 007_test.go
=== RUN   TestExampleTestSuite
=== RUN   TestExampleTestSuite/TestExample
--- PASS: TestExampleTestSuite (0.00s)
    --- PASS: TestExampleTestSuite/TestExample (0.00s)
PASS
ok      command-line-arguments  0.036s

6、常用的stretchr/testify框架函数

func Equal(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool
func NotEqual(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool

func Nil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool
func NotNil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool

func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool
func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool

func NoError(t TestingT, err error, msgAndArgs ...interface{}) bool
func Error(t TestingT, err error, msgAndArgs ...interface{}) bool

func Zero(t TestingT, i interface{}, msgAndArgs ...interface{}) bool
func NotZero(t TestingT, i interface{}, msgAndArgs ...interface{}) bool

func True(t TestingT, value bool, msgAndArgs ...interface{}) bool
func False(t TestingT, value bool, msgAndArgs ...interface{}) bool

func Len(t TestingT, object interface{}, length int, msgAndArgs ...interface{}) bool

func NotContains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool
func NotContains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool
func Subset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok bool)
func NotSubset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok bool)

func FileExists(t TestingT, path string, msgAndArgs ...interface{}) bool
func DirExists(t TestingT, path string, msgAndArgs ...interface{}) bool
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值