Compare commits

..

No commits in common. "master" and "v1.7.4" have entirely different histories.

56 changed files with 1877 additions and 6490 deletions

View File

@ -1,4 +1,4 @@
#!/usr/bin/env bash
#!/bin/bash
if [ -n "$(gofmt -l .)" ]; then
echo "Go code is not formatted:"

View File

@ -1,4 +1,4 @@
#!/usr/bin/env bash
#!/bin/bash
# If GOMOD is defined we are running with Go Modules enabled, either
# automatically or via the GO111MODULE=on environment variable. Codegen only

View File

@ -1,4 +1,4 @@
#!/usr/bin/env bash
#!/bin/bash
set -e

View File

@ -1,12 +0,0 @@
#!/usr/bin/env bash
# Verify that the code snippets in README.md are formatted.
# The tool https://github.com/hougesen/mdsf is used.
if [ -n "$(mdsf verify --config .mdsf.json --log-level error README.md 2>&1)" ]; then
echo "Go code in the README.md is not formatted."
echo "Did you forget to run 'mdsf format --config .mdsf.json README.md'?"
mdsf format --config .mdsf.json README.md
git diff
exit 1
fi

View File

@ -1,23 +0,0 @@
---
name: Bug report
about: Format to report a bug
title: ''
labels: bug
assignees: ''
---
<!-- If this is a question, consider using the discussion section of this repo -->
<!-- Here: https://github.com/stretchr/testify/discussions/new?category=q-a -->
## Description
<!-- A detailed description of the bug -->
## Step To Reproduce
<!-- Steps or code snippet to reproduce the behavior -->
## Expected behavior
<!-- A clear and concise description of what you expected to happen -->
## Actual behavior
<!-- What testify does -->

View File

@ -1,20 +0,0 @@
---
name: Feature request
about: Propose a new feature
title: ''
labels: enhancement
assignees: ''
---
<!-- If this is a question, consider using the discussion section of this repo -->
<!-- Here: https://github.com/stretchr/testify/discussions/new?category=q-a -->
## Description
<!-- A clear and concise description of what feature you are proposing -->
## Proposed solution
<!-- Optionally a suggested implementation -->
## Use case
<!-- What is the motivation? What workarounds have you used? -->

View File

@ -6,36 +6,14 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
go_version:
- stable
- oldstable
go_version: ["1.18.1", "1.17.6", "1.16.5"]
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v3
- name: Setup Go
uses: actions/setup-go@v5
uses: actions/setup-go@v3.2.0
with:
go-version: ${{ matrix.go_version }}
- run: npm install -g mdsf-cli
- run: ./.ci.gogenerate.sh
- run: ./.ci.gogenerate.sh
- run: ./.ci.gofmt.sh
- run: ./.ci.readme.fmt.sh
- run: ./.ci.govet.sh
- run: go test -v -race ./...
test:
runs-on: ubuntu-latest
strategy:
matrix:
go_version:
- "1.17"
- "1.18"
- "1.19"
- "1.20"
- "1.21"
- "1.22"
steps:
- uses: actions/checkout@v4
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: ${{ matrix.go_version }}
- run: go test -v -race ./...

View File

@ -1,21 +0,0 @@
name: Create release from new tag
# this flow will be run only when new tags are pushed that match our pattern
on:
push:
tags:
- "v[0-9]+.[0-9]+.[0-9]+"
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Create GitHub release from tag
uses: softprops/action-gh-release@v2
with:
generate_release_notes: true

6
.gitignore vendored
View File

@ -22,9 +22,3 @@ _testmain.go
*.exe
.DS_Store
# Output of "go test -c"
/assert/assert.test
/require/require.test
/suite/suite.test
/mock/mock.test

View File

@ -1,12 +0,0 @@
{
"$schema": "https://raw.githubusercontent.com/hougesen/mdsf/main/schemas/v0.8.2/mdsf.schema.json",
"format_finished_document": false,
"languages": {
"go": [
[
"gofmt",
"goimports"
]
]
}
}

View File

@ -1,12 +0,0 @@
# Emeritus
We would like to acknowledge previous testify maintainers and their huge contributions to our collective success:
* @matryer
* @glesica
* @ernesto-jimenez
* @mvdkleijn
* @georgelesica-wf
* @bencampbell-wf
We thank these members for their service to this community.

View File

@ -3,15 +3,7 @@
The individuals listed below are active in the project and have the ability to approve and merge
pull requests.
* @glesica
* @boyan-soubachov
* @dolmen
* @MovieStoreGuy
* @brackendawson
* @mvdkleijn
## Approvers
The individuals listed below are active in the project and have the ability to approve pull
requests.
* @arjunmahishi
* @ccoVeille

222
README.md
View File

@ -1,11 +1,9 @@
Testify - Thou Shalt Write Tests
================================
> [!NOTE]
> Testify is being maintained at v1, no breaking changes will be accepted in this repo.
> [See discussion about v2](https://github.com/stretchr/testify/discussions/1560).
We are working on testify v2 and would love to hear what you'd like to see in it, have your say here: https://cutt.ly/testify
[![Build Status](https://github.com/stretchr/testify/actions/workflows/main.yml/badge.svg?branch=master)](https://github.com/stretchr/testify/actions/workflows/main.yml) [![Go Report Card](https://goreportcard.com/badge/github.com/stretchr/testify)](https://goreportcard.com/report/github.com/stretchr/testify) [![PkgGoDev](https://pkg.go.dev/badge/github.com/stretchr/testify)](https://pkg.go.dev/github.com/stretchr/testify)
[![Build Status](https://travis-ci.org/stretchr/testify.svg)](https://travis-ci.org/stretchr/testify) [![Go Report Card](https://goreportcard.com/badge/github.com/stretchr/testify)](https://goreportcard.com/report/github.com/stretchr/testify) [![PkgGoDev](https://pkg.go.dev/badge/github.com/stretchr/testify)](https://pkg.go.dev/github.com/stretchr/testify)
Go code (golang) set of packages that provide many tools for testifying that your code will behave as you intend.
@ -18,12 +16,14 @@ Features include:
Get started:
* Install testify with [one line of code](#installation), or [update it with another](#staying-up-to-date)
* For an introduction to writing test code in Go, see https://go.dev/doc/code#Testing
* Check out the API Documentation https://pkg.go.dev/github.com/stretchr/testify
* Use [testifylint](https://github.com/Antonboom/testifylint) (via [golangci-lint](https://golangci-lint.run/)) to avoid common mistakes
* A little about [Test-Driven Development (TDD)](https://en.wikipedia.org/wiki/Test-driven_development)
* For an introduction to writing test code in Go, see http://golang.org/doc/code.html#Testing
* Check out the API Documentation http://godoc.org/github.com/stretchr/testify
* To make your testing life easier, check out our other project, [gorc](http://github.com/stretchr/gorc)
* A little about [Test-Driven Development (TDD)](http://en.wikipedia.org/wiki/Test-driven_development)
[`assert`](https://pkg.go.dev/github.com/stretchr/testify/assert "API documentation") package
[`assert`](http://godoc.org/github.com/stretchr/testify/assert "API documentation") package
-------------------------------------------------------------------------------------------
The `assert` package provides some helpful methods that allow you to write better test code in Go.
@ -38,27 +38,30 @@ See it in action:
package yours
import (
"testing"
"github.com/stretchr/testify/assert"
"testing"
"github.com/stretchr/testify/assert"
)
func TestSomething(t *testing.T) {
// assert equality
assert.Equal(t, 123, 123, "they should be equal")
// assert inequality
assert.NotEqual(t, 123, 456, "they should not be equal")
// assert equality
assert.Equal(t, 123, 123, "they should be equal")
// assert for nil (good for errors)
assert.Nil(t, object)
// assert inequality
assert.NotEqual(t, 123, 456, "they should not be equal")
// assert for nil (good for errors)
assert.Nil(t, object)
// 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)
}
// 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)
}
}
```
@ -71,55 +74,52 @@ if you assert many times, use the below:
package yours
import (
"testing"
"github.com/stretchr/testify/assert"
"testing"
"github.com/stretchr/testify/assert"
)
func TestSomething(t *testing.T) {
assert := assert.New(t)
assert := assert.New(t)
// assert equality
assert.Equal(123, 123, "they should be equal")
// assert equality
assert.Equal(123, 123, "they should be equal")
// assert inequality
assert.NotEqual(123, 456, "they should not be equal")
// assert inequality
assert.NotEqual(123, 456, "they should not be equal")
// assert for nil (good for errors)
assert.Nil(object)
// assert for nil (good for errors)
assert.Nil(object)
// 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)
}
// 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)
}
}
```
[`require`](https://pkg.go.dev/github.com/stretchr/testify/require "API documentation") package
[`require`](http://godoc.org/github.com/stretchr/testify/require "API documentation") package
---------------------------------------------------------------------------------------------
The `require` package provides same global functions as the `assert` package, but instead of returning a boolean result they terminate current test.
These functions must be called from the goroutine running the test or benchmark function, not from other goroutines created during the test.
Otherwise race conditions may occur.
See [t.FailNow](https://pkg.go.dev/testing#T.FailNow) for details.
See [t.FailNow](http://golang.org/pkg/testing/#T.FailNow) for details.
[`mock`](https://pkg.go.dev/github.com/stretchr/testify/mock "API documentation") package
[`mock`](http://godoc.org/github.com/stretchr/testify/mock "API documentation") package
----------------------------------------------------------------------------------------
The `mock` package provides a mechanism for easily writing mock objects that can be used in place of real objects when writing test code.
An example test function that tests a piece of code that relies on an external object `testObj`, can set up expectations (testify) and assert that they indeed happened:
An example test function that tests a piece of code that relies on an external object `testObj`, can setup expectations (testify) and assert that they indeed happened:
```go
package yours
import (
"testing"
"github.com/stretchr/testify/mock"
"testing"
"github.com/stretchr/testify/mock"
)
/*
@ -128,8 +128,8 @@ import (
// MyMockedObject is a mocked object that implements an interface
// that describes an object that the code I am testing relies on.
type MyMockedObject struct {
mock.Mock
type MyMockedObject struct{
mock.Mock
}
// DoSomething is a method on MyMockedObject that implements some interface
@ -140,8 +140,10 @@ type MyMockedObject struct {
//
// NOTE: This method is not being tested here, code that uses this object is.
func (m *MyMockedObject) DoSomething(number int) (bool, error) {
args := m.Called(number)
return args.Bool(0), args.Error(1)
args := m.Called(number)
return args.Bool(0), args.Error(1)
}
/*
@ -151,17 +153,20 @@ func (m *MyMockedObject) DoSomething(number int) (bool, error) {
// TestSomething is an example of how to use our test object to
// make assertions about some target code we are testing.
func TestSomething(t *testing.T) {
// create an instance of our test object
testObj := new(MyMockedObject)
// set up expectations
testObj.On("DoSomething", 123).Return(true, nil)
// create an instance of our test object
testObj := new(MyMockedObject)
// setup expectations
testObj.On("DoSomething", 123).Return(true, nil)
// call the code we are testing
targetFuncThatDoesSomethingWithObj(testObj)
// assert that the expectations were met
testObj.AssertExpectations(t)
// call the code we are testing
targetFuncThatDoesSomethingWithObj(testObj)
// assert that the expectations were met
testObj.AssertExpectations(t)
}
// TestSomethingWithPlaceholder is a second example of how to use our test object to
@ -170,131 +175,105 @@ func TestSomething(t *testing.T) {
// data being passed in is normally dynamically generated and cannot be
// predicted beforehand (eg. containing hashes that are time sensitive)
func TestSomethingWithPlaceholder(t *testing.T) {
// create an instance of our test object
testObj := new(MyMockedObject)
// set up expectations with a placeholder in the argument list
testObj.On("DoSomething", mock.Anything).Return(true, nil)
// create an instance of our test object
testObj := new(MyMockedObject)
// call the code we are testing
targetFuncThatDoesSomethingWithObj(testObj)
// setup expectations with a placeholder in the argument list
testObj.On("DoSomething", mock.Anything).Return(true, nil)
// assert that the expectations were met
testObj.AssertExpectations(t)
// call the code we are testing
targetFuncThatDoesSomethingWithObj(testObj)
}
// assert that the expectations were met
testObj.AssertExpectations(t)
// TestSomethingElse2 is a third example that shows how you can use
// the Unset method to cleanup handlers and then add new ones.
func TestSomethingElse2(t *testing.T) {
// create an instance of our test object
testObj := new(MyMockedObject)
// set up expectations with a placeholder in the argument list
mockCall := testObj.On("DoSomething", mock.Anything).Return(true, nil)
// call the code we are testing
targetFuncThatDoesSomethingWithObj(testObj)
// assert that the expectations were met
testObj.AssertExpectations(t)
// remove the handler now so we can add another one that takes precedence
mockCall.Unset()
// return false now instead of true
testObj.On("DoSomething", mock.Anything).Return(false, nil)
testObj.AssertExpectations(t)
}
```
For more information on how to write mock code, check out the [API documentation for the `mock` package](https://pkg.go.dev/github.com/stretchr/testify/mock).
For more information on how to write mock code, check out the [API documentation for the `mock` package](http://godoc.org/github.com/stretchr/testify/mock).
You can use the [mockery tool](https://vektra.github.io/mockery/latest/) to autogenerate the mock code against an interface as well, making using mocks much quicker.
You can use the [mockery tool](http://github.com/vektra/mockery) to autogenerate the mock code against an interface as well, making using mocks much quicker.
[`suite`](https://pkg.go.dev/github.com/stretchr/testify/suite "API documentation") package
[`suite`](http://godoc.org/github.com/stretchr/testify/suite "API documentation") package
-----------------------------------------------------------------------------------------
> [!WARNING]
> The suite package does not support parallel tests. See [#934](https://github.com/stretchr/testify/issues/934).
The `suite` package provides functionality that you might be used to from more common object-oriented languages. With it, you can build a testing suite as a struct, build setup/teardown methods and testing methods on your struct, and run them with 'go test' as per normal.
The `suite` package provides functionality that you might be used to from more common object oriented languages. With it, you can build a testing suite as a struct, build setup/teardown methods and testing methods on your struct, and run them with 'go test' as per normal.
An example suite is shown below:
```go
// Basic imports
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/suite"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/suite"
)
// Define the suite, and absorb the built-in basic suite
// functionality from testify - including a T() method which
// returns the current testing context
type ExampleTestSuite struct {
suite.Suite
VariableThatShouldStartAtFive int
suite.Suite
VariableThatShouldStartAtFive int
}
// Make sure that VariableThatShouldStartAtFive is set to five
// before each test
func (suite *ExampleTestSuite) SetupTest() {
suite.VariableThatShouldStartAtFive = 5
suite.VariableThatShouldStartAtFive = 5
}
// All methods that begin with "Test" are run as tests within a
// suite.
func (suite *ExampleTestSuite) TestExample() {
assert.Equal(suite.T(), 5, suite.VariableThatShouldStartAtFive)
assert.Equal(suite.T(), 5, suite.VariableThatShouldStartAtFive)
}
// In order for 'go test' to run this suite, we need to create
// a normal test function and pass our suite to suite.Run
func TestExampleTestSuite(t *testing.T) {
suite.Run(t, new(ExampleTestSuite))
suite.Run(t, new(ExampleTestSuite))
}
```
For a more complete example, using all of the functionality provided by the suite package, look at our [example testing suite](https://github.com/stretchr/testify/blob/master/suite/suite_test.go)
For more information on writing suites, check out the [API documentation for the `suite` package](https://pkg.go.dev/github.com/stretchr/testify/suite).
For more information on writing suites, check out the [API documentation for the `suite` package](http://godoc.org/github.com/stretchr/testify/suite).
`Suite` object has assertion methods:
```go
// Basic imports
import (
"testing"
"github.com/stretchr/testify/suite"
"testing"
"github.com/stretchr/testify/suite"
)
// Define the suite, and absorb the built-in basic suite
// functionality from testify - including assertion methods.
type ExampleTestSuite struct {
suite.Suite
VariableThatShouldStartAtFive int
suite.Suite
VariableThatShouldStartAtFive int
}
// Make sure that VariableThatShouldStartAtFive is set to five
// before each test
func (suite *ExampleTestSuite) SetupTest() {
suite.VariableThatShouldStartAtFive = 5
suite.VariableThatShouldStartAtFive = 5
}
// All methods that begin with "Test" are run as tests within a
// suite.
func (suite *ExampleTestSuite) TestExample() {
suite.Equal(suite.VariableThatShouldStartAtFive, 5)
suite.Equal(suite.VariableThatShouldStartAtFive, 5)
}
// In order for 'go test' to run this suite, we need to create
// a normal test function and pass our suite to suite.Run
func TestExampleTestSuite(t *testing.T) {
suite.Run(t, new(ExampleTestSuite))
suite.Run(t, new(ExampleTestSuite))
}
```
@ -321,13 +300,14 @@ Import the `testify/assert` package into your code using this template:
package yours
import (
"testing"
"github.com/stretchr/testify/assert"
"testing"
"github.com/stretchr/testify/assert"
)
func TestSomething(t *testing.T) {
assert.True(t, true, "True is true!")
assert.True(t, true, "True is true!")
}
```
@ -343,7 +323,7 @@ To update Testify to the latest version, use `go get -u github.com/stretchr/test
Supported go versions
==================
We currently support the most recent major Go versions from 1.19 onward.
We currently support the most recent major Go versions from 1.13 onward.
------
@ -354,7 +334,7 @@ Please feel free to submit issues, fork the repository and send pull requests!
When submitting an issue, we ask that you please include a complete test function that demonstrates the issue. Extra credit for those using Testify to write the test code that demonstrates it.
Code generation is used. [Look for `Code generated with`](https://github.com/search?q=repo%3Astretchr%2Ftestify%20%22Code%20generated%20with%22&type=code) at the top of some files. Run `go generate ./...` to update generated files.
Code generation is used. Look for `CODE GENERATED AUTOMATICALLY` at the top of some files. Run `go generate ./...` to update generated files.
We also chat on the [Gophers Slack](https://gophers.slack.com) group in the `#testify` and `#testify-dev` channels.

View File

@ -16,6 +16,7 @@ import (
"go/token"
"go/types"
"io"
"io/ioutil"
"log"
"os"
"path"
@ -100,15 +101,13 @@ func parseTemplates() (*template.Template, *template.Template, error) {
return nil, nil, err
}
if *tmplFile != "" {
f, err := os.ReadFile(*tmplFile)
f, err := ioutil.ReadFile(*tmplFile)
if err != nil {
return nil, nil, err
}
funcTemplate = string(f)
}
tmpl, err := template.New("function").Funcs(template.FuncMap{
"replace": strings.ReplaceAll,
}).Parse(funcTemplate)
tmpl, err := template.New("function").Parse(funcTemplate)
if err != nil {
return nil, nil, err
}
@ -182,7 +181,7 @@ func parsePackageSource(pkg string) (*types.Scope, *doc.Package, error) {
files := make(map[string]*ast.File)
fileList := make([]*ast.File, len(pd.GoFiles))
for i, fname := range pd.GoFiles {
src, err := os.ReadFile(path.Join(pd.Dir, fname))
src, err := ioutil.ReadFile(path.Join(pd.Dir, fname))
if err != nil {
return nil, nil, err
}
@ -298,8 +297,10 @@ func (f *testFunc) CommentWithoutT(receiver string) string {
return strings.Replace(f.Comment(), search, replace, -1)
}
// Standard header https://go.dev/s/generatedcode.
var headerTemplate = `// Code generated with github.com/stretchr/testify/_codegen; DO NOT EDIT.
var headerTemplate = `/*
* CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen
* THIS FILE MUST NOT BE EDITED BY HAND
*/
package {{.Name}}

View File

@ -1,19 +1,15 @@
package assert
import (
"bytes"
"fmt"
"reflect"
"time"
)
// Deprecated: CompareType has only ever been for internal use and has accidentally been published since v1.6.0. Do not use it.
type CompareType = compareResult
type compareResult int
type CompareType int
const (
compareLess compareResult = iota - 1
compareLess CompareType = iota - 1
compareEqual
compareGreater
)
@ -31,18 +27,15 @@ var (
uint32Type = reflect.TypeOf(uint32(1))
uint64Type = reflect.TypeOf(uint64(1))
uintptrType = reflect.TypeOf(uintptr(1))
float32Type = reflect.TypeOf(float32(1))
float64Type = reflect.TypeOf(float64(1))
stringType = reflect.TypeOf("")
timeType = reflect.TypeOf(time.Time{})
bytesType = reflect.TypeOf([]byte{})
timeType = reflect.TypeOf(time.Time{})
)
func compare(obj1, obj2 interface{}, kind reflect.Kind) (compareResult, bool) {
func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) {
obj1Value := reflect.ValueOf(obj1)
obj2Value := reflect.ValueOf(obj2)
@ -313,11 +306,11 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (compareResult, bool) {
case reflect.Struct:
{
// All structs enter here. We're not interested in most types.
if !obj1Value.CanConvert(timeType) {
if !canConvert(obj1Value, timeType) {
break
}
// time.Time can be compared!
// time.Time can compared!
timeObj1, ok := obj1.(time.Time)
if !ok {
timeObj1 = obj1Value.Convert(timeType).Interface().(time.Time)
@ -328,53 +321,7 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (compareResult, bool) {
timeObj2 = obj2Value.Convert(timeType).Interface().(time.Time)
}
if timeObj1.Before(timeObj2) {
return compareLess, true
}
if timeObj1.Equal(timeObj2) {
return compareEqual, true
}
return compareGreater, true
}
case reflect.Slice:
{
// We only care about the []byte type.
if !obj1Value.CanConvert(bytesType) {
break
}
// []byte can be compared!
bytesObj1, ok := obj1.([]byte)
if !ok {
bytesObj1 = obj1Value.Convert(bytesType).Interface().([]byte)
}
bytesObj2, ok := obj2.([]byte)
if !ok {
bytesObj2 = obj2Value.Convert(bytesType).Interface().([]byte)
}
return compareResult(bytes.Compare(bytesObj1, bytesObj2)), true
}
case reflect.Uintptr:
{
uintptrObj1, ok := obj1.(uintptr)
if !ok {
uintptrObj1 = obj1Value.Convert(uintptrType).Interface().(uintptr)
}
uintptrObj2, ok := obj2.(uintptr)
if !ok {
uintptrObj2 = obj2Value.Convert(uintptrType).Interface().(uintptr)
}
if uintptrObj1 > uintptrObj2 {
return compareGreater, true
}
if uintptrObj1 == uintptrObj2 {
return compareEqual, true
}
if uintptrObj1 < uintptrObj2 {
return compareLess, true
}
return compare(timeObj1.UnixNano(), timeObj2.UnixNano(), reflect.Int64)
}
}
@ -383,85 +330,79 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (compareResult, bool) {
// Greater asserts that the first element is greater than the second
//
// assert.Greater(t, 2, 1)
// assert.Greater(t, float64(2), float64(1))
// assert.Greater(t, "b", "a")
// assert.Greater(t, 2, 1)
// assert.Greater(t, float64(2), float64(1))
// assert.Greater(t, "b", "a")
func Greater(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
}
failMessage := fmt.Sprintf("\"%v\" is not greater than \"%v\"", e1, e2)
return compareTwoValues(t, e1, e2, []compareResult{compareGreater}, failMessage, msgAndArgs...)
return compareTwoValues(t, e1, e2, []CompareType{compareGreater}, "\"%v\" is not greater than \"%v\"", msgAndArgs...)
}
// GreaterOrEqual asserts that the first element is greater than or equal to the second
//
// assert.GreaterOrEqual(t, 2, 1)
// assert.GreaterOrEqual(t, 2, 2)
// assert.GreaterOrEqual(t, "b", "a")
// assert.GreaterOrEqual(t, "b", "b")
// assert.GreaterOrEqual(t, 2, 1)
// assert.GreaterOrEqual(t, 2, 2)
// assert.GreaterOrEqual(t, "b", "a")
// assert.GreaterOrEqual(t, "b", "b")
func GreaterOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
}
failMessage := fmt.Sprintf("\"%v\" is not greater than or equal to \"%v\"", e1, e2)
return compareTwoValues(t, e1, e2, []compareResult{compareGreater, compareEqual}, failMessage, msgAndArgs...)
return compareTwoValues(t, e1, e2, []CompareType{compareGreater, compareEqual}, "\"%v\" is not greater than or equal to \"%v\"", msgAndArgs...)
}
// Less asserts that the first element is less than the second
//
// assert.Less(t, 1, 2)
// assert.Less(t, float64(1), float64(2))
// assert.Less(t, "a", "b")
// assert.Less(t, 1, 2)
// assert.Less(t, float64(1), float64(2))
// assert.Less(t, "a", "b")
func Less(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
}
failMessage := fmt.Sprintf("\"%v\" is not less than \"%v\"", e1, e2)
return compareTwoValues(t, e1, e2, []compareResult{compareLess}, failMessage, msgAndArgs...)
return compareTwoValues(t, e1, e2, []CompareType{compareLess}, "\"%v\" is not less than \"%v\"", msgAndArgs...)
}
// LessOrEqual asserts that the first element is less than or equal to the second
//
// assert.LessOrEqual(t, 1, 2)
// assert.LessOrEqual(t, 2, 2)
// assert.LessOrEqual(t, "a", "b")
// assert.LessOrEqual(t, "b", "b")
// assert.LessOrEqual(t, 1, 2)
// assert.LessOrEqual(t, 2, 2)
// assert.LessOrEqual(t, "a", "b")
// assert.LessOrEqual(t, "b", "b")
func LessOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
}
failMessage := fmt.Sprintf("\"%v\" is not less than or equal to \"%v\"", e1, e2)
return compareTwoValues(t, e1, e2, []compareResult{compareLess, compareEqual}, failMessage, msgAndArgs...)
return compareTwoValues(t, e1, e2, []CompareType{compareLess, compareEqual}, "\"%v\" is not less than or equal to \"%v\"", msgAndArgs...)
}
// Positive asserts that the specified element is positive
//
// assert.Positive(t, 1)
// assert.Positive(t, 1.23)
// assert.Positive(t, 1)
// assert.Positive(t, 1.23)
func Positive(t TestingT, e interface{}, msgAndArgs ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
}
zero := reflect.Zero(reflect.TypeOf(e))
failMessage := fmt.Sprintf("\"%v\" is not positive", e)
return compareTwoValues(t, e, zero.Interface(), []compareResult{compareGreater}, failMessage, msgAndArgs...)
return compareTwoValues(t, e, zero.Interface(), []CompareType{compareGreater}, "\"%v\" is not positive", msgAndArgs...)
}
// Negative asserts that the specified element is negative
//
// assert.Negative(t, -1)
// assert.Negative(t, -1.23)
// assert.Negative(t, -1)
// assert.Negative(t, -1.23)
func Negative(t TestingT, e interface{}, msgAndArgs ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
}
zero := reflect.Zero(reflect.TypeOf(e))
failMessage := fmt.Sprintf("\"%v\" is not negative", e)
return compareTwoValues(t, e, zero.Interface(), []compareResult{compareLess}, failMessage, msgAndArgs...)
return compareTwoValues(t, e, zero.Interface(), []CompareType{compareLess}, "\"%v\" is not negative", msgAndArgs...)
}
func compareTwoValues(t TestingT, e1 interface{}, e2 interface{}, allowedComparesResults []compareResult, failMessage string, msgAndArgs ...interface{}) bool {
func compareTwoValues(t TestingT, e1 interface{}, e2 interface{}, allowedComparesResults []CompareType, failMessage string, msgAndArgs ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
}
@ -474,17 +415,17 @@ func compareTwoValues(t TestingT, e1 interface{}, e2 interface{}, allowedCompare
compareResult, isComparable := compare(e1, e2, e1Kind)
if !isComparable {
return Fail(t, fmt.Sprintf(`Can not compare type "%T"`, e1), msgAndArgs...)
return Fail(t, fmt.Sprintf("Can not compare type \"%s\"", reflect.TypeOf(e1)), msgAndArgs...)
}
if !containsValue(allowedComparesResults, compareResult) {
return Fail(t, failMessage, msgAndArgs...)
return Fail(t, fmt.Sprintf(failMessage, e1, e2), msgAndArgs...)
}
return true
}
func containsValue(values []compareResult, value compareResult) bool {
func containsValue(values []CompareType, value CompareType) bool {
for _, v := range values {
if v == value {
return true

View File

@ -0,0 +1,16 @@
//go:build go1.17
// +build go1.17
// TODO: once support for Go 1.16 is dropped, this file can be
// merged/removed with assertion_compare_go1.17_test.go and
// assertion_compare_legacy.go
package assert
import "reflect"
// Wrapper around reflect.Value.CanConvert, for compatibility
// reasons.
func canConvert(value reflect.Value, to reflect.Type) bool {
return value.CanConvert(to)
}

View File

@ -0,0 +1,54 @@
//go:build go1.17
// +build go1.17
// TODO: once support for Go 1.16 is dropped, this file can be
// merged/removed with assertion_compare_can_convert.go and
// assertion_compare_legacy.go
package assert
import (
"reflect"
"testing"
"time"
)
func TestCompare17(t *testing.T) {
type customTime time.Time
for _, currCase := range []struct {
less interface{}
greater interface{}
cType string
}{
{less: time.Now(), greater: time.Now().Add(time.Hour), cType: "time.Time"},
{less: customTime(time.Now()), greater: customTime(time.Now().Add(time.Hour)), cType: "time.Time"},
} {
resLess, isComparable := compare(currCase.less, currCase.greater, reflect.ValueOf(currCase.less).Kind())
if !isComparable {
t.Error("object should be comparable for type " + currCase.cType)
}
if resLess != compareLess {
t.Errorf("object less (%v) should be less than greater (%v) for type "+currCase.cType,
currCase.less, currCase.greater)
}
resGreater, isComparable := compare(currCase.greater, currCase.less, reflect.ValueOf(currCase.less).Kind())
if !isComparable {
t.Error("object are comparable for type " + currCase.cType)
}
if resGreater != compareGreater {
t.Errorf("object greater should be greater than less for type " + currCase.cType)
}
resEqual, isComparable := compare(currCase.less, currCase.less, reflect.ValueOf(currCase.less).Kind())
if !isComparable {
t.Error("object are comparable for type " + currCase.cType)
}
if resEqual != 0 {
t.Errorf("objects should be equal for type " + currCase.cType)
}
}
}

View File

@ -0,0 +1,16 @@
//go:build !go1.17
// +build !go1.17
// TODO: once support for Go 1.16 is dropped, this file can be
// merged/removed with assertion_compare_go1.17_test.go and
// assertion_compare_can_convert.go
package assert
import "reflect"
// Older versions of Go does not have the reflect.Value.CanConvert
// method.
func canConvert(value reflect.Value, to reflect.Type) bool {
return false
}

View File

@ -6,13 +6,9 @@ import (
"reflect"
"runtime"
"testing"
"time"
)
func TestCompare(t *testing.T) {
t.Parallel()
type customString string
type customInt int
type customInt8 int8
type customInt16 int16
@ -25,9 +21,7 @@ func TestCompare(t *testing.T) {
type customUInt64 uint64
type customFloat32 float32
type customFloat64 float64
type customUintptr uintptr
type customTime time.Time
type customBytes []byte
type customString string
for _, currCase := range []struct {
less interface{}
greater interface{}
@ -58,13 +52,6 @@ func TestCompare(t *testing.T) {
{less: customFloat32(1.23), greater: customFloat32(2.23), cType: "float32"},
{less: float64(1.23), greater: float64(2.34), cType: "float64"},
{less: customFloat64(1.23), greater: customFloat64(2.34), cType: "float64"},
{less: uintptr(1), greater: uintptr(2), cType: "uintptr"},
{less: customUintptr(1), greater: customUintptr(2), cType: "uint64"},
{less: time.Now(), greater: time.Now().Add(time.Hour), cType: "time.Time"},
{less: time.Date(2024, 0, 0, 0, 0, 0, 0, time.Local), greater: time.Date(2263, 0, 0, 0, 0, 0, 0, time.Local), cType: "time.Time"},
{less: customTime(time.Now()), greater: customTime(time.Now().Add(time.Hour)), cType: "time.Time"},
{less: []byte{1, 1}, greater: []byte{1, 2}, cType: "[]byte"},
{less: customBytes([]byte{1, 1}), greater: customBytes([]byte{1, 2}), cType: "[]byte"},
} {
resLess, isComparable := compare(currCase.less, currCase.greater, reflect.ValueOf(currCase.less).Kind())
if !isComparable {
@ -129,8 +116,6 @@ func callerName(skip int) string {
}
func TestGreater(t *testing.T) {
t.Parallel()
mockT := new(testing.T)
if !Greater(mockT, 2, 1) {
@ -163,9 +148,6 @@ func TestGreater(t *testing.T) {
{less: uint64(1), greater: uint64(2), msg: `"1" is not greater than "2"`},
{less: float32(1.23), greater: float32(2.34), msg: `"1.23" is not greater than "2.34"`},
{less: float64(1.23), greater: float64(2.34), msg: `"1.23" is not greater than "2.34"`},
{less: uintptr(1), greater: uintptr(2), msg: `"1" is not greater than "2"`},
{less: time.Time{}, greater: time.Time{}.Add(time.Hour), msg: `"0001-01-01 00:00:00 +0000 UTC" is not greater than "0001-01-01 01:00:00 +0000 UTC"`},
{less: []byte{1, 1}, greater: []byte{1, 2}, msg: `"[1 1]" is not greater than "[1 2]"`},
} {
out := &outputT{buf: bytes.NewBuffer(nil)}
False(t, Greater(out, currCase.less, currCase.greater))
@ -175,8 +157,6 @@ func TestGreater(t *testing.T) {
}
func TestGreaterOrEqual(t *testing.T) {
t.Parallel()
mockT := new(testing.T)
if !GreaterOrEqual(mockT, 2, 1) {
@ -209,9 +189,6 @@ func TestGreaterOrEqual(t *testing.T) {
{less: uint64(1), greater: uint64(2), msg: `"1" is not greater than or equal to "2"`},
{less: float32(1.23), greater: float32(2.34), msg: `"1.23" is not greater than or equal to "2.34"`},
{less: float64(1.23), greater: float64(2.34), msg: `"1.23" is not greater than or equal to "2.34"`},
{less: uintptr(1), greater: uintptr(2), msg: `"1" is not greater than or equal to "2"`},
{less: time.Time{}, greater: time.Time{}.Add(time.Hour), msg: `"0001-01-01 00:00:00 +0000 UTC" is not greater than or equal to "0001-01-01 01:00:00 +0000 UTC"`},
{less: []byte{1, 1}, greater: []byte{1, 2}, msg: `"[1 1]" is not greater than or equal to "[1 2]"`},
} {
out := &outputT{buf: bytes.NewBuffer(nil)}
False(t, GreaterOrEqual(out, currCase.less, currCase.greater))
@ -221,8 +198,6 @@ func TestGreaterOrEqual(t *testing.T) {
}
func TestLess(t *testing.T) {
t.Parallel()
mockT := new(testing.T)
if !Less(mockT, 1, 2) {
@ -255,9 +230,6 @@ func TestLess(t *testing.T) {
{less: uint64(1), greater: uint64(2), msg: `"2" is not less than "1"`},
{less: float32(1.23), greater: float32(2.34), msg: `"2.34" is not less than "1.23"`},
{less: float64(1.23), greater: float64(2.34), msg: `"2.34" is not less than "1.23"`},
{less: uintptr(1), greater: uintptr(2), msg: `"2" is not less than "1"`},
{less: time.Time{}, greater: time.Time{}.Add(time.Hour), msg: `"0001-01-01 01:00:00 +0000 UTC" is not less than "0001-01-01 00:00:00 +0000 UTC"`},
{less: []byte{1, 1}, greater: []byte{1, 2}, msg: `"[1 2]" is not less than "[1 1]"`},
} {
out := &outputT{buf: bytes.NewBuffer(nil)}
False(t, Less(out, currCase.greater, currCase.less))
@ -267,8 +239,6 @@ func TestLess(t *testing.T) {
}
func TestLessOrEqual(t *testing.T) {
t.Parallel()
mockT := new(testing.T)
if !LessOrEqual(mockT, 1, 2) {
@ -301,9 +271,6 @@ func TestLessOrEqual(t *testing.T) {
{less: uint64(1), greater: uint64(2), msg: `"2" is not less than or equal to "1"`},
{less: float32(1.23), greater: float32(2.34), msg: `"2.34" is not less than or equal to "1.23"`},
{less: float64(1.23), greater: float64(2.34), msg: `"2.34" is not less than or equal to "1.23"`},
{less: uintptr(1), greater: uintptr(2), msg: `"2" is not less than or equal to "1"`},
{less: time.Time{}, greater: time.Time{}.Add(time.Hour), msg: `"0001-01-01 01:00:00 +0000 UTC" is not less than or equal to "0001-01-01 00:00:00 +0000 UTC"`},
{less: []byte{1, 1}, greater: []byte{1, 2}, msg: `"[1 2]" is not less than or equal to "[1 1]"`},
} {
out := &outputT{buf: bytes.NewBuffer(nil)}
False(t, LessOrEqual(out, currCase.greater, currCase.less))
@ -313,8 +280,6 @@ func TestLessOrEqual(t *testing.T) {
}
func TestPositive(t *testing.T) {
t.Parallel()
mockT := new(testing.T)
if !Positive(mockT, 1) {
@ -354,8 +319,6 @@ func TestPositive(t *testing.T) {
}
func TestNegative(t *testing.T) {
t.Parallel()
mockT := new(testing.T)
if !Negative(mockT, -1) {
@ -395,8 +358,6 @@ func TestNegative(t *testing.T) {
}
func Test_compareTwoValuesDifferentValuesTypes(t *testing.T) {
t.Parallel()
mockT := new(testing.T)
for _, currCase := range []struct {
@ -409,14 +370,12 @@ func Test_compareTwoValuesDifferentValuesTypes(t *testing.T) {
{v1: float64(12), v2: "123"},
{v1: "float(12)", v2: float64(1)},
} {
result := compareTwoValues(mockT, currCase.v1, currCase.v2, []compareResult{compareLess, compareEqual, compareGreater}, "testFailMessage")
False(t, result)
compareResult := compareTwoValues(mockT, currCase.v1, currCase.v2, []CompareType{compareLess, compareEqual, compareGreater}, "testFailMessage")
False(t, compareResult)
}
}
func Test_compareTwoValuesNotComparableValues(t *testing.T) {
t.Parallel()
mockT := new(testing.T)
type CompareStruct struct {
@ -430,48 +389,44 @@ func Test_compareTwoValuesNotComparableValues(t *testing.T) {
{v1: map[string]int{}, v2: map[string]int{}},
{v1: make([]int, 5), v2: make([]int, 5)},
} {
result := compareTwoValues(mockT, currCase.v1, currCase.v2, []compareResult{compareLess, compareEqual, compareGreater}, "testFailMessage")
False(t, result)
compareResult := compareTwoValues(mockT, currCase.v1, currCase.v2, []CompareType{compareLess, compareEqual, compareGreater}, "testFailMessage")
False(t, compareResult)
}
}
func Test_compareTwoValuesCorrectCompareResult(t *testing.T) {
t.Parallel()
mockT := new(testing.T)
for _, currCase := range []struct {
v1 interface{}
v2 interface{}
allowedResults []compareResult
v1 interface{}
v2 interface{}
compareTypes []CompareType
}{
{v1: 1, v2: 2, allowedResults: []compareResult{compareLess}},
{v1: 1, v2: 2, allowedResults: []compareResult{compareLess, compareEqual}},
{v1: 2, v2: 2, allowedResults: []compareResult{compareGreater, compareEqual}},
{v1: 2, v2: 2, allowedResults: []compareResult{compareEqual}},
{v1: 2, v2: 1, allowedResults: []compareResult{compareEqual, compareGreater}},
{v1: 2, v2: 1, allowedResults: []compareResult{compareGreater}},
{v1: 1, v2: 2, compareTypes: []CompareType{compareLess}},
{v1: 1, v2: 2, compareTypes: []CompareType{compareLess, compareEqual}},
{v1: 2, v2: 2, compareTypes: []CompareType{compareGreater, compareEqual}},
{v1: 2, v2: 2, compareTypes: []CompareType{compareEqual}},
{v1: 2, v2: 1, compareTypes: []CompareType{compareEqual, compareGreater}},
{v1: 2, v2: 1, compareTypes: []CompareType{compareGreater}},
} {
result := compareTwoValues(mockT, currCase.v1, currCase.v2, currCase.allowedResults, "testFailMessage")
True(t, result)
compareResult := compareTwoValues(mockT, currCase.v1, currCase.v2, currCase.compareTypes, "testFailMessage")
True(t, compareResult)
}
}
func Test_containsValue(t *testing.T) {
t.Parallel()
for _, currCase := range []struct {
values []compareResult
value compareResult
values []CompareType
value CompareType
result bool
}{
{values: []compareResult{compareGreater}, value: compareGreater, result: true},
{values: []compareResult{compareGreater, compareLess}, value: compareGreater, result: true},
{values: []compareResult{compareGreater, compareLess}, value: compareLess, result: true},
{values: []compareResult{compareGreater, compareLess}, value: compareEqual, result: false},
{values: []CompareType{compareGreater}, value: compareGreater, result: true},
{values: []CompareType{compareGreater, compareLess}, value: compareGreater, result: true},
{values: []CompareType{compareGreater, compareLess}, value: compareLess, result: true},
{values: []CompareType{compareGreater, compareLess}, value: compareEqual, result: false},
} {
result := containsValue(currCase.values, currCase.value)
Equal(t, currCase.result, result)
compareResult := containsValue(currCase.values, currCase.value)
Equal(t, currCase.result, compareResult)
}
}

View File

@ -1,4 +1,7 @@
// Code generated with github.com/stretchr/testify/_codegen; DO NOT EDIT.
/*
* CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen
* THIS FILE MUST NOT BE EDITED BY HAND
*/
package assert
@ -19,9 +22,9 @@ func Conditionf(t TestingT, comp Comparison, msg string, args ...interface{}) bo
// Containsf asserts that the specified string, list(array, slice...) or map contains the
// specified substring or element.
//
// assert.Containsf(t, "Hello World", "World", "error message %s", "formatted")
// assert.Containsf(t, ["Hello", "World"], "World", "error message %s", "formatted")
// assert.Containsf(t, {"Hello": "World"}, "Hello", "error message %s", "formatted")
// assert.Containsf(t, "Hello World", "World", "error message %s", "formatted")
// assert.Containsf(t, ["Hello", "World"], "World", "error message %s", "formatted")
// assert.Containsf(t, {"Hello": "World"}, "Hello", "error message %s", "formatted")
func Containsf(t TestingT, s interface{}, contains interface{}, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
@ -50,19 +53,10 @@ func ElementsMatchf(t TestingT, listA interface{}, listB interface{}, msg string
return ElementsMatch(t, listA, listB, append([]interface{}{msg}, args...)...)
}
// Emptyf asserts that the given value is "empty".
// Emptyf asserts that the specified object is empty. I.e. nil, "", false, 0 or either
// a slice or a channel with len == 0.
//
// [Zero values] are "empty".
//
// Arrays are "empty" if every element is the zero value of the type (stricter than "empty").
//
// Slices, maps and channels with zero length are "empty".
//
// Pointer values are "empty" if the pointer is nil or if the pointed value is "empty".
//
// assert.Emptyf(t, obj, "error message %s", "formatted")
//
// [Zero values]: https://go.dev/ref/spec#The_zero_value
// assert.Emptyf(t, obj, "error message %s", "formatted")
func Emptyf(t TestingT, object interface{}, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
@ -72,7 +66,7 @@ func Emptyf(t TestingT, object interface{}, msg string, args ...interface{}) boo
// Equalf asserts that two objects are equal.
//
// assert.Equalf(t, 123, 123, "error message %s", "formatted")
// assert.Equalf(t, 123, 123, "error message %s", "formatted")
//
// Pointer variable equality is determined based on the equality of the
// referenced values (as opposed to the memory addresses). Function equality
@ -87,8 +81,8 @@ func Equalf(t TestingT, expected interface{}, actual interface{}, msg string, ar
// EqualErrorf asserts that a function returned an error (i.e. not `nil`)
// and that it is equal to the provided error.
//
// actualObj, err := SomeFunction()
// assert.EqualErrorf(t, err, expectedErrorString, "error message %s", "formatted")
// actualObj, err := SomeFunction()
// assert.EqualErrorf(t, err, expectedErrorString, "error message %s", "formatted")
func EqualErrorf(t TestingT, theError error, errString string, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
@ -96,27 +90,10 @@ func EqualErrorf(t TestingT, theError error, errString string, msg string, args
return EqualError(t, theError, errString, append([]interface{}{msg}, args...)...)
}
// EqualExportedValuesf asserts that the types of two objects are equal and their public
// fields are also equal. This is useful for comparing structs that have private fields
// that could potentially differ.
// EqualValuesf asserts that two objects are equal or convertable to the same types
// and equal.
//
// type S struct {
// Exported int
// notExported int
// }
// assert.EqualExportedValuesf(t, S{1, 2}, S{1, 3}, "error message %s", "formatted") => true
// assert.EqualExportedValuesf(t, S{1, 2}, S{2, 3}, "error message %s", "formatted") => false
func EqualExportedValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
}
return EqualExportedValues(t, expected, actual, append([]interface{}{msg}, args...)...)
}
// EqualValuesf asserts that two objects are equal or convertible to the larger
// type and equal.
//
// assert.EqualValuesf(t, uint32(123), int32(123), "error message %s", "formatted")
// assert.EqualValuesf(t, uint32(123), int32(123), "error message %s", "formatted")
func EqualValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
@ -126,8 +103,10 @@ func EqualValuesf(t TestingT, expected interface{}, actual interface{}, msg stri
// Errorf asserts that a function returned an error (i.e. not `nil`).
//
// actualObj, err := SomeFunction()
// assert.Errorf(t, err, "error message %s", "formatted")
// actualObj, err := SomeFunction()
// if assert.Errorf(t, err, "error message %s", "formatted") {
// assert.Equal(t, expectedErrorf, err)
// }
func Errorf(t TestingT, err error, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
@ -147,8 +126,8 @@ func ErrorAsf(t TestingT, err error, target interface{}, msg string, args ...int
// ErrorContainsf asserts that a function returned an error (i.e. not `nil`)
// and that the error contains the specified substring.
//
// actualObj, err := SomeFunction()
// assert.ErrorContainsf(t, err, expectedErrorSubString, "error message %s", "formatted")
// actualObj, err := SomeFunction()
// assert.ErrorContainsf(t, err, expectedErrorSubString, "error message %s", "formatted")
func ErrorContainsf(t TestingT, theError error, contains string, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
@ -168,7 +147,7 @@ func ErrorIsf(t TestingT, err error, target error, msg string, args ...interface
// Eventuallyf asserts that given condition will be met in waitFor time,
// periodically checking target function each tick.
//
// assert.Eventuallyf(t, func() bool { return true; }, time.Second, 10*time.Millisecond, "error message %s", "formatted")
// assert.Eventuallyf(t, func() bool { return true; }, time.Second, 10*time.Millisecond, "error message %s", "formatted")
func Eventuallyf(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
@ -176,34 +155,9 @@ func Eventuallyf(t TestingT, condition func() bool, waitFor time.Duration, tick
return Eventually(t, condition, waitFor, tick, append([]interface{}{msg}, args...)...)
}
// EventuallyWithTf asserts that given condition will be met in waitFor time,
// periodically checking target function each tick. In contrast to Eventually,
// it supplies a CollectT to the condition function, so that the condition
// function can use the CollectT to call other assertions.
// The condition is considered "met" if no errors are raised in a tick.
// The supplied CollectT collects all errors from one tick (if there are any).
// If the condition is not met before waitFor, the collected errors of
// the last tick are copied to t.
//
// externalValue := false
// go func() {
// time.Sleep(8*time.Second)
// externalValue = true
// }()
// assert.EventuallyWithTf(t, func(c *assert.CollectT, "error message %s", "formatted") {
// // add assertions as needed; any assertion failure will fail the current tick
// assert.True(c, externalValue, "expected 'externalValue' to be true")
// }, 10*time.Second, 1*time.Second, "external state has not changed to 'true'; still false")
func EventuallyWithTf(t TestingT, condition func(collect *CollectT), waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
}
return EventuallyWithT(t, condition, waitFor, tick, append([]interface{}{msg}, args...)...)
}
// Exactlyf asserts that two objects are equal in value and type.
//
// assert.Exactlyf(t, int32(123), int64(123), "error message %s", "formatted")
// assert.Exactlyf(t, int32(123), int64(123), "error message %s", "formatted")
func Exactlyf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
@ -229,7 +183,7 @@ func FailNowf(t TestingT, failureMessage string, msg string, args ...interface{}
// Falsef asserts that the specified value is false.
//
// assert.Falsef(t, myBool, "error message %s", "formatted")
// assert.Falsef(t, myBool, "error message %s", "formatted")
func Falsef(t TestingT, value bool, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
@ -248,9 +202,9 @@ func FileExistsf(t TestingT, path string, msg string, args ...interface{}) bool
// Greaterf asserts that the first element is greater than the second
//
// assert.Greaterf(t, 2, 1, "error message %s", "formatted")
// assert.Greaterf(t, float64(2), float64(1), "error message %s", "formatted")
// assert.Greaterf(t, "b", "a", "error message %s", "formatted")
// assert.Greaterf(t, 2, 1, "error message %s", "formatted")
// assert.Greaterf(t, float64(2), float64(1), "error message %s", "formatted")
// assert.Greaterf(t, "b", "a", "error message %s", "formatted")
func Greaterf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
@ -260,10 +214,10 @@ func Greaterf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...in
// GreaterOrEqualf asserts that the first element is greater than or equal to the second
//
// assert.GreaterOrEqualf(t, 2, 1, "error message %s", "formatted")
// assert.GreaterOrEqualf(t, 2, 2, "error message %s", "formatted")
// assert.GreaterOrEqualf(t, "b", "a", "error message %s", "formatted")
// assert.GreaterOrEqualf(t, "b", "b", "error message %s", "formatted")
// assert.GreaterOrEqualf(t, 2, 1, "error message %s", "formatted")
// assert.GreaterOrEqualf(t, 2, 2, "error message %s", "formatted")
// assert.GreaterOrEqualf(t, "b", "a", "error message %s", "formatted")
// assert.GreaterOrEqualf(t, "b", "b", "error message %s", "formatted")
func GreaterOrEqualf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
@ -274,7 +228,7 @@ func GreaterOrEqualf(t TestingT, e1 interface{}, e2 interface{}, msg string, arg
// HTTPBodyContainsf asserts that a specified handler returns a
// body that contains a string.
//
// assert.HTTPBodyContainsf(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
// assert.HTTPBodyContainsf(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
//
// Returns whether the assertion was successful (true) or not (false).
func HTTPBodyContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool {
@ -287,7 +241,7 @@ func HTTPBodyContainsf(t TestingT, handler http.HandlerFunc, method string, url
// HTTPBodyNotContainsf asserts that a specified handler returns a
// body that does not contain a string.
//
// assert.HTTPBodyNotContainsf(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
// assert.HTTPBodyNotContainsf(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
//
// Returns whether the assertion was successful (true) or not (false).
func HTTPBodyNotContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool {
@ -299,7 +253,7 @@ func HTTPBodyNotContainsf(t TestingT, handler http.HandlerFunc, method string, u
// HTTPErrorf asserts that a specified handler returns an error status code.
//
// assert.HTTPErrorf(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}}
// assert.HTTPErrorf(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}}
//
// Returns whether the assertion was successful (true) or not (false).
func HTTPErrorf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool {
@ -311,7 +265,7 @@ func HTTPErrorf(t TestingT, handler http.HandlerFunc, method string, url string,
// HTTPRedirectf asserts that a specified handler returns a redirect status code.
//
// assert.HTTPRedirectf(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}}
// assert.HTTPRedirectf(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}}
//
// Returns whether the assertion was successful (true) or not (false).
func HTTPRedirectf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool {
@ -323,7 +277,7 @@ func HTTPRedirectf(t TestingT, handler http.HandlerFunc, method string, url stri
// HTTPStatusCodef asserts that a specified handler returns a specified status code.
//
// assert.HTTPStatusCodef(t, myHandler, "GET", "/notImplemented", nil, 501, "error message %s", "formatted")
// assert.HTTPStatusCodef(t, myHandler, "GET", "/notImplemented", nil, 501, "error message %s", "formatted")
//
// Returns whether the assertion was successful (true) or not (false).
func HTTPStatusCodef(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, statuscode int, msg string, args ...interface{}) bool {
@ -335,7 +289,7 @@ func HTTPStatusCodef(t TestingT, handler http.HandlerFunc, method string, url st
// HTTPSuccessf asserts that a specified handler returns a success status code.
//
// assert.HTTPSuccessf(t, myHandler, "POST", "http://www.google.com", nil, "error message %s", "formatted")
// assert.HTTPSuccessf(t, myHandler, "POST", "http://www.google.com", nil, "error message %s", "formatted")
//
// Returns whether the assertion was successful (true) or not (false).
func HTTPSuccessf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool {
@ -347,7 +301,7 @@ func HTTPSuccessf(t TestingT, handler http.HandlerFunc, method string, url strin
// Implementsf asserts that an object is implemented by the specified interface.
//
// assert.Implementsf(t, (*MyInterface)(nil), new(MyObject), "error message %s", "formatted")
// assert.Implementsf(t, (*MyInterface)(nil), new(MyObject), "error message %s", "formatted")
func Implementsf(t TestingT, interfaceObject interface{}, object interface{}, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
@ -357,7 +311,7 @@ func Implementsf(t TestingT, interfaceObject interface{}, object interface{}, ms
// InDeltaf asserts that the two numerals are within delta of each other.
//
// assert.InDeltaf(t, math.Pi, 22/7.0, 0.01, "error message %s", "formatted")
// assert.InDeltaf(t, math.Pi, 22/7.0, 0.01, "error message %s", "formatted")
func InDeltaf(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
@ -399,9 +353,9 @@ func InEpsilonSlicef(t TestingT, expected interface{}, actual interface{}, epsil
// IsDecreasingf asserts that the collection is decreasing
//
// assert.IsDecreasingf(t, []int{2, 1, 0}, "error message %s", "formatted")
// assert.IsDecreasingf(t, []float{2, 1}, "error message %s", "formatted")
// assert.IsDecreasingf(t, []string{"b", "a"}, "error message %s", "formatted")
// assert.IsDecreasingf(t, []int{2, 1, 0}, "error message %s", "formatted")
// assert.IsDecreasingf(t, []float{2, 1}, "error message %s", "formatted")
// assert.IsDecreasingf(t, []string{"b", "a"}, "error message %s", "formatted")
func IsDecreasingf(t TestingT, object interface{}, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
@ -411,9 +365,9 @@ func IsDecreasingf(t TestingT, object interface{}, msg string, args ...interface
// IsIncreasingf asserts that the collection is increasing
//
// assert.IsIncreasingf(t, []int{1, 2, 3}, "error message %s", "formatted")
// assert.IsIncreasingf(t, []float{1, 2}, "error message %s", "formatted")
// assert.IsIncreasingf(t, []string{"a", "b"}, "error message %s", "formatted")
// assert.IsIncreasingf(t, []int{1, 2, 3}, "error message %s", "formatted")
// assert.IsIncreasingf(t, []float{1, 2}, "error message %s", "formatted")
// assert.IsIncreasingf(t, []string{"a", "b"}, "error message %s", "formatted")
func IsIncreasingf(t TestingT, object interface{}, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
@ -423,9 +377,9 @@ func IsIncreasingf(t TestingT, object interface{}, msg string, args ...interface
// IsNonDecreasingf asserts that the collection is not decreasing
//
// assert.IsNonDecreasingf(t, []int{1, 1, 2}, "error message %s", "formatted")
// assert.IsNonDecreasingf(t, []float{1, 2}, "error message %s", "formatted")
// assert.IsNonDecreasingf(t, []string{"a", "b"}, "error message %s", "formatted")
// assert.IsNonDecreasingf(t, []int{1, 1, 2}, "error message %s", "formatted")
// assert.IsNonDecreasingf(t, []float{1, 2}, "error message %s", "formatted")
// assert.IsNonDecreasingf(t, []string{"a", "b"}, "error message %s", "formatted")
func IsNonDecreasingf(t TestingT, object interface{}, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
@ -435,9 +389,9 @@ func IsNonDecreasingf(t TestingT, object interface{}, msg string, args ...interf
// IsNonIncreasingf asserts that the collection is not increasing
//
// assert.IsNonIncreasingf(t, []int{2, 1, 1}, "error message %s", "formatted")
// assert.IsNonIncreasingf(t, []float{2, 1}, "error message %s", "formatted")
// assert.IsNonIncreasingf(t, []string{"b", "a"}, "error message %s", "formatted")
// assert.IsNonIncreasingf(t, []int{2, 1, 1}, "error message %s", "formatted")
// assert.IsNonIncreasingf(t, []float{2, 1}, "error message %s", "formatted")
// assert.IsNonIncreasingf(t, []string{"b", "a"}, "error message %s", "formatted")
func IsNonIncreasingf(t TestingT, object interface{}, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
@ -445,19 +399,7 @@ func IsNonIncreasingf(t TestingT, object interface{}, msg string, args ...interf
return IsNonIncreasing(t, object, append([]interface{}{msg}, args...)...)
}
// IsNotTypef asserts that the specified objects are not of the same type.
//
// assert.IsNotTypef(t, &NotMyStruct{}, &MyStruct{}, "error message %s", "formatted")
func IsNotTypef(t TestingT, theType interface{}, object interface{}, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
}
return IsNotType(t, theType, object, append([]interface{}{msg}, args...)...)
}
// IsTypef asserts that the specified objects are of the same type.
//
// assert.IsTypef(t, &MyStruct{}, &MyStruct{}, "error message %s", "formatted")
func IsTypef(t TestingT, expectedType interface{}, object interface{}, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
@ -467,7 +409,7 @@ func IsTypef(t TestingT, expectedType interface{}, object interface{}, msg strin
// JSONEqf asserts that two JSON strings are equivalent.
//
// assert.JSONEqf(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted")
// assert.JSONEqf(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted")
func JSONEqf(t TestingT, expected string, actual string, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
@ -478,7 +420,7 @@ func JSONEqf(t TestingT, expected string, actual string, msg string, args ...int
// Lenf asserts that the specified object has specific length.
// Lenf also fails if the object has a type that len() not accept.
//
// assert.Lenf(t, mySlice, 3, "error message %s", "formatted")
// assert.Lenf(t, mySlice, 3, "error message %s", "formatted")
func Lenf(t TestingT, object interface{}, length int, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
@ -488,9 +430,9 @@ func Lenf(t TestingT, object interface{}, length int, msg string, args ...interf
// Lessf asserts that the first element is less than the second
//
// assert.Lessf(t, 1, 2, "error message %s", "formatted")
// assert.Lessf(t, float64(1), float64(2), "error message %s", "formatted")
// assert.Lessf(t, "a", "b", "error message %s", "formatted")
// assert.Lessf(t, 1, 2, "error message %s", "formatted")
// assert.Lessf(t, float64(1), float64(2), "error message %s", "formatted")
// assert.Lessf(t, "a", "b", "error message %s", "formatted")
func Lessf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
@ -500,10 +442,10 @@ func Lessf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...inter
// LessOrEqualf asserts that the first element is less than or equal to the second
//
// assert.LessOrEqualf(t, 1, 2, "error message %s", "formatted")
// assert.LessOrEqualf(t, 2, 2, "error message %s", "formatted")
// assert.LessOrEqualf(t, "a", "b", "error message %s", "formatted")
// assert.LessOrEqualf(t, "b", "b", "error message %s", "formatted")
// assert.LessOrEqualf(t, 1, 2, "error message %s", "formatted")
// assert.LessOrEqualf(t, 2, 2, "error message %s", "formatted")
// assert.LessOrEqualf(t, "a", "b", "error message %s", "formatted")
// assert.LessOrEqualf(t, "b", "b", "error message %s", "formatted")
func LessOrEqualf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
@ -513,8 +455,8 @@ func LessOrEqualf(t TestingT, e1 interface{}, e2 interface{}, msg string, args .
// Negativef asserts that the specified element is negative
//
// assert.Negativef(t, -1, "error message %s", "formatted")
// assert.Negativef(t, -1.23, "error message %s", "formatted")
// assert.Negativef(t, -1, "error message %s", "formatted")
// assert.Negativef(t, -1.23, "error message %s", "formatted")
func Negativef(t TestingT, e interface{}, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
@ -525,7 +467,7 @@ func Negativef(t TestingT, e interface{}, msg string, args ...interface{}) bool
// Neverf asserts that the given condition doesn't satisfy in waitFor time,
// periodically checking the target function each tick.
//
// assert.Neverf(t, func() bool { return false; }, time.Second, 10*time.Millisecond, "error message %s", "formatted")
// assert.Neverf(t, func() bool { return false; }, time.Second, 10*time.Millisecond, "error message %s", "formatted")
func Neverf(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
@ -535,7 +477,7 @@ func Neverf(t TestingT, condition func() bool, waitFor time.Duration, tick time.
// Nilf asserts that the specified object is nil.
//
// assert.Nilf(t, err, "error message %s", "formatted")
// assert.Nilf(t, err, "error message %s", "formatted")
func Nilf(t TestingT, object interface{}, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
@ -554,10 +496,10 @@ func NoDirExistsf(t TestingT, path string, msg string, args ...interface{}) bool
// NoErrorf asserts that a function returned no error (i.e. `nil`).
//
// actualObj, err := SomeFunction()
// if assert.NoErrorf(t, err, "error message %s", "formatted") {
// assert.Equal(t, expectedObj, actualObj)
// }
// actualObj, err := SomeFunction()
// if assert.NoErrorf(t, err, "error message %s", "formatted") {
// assert.Equal(t, expectedObj, actualObj)
// }
func NoErrorf(t TestingT, err error, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
@ -577,9 +519,9 @@ func NoFileExistsf(t TestingT, path string, msg string, args ...interface{}) boo
// NotContainsf asserts that the specified string, list(array, slice...) or map does NOT contain the
// specified substring or element.
//
// assert.NotContainsf(t, "Hello World", "Earth", "error message %s", "formatted")
// assert.NotContainsf(t, ["Hello", "World"], "Earth", "error message %s", "formatted")
// assert.NotContainsf(t, {"Hello": "World"}, "Earth", "error message %s", "formatted")
// assert.NotContainsf(t, "Hello World", "Earth", "error message %s", "formatted")
// assert.NotContainsf(t, ["Hello", "World"], "Earth", "error message %s", "formatted")
// assert.NotContainsf(t, {"Hello": "World"}, "Earth", "error message %s", "formatted")
func NotContainsf(t TestingT, s interface{}, contains interface{}, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
@ -587,28 +529,12 @@ func NotContainsf(t TestingT, s interface{}, contains interface{}, msg string, a
return NotContains(t, s, contains, append([]interface{}{msg}, args...)...)
}
// NotElementsMatchf asserts that the specified listA(array, slice...) is NOT equal to specified
// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements,
// the number of appearances of each of them in both lists should not match.
// This is an inverse of ElementsMatch.
// NotEmptyf asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either
// a slice or a channel with len == 0.
//
// assert.NotElementsMatchf(t, [1, 1, 2, 3], [1, 1, 2, 3], "error message %s", "formatted") -> false
//
// assert.NotElementsMatchf(t, [1, 1, 2, 3], [1, 2, 3], "error message %s", "formatted") -> true
//
// assert.NotElementsMatchf(t, [1, 2, 3], [1, 2, 4], "error message %s", "formatted") -> true
func NotElementsMatchf(t TestingT, listA interface{}, listB interface{}, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
}
return NotElementsMatch(t, listA, listB, append([]interface{}{msg}, args...)...)
}
// NotEmptyf asserts that the specified object is NOT [Empty].
//
// if assert.NotEmptyf(t, obj, "error message %s", "formatted") {
// assert.Equal(t, "two", obj[1])
// }
// if assert.NotEmptyf(t, obj, "error message %s", "formatted") {
// assert.Equal(t, "two", obj[1])
// }
func NotEmptyf(t TestingT, object interface{}, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
@ -618,7 +544,7 @@ func NotEmptyf(t TestingT, object interface{}, msg string, args ...interface{})
// NotEqualf asserts that the specified values are NOT equal.
//
// assert.NotEqualf(t, obj1, obj2, "error message %s", "formatted")
// assert.NotEqualf(t, obj1, obj2, "error message %s", "formatted")
//
// Pointer variable equality is determined based on the equality of the
// referenced values (as opposed to the memory addresses).
@ -631,7 +557,7 @@ func NotEqualf(t TestingT, expected interface{}, actual interface{}, msg string,
// NotEqualValuesf asserts that two objects are not equal even when converted to the same type
//
// assert.NotEqualValuesf(t, obj1, obj2, "error message %s", "formatted")
// assert.NotEqualValuesf(t, obj1, obj2, "error message %s", "formatted")
func NotEqualValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
@ -639,16 +565,7 @@ func NotEqualValuesf(t TestingT, expected interface{}, actual interface{}, msg s
return NotEqualValues(t, expected, actual, append([]interface{}{msg}, args...)...)
}
// NotErrorAsf asserts that none of the errors in err's chain matches target,
// but if so, sets target to that error value.
func NotErrorAsf(t TestingT, err error, target interface{}, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
}
return NotErrorAs(t, err, target, append([]interface{}{msg}, args...)...)
}
// NotErrorIsf asserts that none of the errors in err's chain matches target.
// NotErrorIsf asserts that at none of the errors in err's chain matches target.
// This is a wrapper for errors.Is.
func NotErrorIsf(t TestingT, err error, target error, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
@ -657,19 +574,9 @@ func NotErrorIsf(t TestingT, err error, target error, msg string, args ...interf
return NotErrorIs(t, err, target, append([]interface{}{msg}, args...)...)
}
// NotImplementsf asserts that an object does not implement the specified interface.
//
// assert.NotImplementsf(t, (*MyInterface)(nil), new(MyObject), "error message %s", "formatted")
func NotImplementsf(t TestingT, interfaceObject interface{}, object interface{}, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
}
return NotImplements(t, interfaceObject, object, append([]interface{}{msg}, args...)...)
}
// NotNilf asserts that the specified object is not nil.
//
// assert.NotNilf(t, err, "error message %s", "formatted")
// assert.NotNilf(t, err, "error message %s", "formatted")
func NotNilf(t TestingT, object interface{}, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
@ -679,7 +586,7 @@ func NotNilf(t TestingT, object interface{}, msg string, args ...interface{}) bo
// NotPanicsf asserts that the code inside the specified PanicTestFunc does NOT panic.
//
// assert.NotPanicsf(t, func(){ RemainCalm() }, "error message %s", "formatted")
// assert.NotPanicsf(t, func(){ RemainCalm() }, "error message %s", "formatted")
func NotPanicsf(t TestingT, f PanicTestFunc, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
@ -689,8 +596,8 @@ func NotPanicsf(t TestingT, f PanicTestFunc, msg string, args ...interface{}) bo
// NotRegexpf asserts that a specified regexp does not match a string.
//
// assert.NotRegexpf(t, regexp.MustCompile("starts"), "it's starting", "error message %s", "formatted")
// assert.NotRegexpf(t, "^start", "it's not starting", "error message %s", "formatted")
// assert.NotRegexpf(t, regexp.MustCompile("starts"), "it's starting", "error message %s", "formatted")
// assert.NotRegexpf(t, "^start", "it's not starting", "error message %s", "formatted")
func NotRegexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
@ -700,7 +607,7 @@ func NotRegexpf(t TestingT, rx interface{}, str interface{}, msg string, args ..
// NotSamef asserts that two pointers do not reference the same object.
//
// assert.NotSamef(t, ptr1, ptr2, "error message %s", "formatted")
// assert.NotSamef(t, ptr1, ptr2, "error message %s", "formatted")
//
// Both arguments must be pointer variables. Pointer variable sameness is
// determined based on the equality of both type and value.
@ -711,15 +618,10 @@ func NotSamef(t TestingT, expected interface{}, actual interface{}, msg string,
return NotSame(t, expected, actual, append([]interface{}{msg}, args...)...)
}
// NotSubsetf asserts that the list (array, slice, or map) does NOT contain all
// elements given in the subset (array, slice, or map).
// Map elements are key-value pairs unless compared with an array or slice where
// only the map key is evaluated.
// NotSubsetf asserts that the specified list(array, slice...) contains not all
// elements given in the specified subset(array, slice...).
//
// assert.NotSubsetf(t, [1, 3, 4], [1, 2], "error message %s", "formatted")
// assert.NotSubsetf(t, {"x": 1, "y": 2}, {"z": 3}, "error message %s", "formatted")
// assert.NotSubsetf(t, [1, 3, 4], {1: "one", 2: "two"}, "error message %s", "formatted")
// assert.NotSubsetf(t, {"x": 1, "y": 2}, ["z"], "error message %s", "formatted")
// assert.NotSubsetf(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted")
func NotSubsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
@ -737,7 +639,7 @@ func NotZerof(t TestingT, i interface{}, msg string, args ...interface{}) bool {
// Panicsf asserts that the code inside the specified PanicTestFunc panics.
//
// assert.Panicsf(t, func(){ GoCrazy() }, "error message %s", "formatted")
// assert.Panicsf(t, func(){ GoCrazy() }, "error message %s", "formatted")
func Panicsf(t TestingT, f PanicTestFunc, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
@ -749,7 +651,7 @@ func Panicsf(t TestingT, f PanicTestFunc, msg string, args ...interface{}) bool
// panics, and that the recovered panic value is an error that satisfies the
// EqualError comparison.
//
// assert.PanicsWithErrorf(t, "crazy error", func(){ GoCrazy() }, "error message %s", "formatted")
// assert.PanicsWithErrorf(t, "crazy error", func(){ GoCrazy() }, "error message %s", "formatted")
func PanicsWithErrorf(t TestingT, errString string, f PanicTestFunc, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
@ -760,7 +662,7 @@ func PanicsWithErrorf(t TestingT, errString string, f PanicTestFunc, msg string,
// PanicsWithValuef asserts that the code inside the specified PanicTestFunc panics, and that
// the recovered panic value equals the expected panic value.
//
// assert.PanicsWithValuef(t, "crazy error", func(){ GoCrazy() }, "error message %s", "formatted")
// assert.PanicsWithValuef(t, "crazy error", func(){ GoCrazy() }, "error message %s", "formatted")
func PanicsWithValuef(t TestingT, expected interface{}, f PanicTestFunc, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
@ -770,8 +672,8 @@ func PanicsWithValuef(t TestingT, expected interface{}, f PanicTestFunc, msg str
// Positivef asserts that the specified element is positive
//
// assert.Positivef(t, 1, "error message %s", "formatted")
// assert.Positivef(t, 1.23, "error message %s", "formatted")
// assert.Positivef(t, 1, "error message %s", "formatted")
// assert.Positivef(t, 1.23, "error message %s", "formatted")
func Positivef(t TestingT, e interface{}, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
@ -781,8 +683,8 @@ func Positivef(t TestingT, e interface{}, msg string, args ...interface{}) bool
// Regexpf asserts that a specified regexp matches a string.
//
// assert.Regexpf(t, regexp.MustCompile("start"), "it's starting", "error message %s", "formatted")
// assert.Regexpf(t, "start...$", "it's not starting", "error message %s", "formatted")
// assert.Regexpf(t, regexp.MustCompile("start"), "it's starting", "error message %s", "formatted")
// assert.Regexpf(t, "start...$", "it's not starting", "error message %s", "formatted")
func Regexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
@ -792,7 +694,7 @@ func Regexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...in
// Samef asserts that two pointers reference the same object.
//
// assert.Samef(t, ptr1, ptr2, "error message %s", "formatted")
// assert.Samef(t, ptr1, ptr2, "error message %s", "formatted")
//
// Both arguments must be pointer variables. Pointer variable sameness is
// determined based on the equality of both type and value.
@ -803,15 +705,10 @@ func Samef(t TestingT, expected interface{}, actual interface{}, msg string, arg
return Same(t, expected, actual, append([]interface{}{msg}, args...)...)
}
// Subsetf asserts that the list (array, slice, or map) contains all elements
// given in the subset (array, slice, or map).
// Map elements are key-value pairs unless compared with an array or slice where
// only the map key is evaluated.
// Subsetf asserts that the specified list(array, slice...) contains all
// elements given in the specified subset(array, slice...).
//
// assert.Subsetf(t, [1, 2, 3], [1, 2], "error message %s", "formatted")
// assert.Subsetf(t, {"x": 1, "y": 2}, {"x": 1}, "error message %s", "formatted")
// assert.Subsetf(t, [1, 2, 3], {1: "one", 2: "two"}, "error message %s", "formatted")
// assert.Subsetf(t, {"x": 1, "y": 2}, ["x"], "error message %s", "formatted")
// assert.Subsetf(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted")
func Subsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
@ -821,7 +718,7 @@ func Subsetf(t TestingT, list interface{}, subset interface{}, msg string, args
// Truef asserts that the specified value is true.
//
// assert.Truef(t, myBool, "error message %s", "formatted")
// assert.Truef(t, myBool, "error message %s", "formatted")
func Truef(t TestingT, value bool, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
@ -831,7 +728,7 @@ func Truef(t TestingT, value bool, msg string, args ...interface{}) bool {
// WithinDurationf asserts that the two times are within duration delta of each other.
//
// assert.WithinDurationf(t, time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted")
// assert.WithinDurationf(t, time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted")
func WithinDurationf(t TestingT, expected time.Time, actual time.Time, delta time.Duration, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
@ -839,16 +736,6 @@ func WithinDurationf(t TestingT, expected time.Time, actual time.Time, delta tim
return WithinDuration(t, expected, actual, delta, append([]interface{}{msg}, args...)...)
}
// WithinRangef asserts that a time is within a time range (inclusive).
//
// assert.WithinRangef(t, time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second), "error message %s", "formatted")
func WithinRangef(t TestingT, actual time.Time, start time.Time, end time.Time, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
}
return WithinRange(t, actual, start, end, append([]interface{}{msg}, args...)...)
}
// YAMLEqf asserts that two YAML strings are equivalent.
func YAMLEqf(t TestingT, expected string, actual string, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {

File diff suppressed because it is too large Load Diff

View File

@ -6,7 +6,7 @@ import (
)
// isOrdered checks that collection contains orderable elements.
func isOrdered(t TestingT, object interface{}, allowedComparesResults []compareResult, failMessage string, msgAndArgs ...interface{}) bool {
func isOrdered(t TestingT, object interface{}, allowedComparesResults []CompareType, failMessage string, msgAndArgs ...interface{}) bool {
objKind := reflect.TypeOf(object).Kind()
if objKind != reflect.Slice && objKind != reflect.Array {
return false
@ -33,7 +33,7 @@ func isOrdered(t TestingT, object interface{}, allowedComparesResults []compareR
compareResult, isComparable := compare(prevValueInterface, valueInterface, firstValueKind)
if !isComparable {
return Fail(t, fmt.Sprintf(`Can not compare type "%T" and "%T"`, value, prevValue), msgAndArgs...)
return Fail(t, fmt.Sprintf("Can not compare type \"%s\" and \"%s\"", reflect.TypeOf(value), reflect.TypeOf(prevValue)), msgAndArgs...)
}
if !containsValue(allowedComparesResults, compareResult) {
@ -46,36 +46,36 @@ func isOrdered(t TestingT, object interface{}, allowedComparesResults []compareR
// IsIncreasing asserts that the collection is increasing
//
// assert.IsIncreasing(t, []int{1, 2, 3})
// assert.IsIncreasing(t, []float{1, 2})
// assert.IsIncreasing(t, []string{"a", "b"})
// assert.IsIncreasing(t, []int{1, 2, 3})
// assert.IsIncreasing(t, []float{1, 2})
// assert.IsIncreasing(t, []string{"a", "b"})
func IsIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
return isOrdered(t, object, []compareResult{compareLess}, "\"%v\" is not less than \"%v\"", msgAndArgs...)
return isOrdered(t, object, []CompareType{compareLess}, "\"%v\" is not less than \"%v\"", msgAndArgs...)
}
// IsNonIncreasing asserts that the collection is not increasing
//
// assert.IsNonIncreasing(t, []int{2, 1, 1})
// assert.IsNonIncreasing(t, []float{2, 1})
// assert.IsNonIncreasing(t, []string{"b", "a"})
// assert.IsNonIncreasing(t, []int{2, 1, 1})
// assert.IsNonIncreasing(t, []float{2, 1})
// assert.IsNonIncreasing(t, []string{"b", "a"})
func IsNonIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
return isOrdered(t, object, []compareResult{compareEqual, compareGreater}, "\"%v\" is not greater than or equal to \"%v\"", msgAndArgs...)
return isOrdered(t, object, []CompareType{compareEqual, compareGreater}, "\"%v\" is not greater than or equal to \"%v\"", msgAndArgs...)
}
// IsDecreasing asserts that the collection is decreasing
//
// assert.IsDecreasing(t, []int{2, 1, 0})
// assert.IsDecreasing(t, []float{2, 1})
// assert.IsDecreasing(t, []string{"b", "a"})
// assert.IsDecreasing(t, []int{2, 1, 0})
// assert.IsDecreasing(t, []float{2, 1})
// assert.IsDecreasing(t, []string{"b", "a"})
func IsDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
return isOrdered(t, object, []compareResult{compareGreater}, "\"%v\" is not greater than \"%v\"", msgAndArgs...)
return isOrdered(t, object, []CompareType{compareGreater}, "\"%v\" is not greater than \"%v\"", msgAndArgs...)
}
// IsNonDecreasing asserts that the collection is not decreasing
//
// assert.IsNonDecreasing(t, []int{1, 1, 2})
// assert.IsNonDecreasing(t, []float{1, 2})
// assert.IsNonDecreasing(t, []string{"a", "b"})
// assert.IsNonDecreasing(t, []int{1, 1, 2})
// assert.IsNonDecreasing(t, []float{1, 2})
// assert.IsNonDecreasing(t, []string{"a", "b"})
func IsNonDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
return isOrdered(t, object, []compareResult{compareLess, compareEqual}, "\"%v\" is not less than or equal to \"%v\"", msgAndArgs...)
return isOrdered(t, object, []CompareType{compareLess, compareEqual}, "\"%v\" is not less than or equal to \"%v\"", msgAndArgs...)
}

View File

@ -6,8 +6,6 @@ import (
)
func TestIsIncreasing(t *testing.T) {
t.Parallel()
mockT := new(testing.T)
if !IsIncreasing(mockT, []int{1, 2}) {
@ -53,8 +51,6 @@ func TestIsIncreasing(t *testing.T) {
}
func TestIsNonIncreasing(t *testing.T) {
t.Parallel()
mockT := new(testing.T)
if !IsNonIncreasing(mockT, []int{2, 1}) {
@ -100,8 +96,6 @@ func TestIsNonIncreasing(t *testing.T) {
}
func TestIsDecreasing(t *testing.T) {
t.Parallel()
mockT := new(testing.T)
if !IsDecreasing(mockT, []int{2, 1}) {
@ -147,8 +141,6 @@ func TestIsDecreasing(t *testing.T) {
}
func TestIsNonDecreasing(t *testing.T) {
t.Parallel()
mockT := new(testing.T)
if !IsNonDecreasing(mockT, []int{1, 2}) {
@ -194,8 +186,6 @@ func TestIsNonDecreasing(t *testing.T) {
}
func TestOrderingMsgAndArgsForwarding(t *testing.T) {
t.Parallel()
msgAndArgs := []interface{}{"format %s %x", "this", 0xc001}
expectedOutput := "format this c001\n"
collection := []int{1, 2, 1}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,44 +1,39 @@
// Package assert provides a set of comprehensive testing tools for use with the normal Go testing system.
//
// # Note
//
// All functions in this package return a bool value indicating whether the assertion has passed.
//
// # Example Usage
// Example Usage
//
// The following is a complete example using assert in a standard test function:
// import (
// "testing"
// "github.com/stretchr/testify/assert"
// )
//
// import (
// "testing"
// "github.com/stretchr/testify/assert"
// )
// func TestSomething(t *testing.T) {
//
// func TestSomething(t *testing.T) {
// var a string = "Hello"
// var b string = "Hello"
//
// var a string = "Hello"
// var b string = "Hello"
// assert.Equal(t, a, b, "The two words should be the same.")
//
// assert.Equal(t, a, b, "The two words should be the same.")
//
// }
// }
//
// if you assert many times, use the format below:
//
// import (
// "testing"
// "github.com/stretchr/testify/assert"
// )
// import (
// "testing"
// "github.com/stretchr/testify/assert"
// )
//
// func TestSomething(t *testing.T) {
// assert := assert.New(t)
// func TestSomething(t *testing.T) {
// assert := assert.New(t)
//
// var a string = "Hello"
// var b string = "Hello"
// var a string = "Hello"
// var b string = "Hello"
//
// assert.Equal(a, b, "The two words should be the same.")
// }
// assert.Equal(a, b, "The two words should be the same.")
// }
//
// # Assertions
// Assertions
//
// Assertions allow you to easily write test code, and are global funcs in the `assert` package.
// All assertion functions take, as the first argument, the `*testing.T` object provided by the

View File

@ -8,8 +8,6 @@ import (
)
func TestImplementsWrapper(t *testing.T) {
t.Parallel()
assert := New(new(testing.T))
if !assert.Implements((*AssertionTesterInterface)(nil), new(AssertionTesterConformingObject)) {
@ -21,8 +19,6 @@ func TestImplementsWrapper(t *testing.T) {
}
func TestIsTypeWrapper(t *testing.T) {
t.Parallel()
assert := New(new(testing.T))
if !assert.IsType(new(AssertionTesterConformingObject), new(AssertionTesterConformingObject)) {
@ -35,8 +31,6 @@ func TestIsTypeWrapper(t *testing.T) {
}
func TestEqualWrapper(t *testing.T) {
t.Parallel()
assert := New(new(testing.T))
if !assert.Equal("Hello World", "Hello World") {
@ -57,8 +51,6 @@ func TestEqualWrapper(t *testing.T) {
}
func TestEqualValuesWrapper(t *testing.T) {
t.Parallel()
assert := New(new(testing.T))
if !assert.EqualValues(uint32(10), int32(10)) {
@ -67,8 +59,6 @@ func TestEqualValuesWrapper(t *testing.T) {
}
func TestNotNilWrapper(t *testing.T) {
t.Parallel()
assert := New(new(testing.T))
if !assert.NotNil(new(AssertionTesterConformingObject)) {
@ -81,8 +71,6 @@ func TestNotNilWrapper(t *testing.T) {
}
func TestNilWrapper(t *testing.T) {
t.Parallel()
assert := New(new(testing.T))
if !assert.Nil(nil) {
@ -95,8 +83,6 @@ func TestNilWrapper(t *testing.T) {
}
func TestTrueWrapper(t *testing.T) {
t.Parallel()
assert := New(new(testing.T))
if !assert.True(true) {
@ -109,8 +95,6 @@ func TestTrueWrapper(t *testing.T) {
}
func TestFalseWrapper(t *testing.T) {
t.Parallel()
assert := New(new(testing.T))
if !assert.False(false) {
@ -123,8 +107,6 @@ func TestFalseWrapper(t *testing.T) {
}
func TestExactlyWrapper(t *testing.T) {
t.Parallel()
assert := New(new(testing.T))
a := float32(1)
@ -152,7 +134,6 @@ func TestExactlyWrapper(t *testing.T) {
}
func TestNotEqualWrapper(t *testing.T) {
t.Parallel()
assert := New(new(testing.T))
@ -174,7 +155,6 @@ func TestNotEqualWrapper(t *testing.T) {
}
func TestNotEqualValuesWrapper(t *testing.T) {
t.Parallel()
assert := New(new(testing.T))
@ -199,7 +179,6 @@ func TestNotEqualValuesWrapper(t *testing.T) {
}
func TestContainsWrapper(t *testing.T) {
t.Parallel()
assert := New(new(testing.T))
list := []string{"Foo", "Bar"}
@ -221,7 +200,6 @@ func TestContainsWrapper(t *testing.T) {
}
func TestNotContainsWrapper(t *testing.T) {
t.Parallel()
assert := New(new(testing.T))
list := []string{"Foo", "Bar"}
@ -243,7 +221,6 @@ func TestNotContainsWrapper(t *testing.T) {
}
func TestConditionWrapper(t *testing.T) {
t.Parallel()
assert := New(new(testing.T))
@ -258,7 +235,6 @@ func TestConditionWrapper(t *testing.T) {
}
func TestDidPanicWrapper(t *testing.T) {
t.Parallel()
if funcDidPanic, _, _ := didPanic(func() {
panic("Panic!")
@ -274,7 +250,6 @@ func TestDidPanicWrapper(t *testing.T) {
}
func TestPanicsWrapper(t *testing.T) {
t.Parallel()
assert := New(new(testing.T))
@ -292,7 +267,6 @@ func TestPanicsWrapper(t *testing.T) {
}
func TestNotPanicsWrapper(t *testing.T) {
t.Parallel()
assert := New(new(testing.T))
@ -310,8 +284,6 @@ func TestNotPanicsWrapper(t *testing.T) {
}
func TestNoErrorWrapper(t *testing.T) {
t.Parallel()
assert := New(t)
mockAssert := New(new(testing.T))
@ -328,8 +300,6 @@ func TestNoErrorWrapper(t *testing.T) {
}
func TestErrorWrapper(t *testing.T) {
t.Parallel()
assert := New(t)
mockAssert := New(new(testing.T))
@ -346,8 +316,6 @@ func TestErrorWrapper(t *testing.T) {
}
func TestErrorContainsWrapper(t *testing.T) {
t.Parallel()
assert := New(t)
mockAssert := New(new(testing.T))
@ -367,8 +335,6 @@ func TestErrorContainsWrapper(t *testing.T) {
}
func TestEqualErrorWrapper(t *testing.T) {
t.Parallel()
assert := New(t)
mockAssert := New(new(testing.T))
@ -386,8 +352,6 @@ func TestEqualErrorWrapper(t *testing.T) {
}
func TestEmptyWrapper(t *testing.T) {
t.Parallel()
assert := New(t)
mockAssert := New(new(testing.T))
@ -406,8 +370,6 @@ func TestEmptyWrapper(t *testing.T) {
}
func TestNotEmptyWrapper(t *testing.T) {
t.Parallel()
assert := New(t)
mockAssert := New(new(testing.T))
@ -426,8 +388,6 @@ func TestNotEmptyWrapper(t *testing.T) {
}
func TestLenWrapper(t *testing.T) {
t.Parallel()
assert := New(t)
mockAssert := New(new(testing.T))
@ -468,8 +428,6 @@ func TestLenWrapper(t *testing.T) {
}
func TestWithinDurationWrapper(t *testing.T) {
t.Parallel()
assert := New(t)
mockAssert := New(new(testing.T))
a := time.Now()
@ -489,8 +447,6 @@ func TestWithinDurationWrapper(t *testing.T) {
}
func TestInDeltaWrapper(t *testing.T) {
t.Parallel()
assert := New(new(testing.T))
True(t, assert.InDelta(1.001, 1, 0.01), "|1.001 - 1| <= 0.01")
@ -525,8 +481,6 @@ func TestInDeltaWrapper(t *testing.T) {
}
func TestInEpsilonWrapper(t *testing.T) {
t.Parallel()
assert := New(new(testing.T))
cases := []struct {
@ -565,7 +519,6 @@ func TestInEpsilonWrapper(t *testing.T) {
}
func TestRegexpWrapper(t *testing.T) {
t.Parallel()
assert := New(new(testing.T))
@ -593,7 +546,7 @@ func TestRegexpWrapper(t *testing.T) {
}
for _, tc := range cases {
False(t, assert.Regexp(tc.rx, tc.str), "Expected %q to not match %q", tc.rx, tc.str)
False(t, assert.Regexp(tc.rx, tc.str), "Expected \"%s\" to not match \"%s\"", tc.rx, tc.str)
False(t, assert.Regexp(regexp.MustCompile(tc.rx), tc.str))
True(t, assert.NotRegexp(tc.rx, tc.str))
True(t, assert.NotRegexp(regexp.MustCompile(tc.rx), tc.str))
@ -601,8 +554,6 @@ func TestRegexpWrapper(t *testing.T) {
}
func TestZeroWrapper(t *testing.T) {
t.Parallel()
assert := New(t)
mockAssert := New(new(testing.T))
@ -616,8 +567,6 @@ func TestZeroWrapper(t *testing.T) {
}
func TestNotZeroWrapper(t *testing.T) {
t.Parallel()
assert := New(t)
mockAssert := New(new(testing.T))
@ -631,8 +580,6 @@ func TestNotZeroWrapper(t *testing.T) {
}
func TestJSONEqWrapper_EqualSONString(t *testing.T) {
t.Parallel()
assert := New(new(testing.T))
if !assert.JSONEq(`{"hello": "world", "foo": "bar"}`, `{"hello": "world", "foo": "bar"}`) {
t.Error("JSONEq should return true")
@ -641,8 +588,6 @@ func TestJSONEqWrapper_EqualSONString(t *testing.T) {
}
func TestJSONEqWrapper_EquivalentButNotEqual(t *testing.T) {
t.Parallel()
assert := New(new(testing.T))
if !assert.JSONEq(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) {
t.Error("JSONEq should return true")
@ -651,8 +596,6 @@ func TestJSONEqWrapper_EquivalentButNotEqual(t *testing.T) {
}
func TestJSONEqWrapper_HashOfArraysAndHashes(t *testing.T) {
t.Parallel()
assert := New(new(testing.T))
if !assert.JSONEq("{\r\n\t\"numeric\": 1.5,\r\n\t\"array\": [{\"foo\": \"bar\"}, 1, \"string\", [\"nested\", \"array\", 5.5]],\r\n\t\"hash\": {\"nested\": \"hash\", \"nested_slice\": [\"this\", \"is\", \"nested\"]},\r\n\t\"string\": \"foo\"\r\n}",
"{\r\n\t\"numeric\": 1.5,\r\n\t\"hash\": {\"nested\": \"hash\", \"nested_slice\": [\"this\", \"is\", \"nested\"]},\r\n\t\"string\": \"foo\",\r\n\t\"array\": [{\"foo\": \"bar\"}, 1, \"string\", [\"nested\", \"array\", 5.5]]\r\n}") {
@ -661,8 +604,6 @@ func TestJSONEqWrapper_HashOfArraysAndHashes(t *testing.T) {
}
func TestJSONEqWrapper_Array(t *testing.T) {
t.Parallel()
assert := New(new(testing.T))
if !assert.JSONEq(`["foo", {"hello": "world", "nested": "hash"}]`, `["foo", {"nested": "hash", "hello": "world"}]`) {
t.Error("JSONEq should return true")
@ -671,8 +612,6 @@ func TestJSONEqWrapper_Array(t *testing.T) {
}
func TestJSONEqWrapper_HashAndArrayNotEquivalent(t *testing.T) {
t.Parallel()
assert := New(new(testing.T))
if assert.JSONEq(`["foo", {"hello": "world", "nested": "hash"}]`, `{"foo": "bar", {"nested": "hash", "hello": "world"}}`) {
t.Error("JSONEq should return false")
@ -680,8 +619,6 @@ func TestJSONEqWrapper_HashAndArrayNotEquivalent(t *testing.T) {
}
func TestJSONEqWrapper_HashesNotEquivalent(t *testing.T) {
t.Parallel()
assert := New(new(testing.T))
if assert.JSONEq(`{"foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) {
t.Error("JSONEq should return false")
@ -689,8 +626,6 @@ func TestJSONEqWrapper_HashesNotEquivalent(t *testing.T) {
}
func TestJSONEqWrapper_ActualIsNotJSON(t *testing.T) {
t.Parallel()
assert := New(new(testing.T))
if assert.JSONEq(`{"foo": "bar"}`, "Not JSON") {
t.Error("JSONEq should return false")
@ -698,8 +633,6 @@ func TestJSONEqWrapper_ActualIsNotJSON(t *testing.T) {
}
func TestJSONEqWrapper_ExpectedIsNotJSON(t *testing.T) {
t.Parallel()
assert := New(new(testing.T))
if assert.JSONEq("Not JSON", `{"foo": "bar", "hello": "world"}`) {
t.Error("JSONEq should return false")
@ -707,8 +640,6 @@ func TestJSONEqWrapper_ExpectedIsNotJSON(t *testing.T) {
}
func TestJSONEqWrapper_ExpectedAndActualNotJSON(t *testing.T) {
t.Parallel()
assert := New(new(testing.T))
if assert.JSONEq("Not JSON", "Not JSON") {
t.Error("JSONEq should return false")
@ -716,8 +647,6 @@ func TestJSONEqWrapper_ExpectedAndActualNotJSON(t *testing.T) {
}
func TestJSONEqWrapper_ArraysOfDifferentOrder(t *testing.T) {
t.Parallel()
assert := New(new(testing.T))
if assert.JSONEq(`["foo", {"hello": "world", "nested": "hash"}]`, `[{ "hello": "world", "nested": "hash"}, "foo"]`) {
t.Error("JSONEq should return false")
@ -725,8 +654,6 @@ func TestJSONEqWrapper_ArraysOfDifferentOrder(t *testing.T) {
}
func TestYAMLEqWrapper_EqualYAMLString(t *testing.T) {
t.Parallel()
assert := New(new(testing.T))
if !assert.YAMLEq(`{"hello": "world", "foo": "bar"}`, `{"hello": "world", "foo": "bar"}`) {
t.Error("YAMLEq should return true")
@ -735,8 +662,6 @@ func TestYAMLEqWrapper_EqualYAMLString(t *testing.T) {
}
func TestYAMLEqWrapper_EquivalentButNotEqual(t *testing.T) {
t.Parallel()
assert := New(new(testing.T))
if !assert.YAMLEq(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) {
t.Error("YAMLEq should return true")
@ -745,8 +670,6 @@ func TestYAMLEqWrapper_EquivalentButNotEqual(t *testing.T) {
}
func TestYAMLEqWrapper_HashOfArraysAndHashes(t *testing.T) {
t.Parallel()
assert := New(new(testing.T))
expected := `
numeric: 1.5
@ -779,8 +702,6 @@ array:
}
func TestYAMLEqWrapper_Array(t *testing.T) {
t.Parallel()
assert := New(new(testing.T))
if !assert.YAMLEq(`["foo", {"hello": "world", "nested": "hash"}]`, `["foo", {"nested": "hash", "hello": "world"}]`) {
t.Error("YAMLEq should return true")
@ -789,8 +710,6 @@ func TestYAMLEqWrapper_Array(t *testing.T) {
}
func TestYAMLEqWrapper_HashAndArrayNotEquivalent(t *testing.T) {
t.Parallel()
assert := New(new(testing.T))
if assert.YAMLEq(`["foo", {"hello": "world", "nested": "hash"}]`, `{"foo": "bar", {"nested": "hash", "hello": "world"}}`) {
t.Error("YAMLEq should return false")
@ -798,8 +717,6 @@ func TestYAMLEqWrapper_HashAndArrayNotEquivalent(t *testing.T) {
}
func TestYAMLEqWrapper_HashesNotEquivalent(t *testing.T) {
t.Parallel()
assert := New(new(testing.T))
if assert.YAMLEq(`{"foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) {
t.Error("YAMLEq should return false")
@ -807,8 +724,6 @@ func TestYAMLEqWrapper_HashesNotEquivalent(t *testing.T) {
}
func TestYAMLEqWrapper_ActualIsSimpleString(t *testing.T) {
t.Parallel()
assert := New(new(testing.T))
if assert.YAMLEq(`{"foo": "bar"}`, "Simple String") {
t.Error("YAMLEq should return false")
@ -816,8 +731,6 @@ func TestYAMLEqWrapper_ActualIsSimpleString(t *testing.T) {
}
func TestYAMLEqWrapper_ExpectedIsSimpleString(t *testing.T) {
t.Parallel()
assert := New(new(testing.T))
if assert.YAMLEq("Simple String", `{"foo": "bar", "hello": "world"}`) {
t.Error("YAMLEq should return false")
@ -825,8 +738,6 @@ func TestYAMLEqWrapper_ExpectedIsSimpleString(t *testing.T) {
}
func TestYAMLEqWrapper_ExpectedAndActualSimpleString(t *testing.T) {
t.Parallel()
assert := New(new(testing.T))
if !assert.YAMLEq("Simple String", "Simple String") {
t.Error("YAMLEq should return true")
@ -834,8 +745,6 @@ func TestYAMLEqWrapper_ExpectedAndActualSimpleString(t *testing.T) {
}
func TestYAMLEqWrapper_ArraysOfDifferentOrder(t *testing.T) {
t.Parallel()
assert := New(new(testing.T))
if assert.YAMLEq(`["foo", {"hello": "world", "nested": "hash"}]`, `[{ "hello": "world", "nested": "hash"}, "foo"]`) {
t.Error("YAMLEq should return false")

View File

@ -12,7 +12,7 @@ import (
// an error if building a new request fails.
func httpCode(handler http.HandlerFunc, method, url string, values url.Values) (int, error) {
w := httptest.NewRecorder()
req, err := http.NewRequest(method, url, http.NoBody)
req, err := http.NewRequest(method, url, nil)
if err != nil {
return -1, err
}
@ -23,7 +23,7 @@ func httpCode(handler http.HandlerFunc, method, url string, values url.Values) (
// HTTPSuccess asserts that a specified handler returns a success status code.
//
// assert.HTTPSuccess(t, myHandler, "POST", "http://www.google.com", nil)
// assert.HTTPSuccess(t, myHandler, "POST", "http://www.google.com", nil)
//
// Returns whether the assertion was successful (true) or not (false).
func HTTPSuccess(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, msgAndArgs ...interface{}) bool {
@ -32,12 +32,12 @@ func HTTPSuccess(t TestingT, handler http.HandlerFunc, method, url string, value
}
code, err := httpCode(handler, method, url, values)
if err != nil {
Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err), msgAndArgs...)
Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err))
}
isSuccessCode := code >= http.StatusOK && code <= http.StatusPartialContent
if !isSuccessCode {
Fail(t, fmt.Sprintf("Expected HTTP success status code for %q but received %d", url+"?"+values.Encode(), code), msgAndArgs...)
Fail(t, fmt.Sprintf("Expected HTTP success status code for %q but received %d", url+"?"+values.Encode(), code))
}
return isSuccessCode
@ -45,7 +45,7 @@ func HTTPSuccess(t TestingT, handler http.HandlerFunc, method, url string, value
// HTTPRedirect asserts that a specified handler returns a redirect status code.
//
// assert.HTTPRedirect(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}}
// assert.HTTPRedirect(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}}
//
// Returns whether the assertion was successful (true) or not (false).
func HTTPRedirect(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, msgAndArgs ...interface{}) bool {
@ -54,12 +54,12 @@ func HTTPRedirect(t TestingT, handler http.HandlerFunc, method, url string, valu
}
code, err := httpCode(handler, method, url, values)
if err != nil {
Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err), msgAndArgs...)
Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err))
}
isRedirectCode := code >= http.StatusMultipleChoices && code <= http.StatusTemporaryRedirect
if !isRedirectCode {
Fail(t, fmt.Sprintf("Expected HTTP redirect status code for %q but received %d", url+"?"+values.Encode(), code), msgAndArgs...)
Fail(t, fmt.Sprintf("Expected HTTP redirect status code for %q but received %d", url+"?"+values.Encode(), code))
}
return isRedirectCode
@ -67,7 +67,7 @@ func HTTPRedirect(t TestingT, handler http.HandlerFunc, method, url string, valu
// HTTPError asserts that a specified handler returns an error status code.
//
// assert.HTTPError(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}}
// assert.HTTPError(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}}
//
// Returns whether the assertion was successful (true) or not (false).
func HTTPError(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, msgAndArgs ...interface{}) bool {
@ -76,12 +76,12 @@ func HTTPError(t TestingT, handler http.HandlerFunc, method, url string, values
}
code, err := httpCode(handler, method, url, values)
if err != nil {
Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err), msgAndArgs...)
Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err))
}
isErrorCode := code >= http.StatusBadRequest
if !isErrorCode {
Fail(t, fmt.Sprintf("Expected HTTP error status code for %q but received %d", url+"?"+values.Encode(), code), msgAndArgs...)
Fail(t, fmt.Sprintf("Expected HTTP error status code for %q but received %d", url+"?"+values.Encode(), code))
}
return isErrorCode
@ -89,7 +89,7 @@ func HTTPError(t TestingT, handler http.HandlerFunc, method, url string, values
// HTTPStatusCode asserts that a specified handler returns a specified status code.
//
// assert.HTTPStatusCode(t, myHandler, "GET", "/notImplemented", nil, 501)
// assert.HTTPStatusCode(t, myHandler, "GET", "/notImplemented", nil, 501)
//
// Returns whether the assertion was successful (true) or not (false).
func HTTPStatusCode(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, statuscode int, msgAndArgs ...interface{}) bool {
@ -98,12 +98,12 @@ func HTTPStatusCode(t TestingT, handler http.HandlerFunc, method, url string, va
}
code, err := httpCode(handler, method, url, values)
if err != nil {
Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err), msgAndArgs...)
Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err))
}
successful := code == statuscode
if !successful {
Fail(t, fmt.Sprintf("Expected HTTP status code %d for %q but received %d", statuscode, url+"?"+values.Encode(), code), msgAndArgs...)
Fail(t, fmt.Sprintf("Expected HTTP status code %d for %q but received %d", statuscode, url+"?"+values.Encode(), code))
}
return successful
@ -113,10 +113,7 @@ func HTTPStatusCode(t TestingT, handler http.HandlerFunc, method, url string, va
// empty string if building a new request fails.
func HTTPBody(handler http.HandlerFunc, method, url string, values url.Values) string {
w := httptest.NewRecorder()
if len(values) > 0 {
url += "?" + values.Encode()
}
req, err := http.NewRequest(method, url, http.NoBody)
req, err := http.NewRequest(method, url+"?"+values.Encode(), nil)
if err != nil {
return ""
}
@ -127,7 +124,7 @@ func HTTPBody(handler http.HandlerFunc, method, url string, values url.Values) s
// HTTPBodyContains asserts that a specified handler returns a
// body that contains a string.
//
// assert.HTTPBodyContains(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky")
// assert.HTTPBodyContains(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky")
//
// Returns whether the assertion was successful (true) or not (false).
func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool {
@ -138,7 +135,7 @@ func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method, url string,
contains := strings.Contains(body, fmt.Sprint(str))
if !contains {
Fail(t, fmt.Sprintf("Expected response body for %q to contain %q but found %q", url+"?"+values.Encode(), str, body), msgAndArgs...)
Fail(t, fmt.Sprintf("Expected response body for \"%s\" to contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body))
}
return contains
@ -147,7 +144,7 @@ func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method, url string,
// HTTPBodyNotContains asserts that a specified handler returns a
// body that does not contain a string.
//
// assert.HTTPBodyNotContains(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky")
// assert.HTTPBodyNotContains(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky")
//
// Returns whether the assertion was successful (true) or not (false).
func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool {
@ -158,7 +155,7 @@ func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, method, url strin
contains := strings.Contains(body, fmt.Sprint(str))
if contains {
Fail(t, fmt.Sprintf("Expected response body for %q to NOT contain %q but found %q", url+"?"+values.Encode(), str, body), msgAndArgs...)
Fail(t, fmt.Sprintf("Expected response body for \"%s\" to NOT contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body))
}
return !contains

View File

@ -2,7 +2,6 @@ package assert
import (
"fmt"
"io"
"net/http"
"net/url"
"testing"
@ -12,12 +11,6 @@ func httpOK(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
}
func httpReadBody(w http.ResponseWriter, r *http.Request) {
_, _ = io.Copy(io.Discard, r.Body)
w.WriteHeader(http.StatusOK)
_, _ = w.Write([]byte("hello"))
}
func httpRedirect(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusTemporaryRedirect)
}
@ -31,8 +24,6 @@ func httpStatusCode(w http.ResponseWriter, r *http.Request) {
}
func TestHTTPSuccess(t *testing.T) {
t.Parallel()
assert := New(t)
mockT1 := new(testing.T)
@ -43,35 +34,21 @@ func TestHTTPSuccess(t *testing.T) {
assert.Equal(HTTPSuccess(mockT2, httpRedirect, "GET", "/", nil), false)
assert.True(mockT2.Failed())
mockT3 := new(mockTestingT)
assert.Equal(HTTPSuccess(
mockT3, httpError, "GET", "/", nil,
"was not expecting a failure here",
), false)
mockT3 := new(testing.T)
assert.Equal(HTTPSuccess(mockT3, httpError, "GET", "/", nil), false)
assert.True(mockT3.Failed())
assert.Contains(mockT3.errorString(), "was not expecting a failure here")
mockT4 := new(testing.T)
assert.Equal(HTTPSuccess(mockT4, httpStatusCode, "GET", "/", nil), false)
assert.True(mockT4.Failed())
mockT5 := new(testing.T)
assert.Equal(HTTPSuccess(mockT5, httpReadBody, "POST", "/", nil), true)
assert.False(mockT5.Failed())
}
func TestHTTPRedirect(t *testing.T) {
t.Parallel()
assert := New(t)
mockT1 := new(mockTestingT)
assert.Equal(HTTPRedirect(
mockT1, httpOK, "GET", "/", nil,
"was expecting a 3xx status code. Got 200.",
), false)
mockT1 := new(testing.T)
assert.Equal(HTTPRedirect(mockT1, httpOK, "GET", "/", nil), false)
assert.True(mockT1.Failed())
assert.Contains(mockT1.errorString(), "was expecting a 3xx status code. Got 200.")
mockT2 := new(testing.T)
assert.Equal(HTTPRedirect(mockT2, httpRedirect, "GET", "/", nil), true)
@ -87,21 +64,15 @@ func TestHTTPRedirect(t *testing.T) {
}
func TestHTTPError(t *testing.T) {
t.Parallel()
assert := New(t)
mockT1 := new(testing.T)
assert.Equal(HTTPError(mockT1, httpOK, "GET", "/", nil), false)
assert.True(mockT1.Failed())
mockT2 := new(mockTestingT)
assert.Equal(HTTPError(
mockT2, httpRedirect, "GET", "/", nil,
"Expected this request to error out. But it didn't",
), false)
mockT2 := new(testing.T)
assert.Equal(HTTPError(mockT2, httpRedirect, "GET", "/", nil), false)
assert.True(mockT2.Failed())
assert.Contains(mockT2.errorString(), "Expected this request to error out. But it didn't")
mockT3 := new(testing.T)
assert.Equal(HTTPError(mockT3, httpError, "GET", "/", nil), true)
@ -113,8 +84,6 @@ func TestHTTPError(t *testing.T) {
}
func TestHTTPStatusCode(t *testing.T) {
t.Parallel()
assert := New(t)
mockT1 := new(testing.T)
@ -125,13 +94,9 @@ func TestHTTPStatusCode(t *testing.T) {
assert.Equal(HTTPStatusCode(mockT2, httpRedirect, "GET", "/", nil, http.StatusSwitchingProtocols), false)
assert.True(mockT2.Failed())
mockT3 := new(mockTestingT)
assert.Equal(HTTPStatusCode(
mockT3, httpError, "GET", "/", nil, http.StatusSwitchingProtocols,
"Expected the status code to be %d", http.StatusSwitchingProtocols,
), false)
mockT3 := new(testing.T)
assert.Equal(HTTPStatusCode(mockT3, httpError, "GET", "/", nil, http.StatusSwitchingProtocols), false)
assert.True(mockT3.Failed())
assert.Contains(mockT3.errorString(), "Expected the status code to be 101")
mockT4 := new(testing.T)
assert.Equal(HTTPStatusCode(mockT4, httpStatusCode, "GET", "/", nil, http.StatusSwitchingProtocols), true)
@ -139,8 +104,6 @@ func TestHTTPStatusCode(t *testing.T) {
}
func TestHTTPStatusesWrapper(t *testing.T) {
t.Parallel()
assert := New(t)
mockAssert := New(new(testing.T))
@ -159,12 +122,10 @@ func TestHTTPStatusesWrapper(t *testing.T) {
func httpHelloName(w http.ResponseWriter, r *http.Request) {
name := r.FormValue("name")
_, _ = fmt.Fprintf(w, "Hello, %s!", name)
_, _ = w.Write([]byte(fmt.Sprintf("Hello, %s!", name)))
}
func TestHTTPRequestWithNoParams(t *testing.T) {
t.Parallel()
var got *http.Request
handler := func(w http.ResponseWriter, r *http.Request) {
got = r
@ -178,8 +139,6 @@ func TestHTTPRequestWithNoParams(t *testing.T) {
}
func TestHTTPRequestWithParams(t *testing.T) {
t.Parallel()
var got *http.Request
handler := func(w http.ResponseWriter, r *http.Request) {
got = r
@ -196,29 +155,19 @@ func TestHTTPRequestWithParams(t *testing.T) {
}
func TestHttpBody(t *testing.T) {
t.Parallel()
assert := New(t)
mockT := new(mockTestingT)
mockT := new(testing.T)
assert.True(HTTPBodyContains(mockT, httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "Hello, World!"))
assert.True(HTTPBodyContains(mockT, httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "World"))
assert.False(HTTPBodyContains(mockT, httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "world"))
assert.False(HTTPBodyNotContains(mockT, httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "Hello, World!"))
assert.False(HTTPBodyNotContains(
mockT, httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "World",
"Expected the request body to not contain 'World'. But it did.",
))
assert.False(HTTPBodyNotContains(mockT, httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "World"))
assert.True(HTTPBodyNotContains(mockT, httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "world"))
assert.Contains(mockT.errorString(), "Expected the request body to not contain 'World'. But it did.")
assert.True(HTTPBodyContains(mockT, httpReadBody, "GET", "/", nil, "hello"))
}
func TestHttpBodyWrappers(t *testing.T) {
t.Parallel()
assert := New(t)
mockAssert := New(new(testing.T))
@ -229,4 +178,5 @@ func TestHttpBodyWrappers(t *testing.T) {
assert.False(mockAssert.HTTPBodyNotContains(httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "Hello, World!"))
assert.False(mockAssert.HTTPBodyNotContains(httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "World"))
assert.True(mockAssert.HTTPBodyNotContains(httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "world"))
}

View File

@ -1,4 +0,0 @@
// This package exists just to isolate tests that reference the [unsafe] package.
//
// The tests in this package are totally safe.
package unsafetests

View File

@ -1,34 +0,0 @@
package unsafetests_test
import (
"fmt"
"testing"
"unsafe"
"github.com/stretchr/testify/assert"
)
type ignoreTestingT struct{}
var _ assert.TestingT = ignoreTestingT{}
func (ignoreTestingT) Helper() {}
func (ignoreTestingT) Errorf(format string, args ...interface{}) {
// Run the formatting, but ignore the result
msg := fmt.Sprintf(format, args...)
_ = msg
}
func TestUnsafePointers(t *testing.T) {
var ignore ignoreTestingT
assert.True(t, assert.Nil(t, unsafe.Pointer(nil), "unsafe.Pointer(nil) is nil"))
assert.False(t, assert.NotNil(ignore, unsafe.Pointer(nil), "unsafe.Pointer(nil) is nil"))
assert.True(t, assert.Nil(t, unsafe.Pointer((*int)(nil)), "unsafe.Pointer((*int)(nil)) is nil"))
assert.False(t, assert.NotNil(ignore, unsafe.Pointer((*int)(nil)), "unsafe.Pointer((*int)(nil)) is nil"))
assert.False(t, assert.Nil(ignore, unsafe.Pointer(new(int)), "unsafe.Pointer(new(int)) is NOT nil"))
assert.True(t, assert.NotNil(t, unsafe.Pointer(new(int)), "unsafe.Pointer(new(int)) is NOT nil"))
}

View File

@ -1,24 +0,0 @@
//go:build testify_yaml_custom && !testify_yaml_fail && !testify_yaml_default
// Package yaml is an implementation of YAML functions that calls a pluggable implementation.
//
// This implementation is selected with the testify_yaml_custom build tag.
//
// go test -tags testify_yaml_custom
//
// This implementation can be used at build time to replace the default implementation
// to avoid linking with [gopkg.in/yaml.v3].
//
// In your test package:
//
// import assertYaml "github.com/stretchr/testify/assert/yaml"
//
// func init() {
// assertYaml.Unmarshal = func (in []byte, out interface{}) error {
// // ...
// return nil
// }
// }
package yaml
var Unmarshal func(in []byte, out interface{}) error

View File

@ -1,36 +0,0 @@
//go:build !testify_yaml_fail && !testify_yaml_custom
// Package yaml is just an indirection to handle YAML deserialization.
//
// This package is just an indirection that allows the builder to override the
// indirection with an alternative implementation of this package that uses
// another implementation of YAML deserialization. This allows to not either not
// use YAML deserialization at all, or to use another implementation than
// [gopkg.in/yaml.v3] (for example for license compatibility reasons, see [PR #1120]).
//
// Alternative implementations are selected using build tags:
//
// - testify_yaml_fail: [Unmarshal] always fails with an error
// - testify_yaml_custom: [Unmarshal] is a variable. Caller must initialize it
// before calling any of [github.com/stretchr/testify/assert.YAMLEq] or
// [github.com/stretchr/testify/assert.YAMLEqf].
//
// Usage:
//
// go test -tags testify_yaml_fail
//
// You can check with "go list" which implementation is linked:
//
// go list -f '{{.Imports}}' github.com/stretchr/testify/assert/yaml
// go list -tags testify_yaml_fail -f '{{.Imports}}' github.com/stretchr/testify/assert/yaml
// go list -tags testify_yaml_custom -f '{{.Imports}}' github.com/stretchr/testify/assert/yaml
//
// [PR #1120]: https://github.com/stretchr/testify/pull/1120
package yaml
import goyaml "gopkg.in/yaml.v3"
// Unmarshal is just a wrapper of [gopkg.in/yaml.v3.Unmarshal].
func Unmarshal(in []byte, out interface{}) error {
return goyaml.Unmarshal(in, out)
}

View File

@ -1,17 +0,0 @@
//go:build testify_yaml_fail && !testify_yaml_custom && !testify_yaml_default
// Package yaml is an implementation of YAML functions that always fail.
//
// This implementation can be used at build time to replace the default implementation
// to avoid linking with [gopkg.in/yaml.v3]:
//
// go test -tags testify_yaml_fail
package yaml
import "errors"
var errNotImplemented = errors.New("YAML functions are not available (see https://pkg.go.dev/github.com/stretchr/testify/assert/yaml)")
func Unmarshal([]byte, interface{}) error {
return errNotImplemented
}

28
doc.go
View File

@ -1,17 +1,23 @@
// Module testify is a set of packages that provide many tools for testifying that your code will behave as you intend.
// ** We are working on testify v2 and would love to hear what you'd like to see in it, have your say here: https://cutt.ly/testify **
// Package testify is a set of packages that provide many tools for testifying that your code will behave as you intend.
//
// Testify contains the following packages:
// testify contains the following packages:
//
// The [github.com/stretchr/testify/assert] package provides a comprehensive set of assertion functions that tie in to [the Go testing system].
// The [github.com/stretchr/testify/require] package provides the same assertions but as fatal checks.
// The assert package provides a comprehensive set of assertion functions that tie in to the Go testing system.
//
// The [github.com/stretchr/testify/mock] package provides a system by which it is possible to mock your objects and verify calls are happening as expected.
// The http package contains tools to make it easier to test http activity using the Go testing system.
//
// The [github.com/stretchr/testify/suite] package provides a basic structure for using structs as testing suites, and methods on those structs as tests. It includes setup/teardown functionality in the way of interfaces.
// The mock package provides a system by which it is possible to mock your objects and verify calls are happening as expected.
//
// A [golangci-lint] compatible linter for testify is available called [testifylint].
//
// [the Go testing system]: https://go.dev/doc/code#Testing
// [golangci-lint]: https://golangci-lint.run/
// [testifylint]: https://github.com/Antonboom/testifylint
// The suite package provides a basic structure for using structs as testing suites, and methods on those structs as tests. It includes setup/teardown functionality in the way of interfaces.
package testify
// blank imports help docs.
import (
// assert package
_ "github.com/stretchr/testify/assert"
// http package
_ "github.com/stretchr/testify/http"
// mock package
_ "github.com/stretchr/testify/mock"
)

10
go.mod
View File

@ -1,16 +1,10 @@
module github.com/stretchr/testify
// This should match the minimum supported version that is tested in
// .github/workflows/main.yml
go 1.17
go 1.13
require (
github.com/davecgh/go-spew v1.1.1
github.com/pmezard/go-difflib v1.0.0
github.com/stretchr/objx v0.5.2 // To avoid a cycle the version of testify used by objx should be excluded below
github.com/stretchr/objx v0.4.0
gopkg.in/yaml.v3 v3.0.1
)
// Break dependency cycle with objx.
// See https://github.com/stretchr/objx/pull/140
exclude github.com/stretchr/testify v1.8.4

8
go.sum
View File

@ -1,10 +1,14 @@
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View File

@ -1,2 +1,2 @@
// Deprecated: Use [net/http/httptest] instead.
// Package http DEPRECATED USE net/http/httptest
package http

View File

@ -4,7 +4,7 @@ import (
"net/http"
)
// Deprecated: Use [net/http/httptest] instead.
// TestResponseWriter DEPRECATED: We recommend you use http://golang.org/pkg/net/http/httptest instead.
type TestResponseWriter struct {
// StatusCode is the last int written by the call to WriteHeader(int)
@ -17,7 +17,7 @@ type TestResponseWriter struct {
header http.Header
}
// Deprecated: Use [net/http/httptest] instead.
// Header DEPRECATED: We recommend you use http://golang.org/pkg/net/http/httptest instead.
func (rw *TestResponseWriter) Header() http.Header {
if rw.header == nil {
@ -27,7 +27,7 @@ func (rw *TestResponseWriter) Header() http.Header {
return rw.header
}
// Deprecated: Use [net/http/httptest] instead.
// Write DEPRECATED: We recommend you use http://golang.org/pkg/net/http/httptest instead.
func (rw *TestResponseWriter) Write(bytes []byte) (int, error) {
// assume 200 success if no header has been set
@ -43,7 +43,7 @@ func (rw *TestResponseWriter) Write(bytes []byte) (int, error) {
}
// Deprecated: Use [net/http/httptest] instead.
// WriteHeader DEPRECATED: We recommend you use http://golang.org/pkg/net/http/httptest instead.
func (rw *TestResponseWriter) WriteHeader(i int) {
rw.StatusCode = i
}

View File

@ -6,12 +6,12 @@ import (
"github.com/stretchr/testify/mock"
)
// Deprecated: Use [net/http/httptest] instead.
// TestRoundTripper DEPRECATED USE net/http/httptest
type TestRoundTripper struct {
mock.Mock
}
// Deprecated: Use [net/http/httptest] instead.
// RoundTrip DEPRECATED USE net/http/httptest
func (t *TestRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
args := t.Called(req)
return args.Get(0).(*http.Response), args.Error(1)

View File

@ -1,17 +1,17 @@
// Package mock provides a system by which it is possible to mock your objects
// and verify calls are happening as expected.
//
// # Example Usage
// Example Usage
//
// The mock package provides an object, Mock, that tracks activity on another object. It is usually
// embedded into a test object as shown below:
//
// type MyTestObject struct {
// // add a Mock object instance
// mock.Mock
// type MyTestObject struct {
// // add a Mock object instance
// mock.Mock
//
// // other fields go here as normal
// }
// // other fields go here as normal
// }
//
// When implementing the methods of an interface, you wire your functions up
// to call the Mock.Called(args...) method, and return the appropriate values.
@ -19,25 +19,25 @@
// For example, to mock a method that saves the name and age of a person and returns
// the year of their birth or an error, you might write this:
//
// func (o *MyTestObject) SavePersonDetails(firstname, lastname string, age int) (int, error) {
// args := o.Called(firstname, lastname, age)
// return args.Int(0), args.Error(1)
// }
// func (o *MyTestObject) SavePersonDetails(firstname, lastname string, age int) (int, error) {
// args := o.Called(firstname, lastname, age)
// return args.Int(0), args.Error(1)
// }
//
// The Int, Error and Bool methods are examples of strongly typed getters that take the argument
// index position. Given this argument list:
//
// (12, true, "Something")
// (12, true, "Something")
//
// You could read them out strongly typed like this:
//
// args.Int(0)
// args.Bool(1)
// args.String(2)
// args.Int(0)
// args.Bool(1)
// args.String(2)
//
// For objects of your own type, use the generic Arguments.Get(index) method and make a type assertion:
//
// return args.Get(0).(*MyObject), args.Get(1).(*AnotherObjectOfMine)
// return args.Get(0).(*MyObject), args.Get(1).(*AnotherObjectOfMine)
//
// This may cause a panic if the object you are getting is nil (the type assertion will fail), in those
// cases you should check for nil first.

View File

@ -3,7 +3,6 @@ package mock
import (
"errors"
"fmt"
"path"
"reflect"
"regexp"
"runtime"
@ -14,13 +13,9 @@ import (
"github.com/davecgh/go-spew/spew"
"github.com/pmezard/go-difflib/difflib"
"github.com/stretchr/objx"
"github.com/stretchr/testify/assert"
)
// regex for GCCGO functions
var gccgoRE = regexp.MustCompile(`\.pN\d+_`)
// TestingT is an interface wrapper around *testing.T
type TestingT interface {
Logf(format string, args ...interface{})
@ -75,17 +70,14 @@ type Call struct {
// if the PanicMsg is set to a non nil string the function call will panic
// irrespective of other settings
PanicMsg *string
// Calls which must be satisfied before this call can be
requires []*Call
}
func newCall(parent *Mock, methodName string, callerInfo []string, methodArguments Arguments, returnArguments Arguments) *Call {
func newCall(parent *Mock, methodName string, callerInfo []string, methodArguments ...interface{}) *Call {
return &Call{
Parent: parent,
Method: methodName,
Arguments: methodArguments,
ReturnArguments: returnArguments,
ReturnArguments: make([]interface{}, 0),
callerInfo: callerInfo,
Repeatability: 0,
WaitFor: nil,
@ -104,7 +96,7 @@ func (c *Call) unlock() {
// Return specifies the return arguments for the expectation.
//
// Mock.On("DoSomething").Return(errors.New("failed"))
// Mock.On("DoSomething").Return(errors.New("failed"))
func (c *Call) Return(returnArguments ...interface{}) *Call {
c.lock()
defer c.unlock()
@ -114,9 +106,9 @@ func (c *Call) Return(returnArguments ...interface{}) *Call {
return c
}
// Panic specifies if the function call should fail and the panic message
// Panic specifies if the functon call should fail and the panic message
//
// Mock.On("DoSomething").Panic("test panic")
// Mock.On("DoSomething").Panic("test panic")
func (c *Call) Panic(msg string) *Call {
c.lock()
defer c.unlock()
@ -126,24 +118,24 @@ func (c *Call) Panic(msg string) *Call {
return c
}
// Once indicates that the mock should only return the value once.
// Once indicates that that the mock should only return the value once.
//
// Mock.On("MyMethod", arg1, arg2).Return(returnArg1, returnArg2).Once()
// Mock.On("MyMethod", arg1, arg2).Return(returnArg1, returnArg2).Once()
func (c *Call) Once() *Call {
return c.Times(1)
}
// Twice indicates that the mock should only return the value twice.
// Twice indicates that that the mock should only return the value twice.
//
// Mock.On("MyMethod", arg1, arg2).Return(returnArg1, returnArg2).Twice()
// Mock.On("MyMethod", arg1, arg2).Return(returnArg1, returnArg2).Twice()
func (c *Call) Twice() *Call {
return c.Times(2)
}
// Times indicates that the mock should only return the indicated number
// Times indicates that that the mock should only return the indicated number
// of times.
//
// Mock.On("MyMethod", arg1, arg2).Return(returnArg1, returnArg2).Times(5)
// Mock.On("MyMethod", arg1, arg2).Return(returnArg1, returnArg2).Times(5)
func (c *Call) Times(i int) *Call {
c.lock()
defer c.unlock()
@ -154,7 +146,7 @@ func (c *Call) Times(i int) *Call {
// WaitUntil sets the channel that will block the mock's return until its closed
// or a message is received.
//
// Mock.On("MyMethod", arg1, arg2).WaitUntil(time.After(time.Second))
// Mock.On("MyMethod", arg1, arg2).WaitUntil(time.After(time.Second))
func (c *Call) WaitUntil(w <-chan time.Time) *Call {
c.lock()
defer c.unlock()
@ -164,7 +156,7 @@ func (c *Call) WaitUntil(w <-chan time.Time) *Call {
// After sets how long to block until the call returns
//
// Mock.On("MyMethod", arg1, arg2).After(time.Second)
// Mock.On("MyMethod", arg1, arg2).After(time.Second)
func (c *Call) After(d time.Duration) *Call {
c.lock()
defer c.unlock()
@ -176,10 +168,10 @@ func (c *Call) After(d time.Duration) *Call {
// mocking a method (such as an unmarshaler) that takes a pointer to a struct and
// sets properties in such struct
//
// Mock.On("Unmarshal", AnythingOfType("*map[string]interface{}")).Return().Run(func(args Arguments) {
// arg := args.Get(0).(*map[string]interface{})
// arg["foo"] = "bar"
// })
// Mock.On("Unmarshal", AnythingOfType("*map[string]interface{}")).Return().Run(func(args Arguments) {
// arg := args.Get(0).(*map[string]interface{})
// arg["foo"] = "bar"
// })
func (c *Call) Run(fn func(args Arguments)) *Call {
c.lock()
defer c.unlock()
@ -199,101 +191,14 @@ func (c *Call) Maybe() *Call {
// On chains a new expectation description onto the mocked interface. This
// allows syntax like.
//
// Mock.
// On("MyMethod", 1).Return(nil).
// On("MyOtherMethod", 'a', 'b', 'c').Return(errors.New("Some Error"))
//
// Mock.
// On("MyMethod", 1).Return(nil).
// On("MyOtherMethod", 'a', 'b', 'c').Return(errors.New("Some Error"))
//go:noinline
func (c *Call) On(methodName string, arguments ...interface{}) *Call {
return c.Parent.On(methodName, arguments...)
}
// Unset removes all mock handlers that satisfy the call instance arguments from being
// called. Only supported on call instances with static input arguments.
//
// For example, the only handler remaining after the following would be "MyMethod(2, 2)":
//
// Mock.
// On("MyMethod", 2, 2).Return(0).
// On("MyMethod", 3, 3).Return(0).
// On("MyMethod", Anything, Anything).Return(0)
// Mock.On("MyMethod", 3, 3).Unset()
func (c *Call) Unset() *Call {
var unlockOnce sync.Once
for _, arg := range c.Arguments {
if v := reflect.ValueOf(arg); v.Kind() == reflect.Func {
panic(fmt.Sprintf("cannot use Func in expectations. Use mock.AnythingOfType(\"%T\")", arg))
}
}
c.lock()
defer unlockOnce.Do(c.unlock)
foundMatchingCall := false
// in-place filter slice for calls to be removed - iterate from 0'th to last skipping unnecessary ones
var index int // write index
for _, call := range c.Parent.ExpectedCalls {
if call.Method == c.Method {
_, diffCount := call.Arguments.Diff(c.Arguments)
if diffCount == 0 {
foundMatchingCall = true
// Remove from ExpectedCalls - just skip it
continue
}
}
c.Parent.ExpectedCalls[index] = call
index++
}
// trim slice up to last copied index
c.Parent.ExpectedCalls = c.Parent.ExpectedCalls[:index]
if !foundMatchingCall {
unlockOnce.Do(c.unlock)
c.Parent.fail("\n\nmock: Could not find expected call\n-----------------------------\n\n%s\n\n",
callString(c.Method, c.Arguments, true),
)
}
return c
}
// NotBefore indicates that the mock should only be called after the referenced
// calls have been called as expected. The referenced calls may be from the
// same mock instance and/or other mock instances.
//
// Mock.On("Do").Return(nil).NotBefore(
// Mock.On("Init").Return(nil)
// )
func (c *Call) NotBefore(calls ...*Call) *Call {
c.lock()
defer c.unlock()
for _, call := range calls {
if call.Parent == nil {
panic("not before calls must be created with Mock.On()")
}
}
c.requires = append(c.requires, calls...)
return c
}
// InOrder defines the order in which the calls should be made
//
// For example:
//
// InOrder(
// Mock.On("init").Return(nil),
// Mock.On("Do").Return(nil),
// )
func InOrder(calls ...*Call) {
for i := 1; i < len(calls); i++ {
calls[i].NotBefore(calls[i-1])
}
}
// Mock is the workhorse used to track activity on another object.
// For an example of its usage, refer to the "Example Usage" section at the top
// of this document.
@ -313,7 +218,7 @@ type Mock struct {
// this data completely allowing you to do whatever you like with it.
testData objx.Map
mutex sync.Mutex
mutex *sync.Mutex
}
// String provides a %v format string for Mock.
@ -338,11 +243,12 @@ func (m *Mock) TestData() objx.Map {
Setting expectations
*/
// Test sets the [TestingT] on which errors will be reported, otherwise errors
// will cause a panic.
// Test should not be called on an object that is going to be used in a
// goroutine other than the one running the test function.
// Test sets the test struct variable of the mock object
func (m *Mock) Test(t TestingT) {
if m.mutex == nil {
m.mutex = &sync.Mutex{}
}
m.mutex.Lock()
defer m.mutex.Unlock()
m.test = t
@ -365,7 +271,7 @@ func (m *Mock) fail(format string, args ...interface{}) {
// On starts a description of an expectation of the specified method
// being called.
//
// Mock.On("MyMethod", arg1, arg2)
// Mock.On("MyMethod", arg1, arg2)
func (m *Mock) On(methodName string, arguments ...interface{}) *Call {
for _, arg := range arguments {
if v := reflect.ValueOf(arg); v.Kind() == reflect.Func {
@ -373,10 +279,12 @@ func (m *Mock) On(methodName string, arguments ...interface{}) *Call {
}
}
// Since we start mocks with the .On() function, m.mutex should be reset
m.mutex = &sync.Mutex{}
m.mutex.Lock()
defer m.mutex.Unlock()
c := newCall(m, methodName, assert.CallerInfo(), arguments, make([]interface{}, 0))
c := newCall(m, methodName, assert.CallerInfo(), arguments...)
m.ExpectedCalls = append(m.ExpectedCalls, c)
return c
}
@ -456,10 +364,6 @@ func callString(method string, arguments Arguments, includeArgumentValues bool)
if includeArgumentValues {
var argVals []string
for argIndex, arg := range arguments {
if _, ok := arg.(*FunctionalOptionsArgument); ok {
argVals = append(argVals, fmt.Sprintf("%d: %s", argIndex, arg))
continue
}
argVals = append(argVals, fmt.Sprintf("%d: %#v", argIndex, arg))
}
argValsString = fmt.Sprintf("\n\t\t%s", strings.Join(argVals, "\n\t\t"))
@ -483,8 +387,9 @@ func (m *Mock) Called(arguments ...interface{}) Arguments {
// For Ex: github_com_docker_libkv_store_mock.WatchTree.pN39_github_com_docker_libkv_store_mock.Mock
// uses interface information unlike golang github.com/docker/libkv/store/mock.(*Mock).WatchTree
// With GCCGO we need to remove interface information starting from pN<dd>.
if gccgoRE.MatchString(functionPath) {
functionPath = gccgoRE.Split(functionPath, -1)[0]
re := regexp.MustCompile("\\.pN\\d+_")
if re.MatchString(functionPath) {
functionPath = re.Split(functionPath, -1)[0]
}
parts := strings.Split(functionPath, ".")
functionName := parts[len(parts)-1]
@ -501,10 +406,10 @@ func (m *Mock) MethodCalled(methodName string, arguments ...interface{}) Argumen
found, call := m.findExpectedCall(methodName, arguments...)
if found < 0 {
// expected call found, but it has already been called with repeatable times
// expected call found but it has already been called with repeatable times
if call != nil {
m.mutex.Unlock()
m.fail("\nassert: mock: The method has been called over %d times.\n\tEither do one more Mock.On(%#v).Return(...), or remove extra call.\n\tThis call was unexpected:\n\t\t%s\n\tat: %s", call.totalCalls, methodName, callString(methodName, arguments, true), assert.CallerInfo())
m.fail("\nassert: mock: The method has been called over %d times.\n\tEither do one more Mock.On(\"%s\").Return(...), or remove extra call.\n\tThis call was unexpected:\n\t\t%s\n\tat: %s", call.totalCalls, methodName, callString(methodName, arguments, true), assert.CallerInfo())
}
// we have to fail here - because we don't know what to do
// as the return arguments. This is because:
@ -516,34 +421,14 @@ func (m *Mock) MethodCalled(methodName string, arguments ...interface{}) Argumen
m.mutex.Unlock()
if closestCall != nil {
m.fail("\n\nmock: Unexpected Method Call\n-----------------------------\n\n%s\n\nThe closest call I have is: \n\n%s\n\n%s\nDiff: %s\nat: %s\n",
m.fail("\n\nmock: Unexpected Method Call\n-----------------------------\n\n%s\n\nThe closest call I have is: \n\n%s\n\n%s\nDiff: %s",
callString(methodName, arguments, true),
callString(methodName, closestCall.Arguments, true),
diffArguments(closestCall.Arguments, arguments),
strings.TrimSpace(mismatch),
assert.CallerInfo(),
)
} else {
m.fail("\nassert: mock: I don't know what to return because the method call was unexpected.\n\tEither do Mock.On(%#v).Return(...) first, or remove the %s() call.\n\tThis method was unexpected:\n\t\t%s\n\tat: %s", methodName, methodName, callString(methodName, arguments, true), assert.CallerInfo())
}
}
for _, requirement := range call.requires {
if satisfied, _ := requirement.Parent.checkExpectation(requirement); !satisfied {
m.mutex.Unlock()
m.fail("mock: Unexpected Method Call\n-----------------------------\n\n%s\n\nMust not be called before%s:\n\n%s",
callString(call.Method, call.Arguments, true),
func() (s string) {
if requirement.totalCalls > 0 {
s = " another call of"
}
if call.Parent != requirement.Parent {
s += " method from another mock instance"
}
return
}(),
callString(requirement.Method, requirement.Arguments, true),
)
m.fail("\nassert: mock: I don't know what to return because the method call was unexpected.\n\tEither do Mock.On(\"%s\").Return(...) first, or remove the %s() call.\n\tThis method was unexpected:\n\t\t%s\n\tat: %s", methodName, methodName, callString(methodName, arguments, true), assert.CallerInfo())
}
}
@ -555,7 +440,7 @@ func (m *Mock) MethodCalled(methodName string, arguments ...interface{}) Argumen
call.totalCalls++
// add the call
m.Calls = append(m.Calls, *newCall(m, methodName, assert.CallerInfo(), arguments, call.ReturnArguments))
m.Calls = append(m.Calls, *newCall(m, methodName, assert.CallerInfo(), arguments...))
m.mutex.Unlock()
// block if specified
@ -591,7 +476,7 @@ func (m *Mock) MethodCalled(methodName string, arguments ...interface{}) Argumen
Assertions
*/
type assertExpectationiser interface {
type assertExpectationser interface {
AssertExpectations(TestingT) bool
}
@ -604,11 +489,11 @@ func AssertExpectationsForObjects(t TestingT, testObjects ...interface{}) bool {
h.Helper()
}
for _, obj := range testObjects {
if m, ok := obj.(*Mock); ok {
if m, ok := obj.(Mock); ok {
t.Logf("Deprecated mock.AssertExpectationsForObjects(myMock.Mock) use mock.AssertExpectationsForObjects(myMock)")
obj = m
obj = &m
}
m := obj.(assertExpectationiser)
m := obj.(assertExpectationser)
if !m.AssertExpectations(t) {
t.Logf("Expectations didn't match for Mock: %+v", reflect.TypeOf(m))
return false
@ -620,42 +505,41 @@ func AssertExpectationsForObjects(t TestingT, testObjects ...interface{}) bool {
// AssertExpectations asserts that everything specified with On and Return was
// in fact called as expected. Calls may have occurred in any order.
func (m *Mock) AssertExpectations(t TestingT) bool {
if s, ok := t.(interface{ Skipped() bool }); ok && s.Skipped() {
return true
}
if h, ok := t.(tHelper); ok {
h.Helper()
}
if m.mutex == nil {
m.mutex = &sync.Mutex{}
}
m.mutex.Lock()
defer m.mutex.Unlock()
var somethingMissing bool
var failedExpectations int
// iterate through each expectation
expectedCalls := m.expectedCalls()
for _, expectedCall := range expectedCalls {
satisfied, reason := m.checkExpectation(expectedCall)
if !satisfied {
if !expectedCall.optional && !m.methodWasCalled(expectedCall.Method, expectedCall.Arguments) && expectedCall.totalCalls == 0 {
somethingMissing = true
failedExpectations++
t.Logf(reason)
t.Logf("FAIL:\t%s(%s)\n\t\tat: %s", expectedCall.Method, expectedCall.Arguments.String(), expectedCall.callerInfo)
} else {
if expectedCall.Repeatability > 0 {
somethingMissing = true
failedExpectations++
t.Logf("FAIL:\t%s(%s)\n\t\tat: %s", expectedCall.Method, expectedCall.Arguments.String(), expectedCall.callerInfo)
} else {
t.Logf("PASS:\t%s(%s)", expectedCall.Method, expectedCall.Arguments.String())
}
}
}
if failedExpectations != 0 {
if somethingMissing {
t.Errorf("FAIL: %d out of %d expectation(s) were met.\n\tThe code you are testing needs to make %d more call(s).\n\tat: %s", len(expectedCalls)-failedExpectations, len(expectedCalls), failedExpectations, assert.CallerInfo())
}
return failedExpectations == 0
}
func (m *Mock) checkExpectation(call *Call) (bool, string) {
if !call.optional && !m.methodWasCalled(call.Method, call.Arguments) && call.totalCalls == 0 {
return false, fmt.Sprintf("FAIL:\t%s(%s)\n\t\tat: %s", call.Method, call.Arguments.String(), call.callerInfo)
}
if call.Repeatability > 0 {
return false, fmt.Sprintf("FAIL:\t%s(%s)\n\t\tat: %s", call.Method, call.Arguments.String(), call.callerInfo)
}
return true, fmt.Sprintf("PASS:\t%s(%s)", call.Method, call.Arguments.String())
return !somethingMissing
}
// AssertNumberOfCalls asserts that the method was called expectedCalls times.
@ -671,7 +555,7 @@ func (m *Mock) AssertNumberOfCalls(t TestingT, methodName string, expectedCalls
actualCalls++
}
}
return assert.Equal(t, expectedCalls, actualCalls, fmt.Sprintf("Expected number of calls (%d) of method %s does not match the actual number of calls (%d).", expectedCalls, methodName, actualCalls))
return assert.Equal(t, expectedCalls, actualCalls, fmt.Sprintf("Expected number of calls (%d) does not match the actual number of calls (%d).", expectedCalls, actualCalls))
}
// AssertCalled asserts that the method was called.
@ -789,80 +673,34 @@ const (
Anything = "mock.Anything"
)
// AnythingOfTypeArgument contains the type of an argument
// for use when type checking. Used in [Arguments.Diff] and [Arguments.Assert].
//
// Deprecated: this is an implementation detail that must not be used. Use the [AnythingOfType] constructor instead, example:
//
// m.On("Do", mock.AnythingOfType("string"))
//
// All explicit type declarations can be replaced with interface{} as is expected by [Mock.On], example:
//
// func anyString interface{} {
// return mock.AnythingOfType("string")
// }
type AnythingOfTypeArgument = anythingOfTypeArgument
// anythingOfTypeArgument is a string that contains the type of an argument
// AnythingOfTypeArgument is a string that contains the type of an argument
// for use when type checking. Used in Diff and Assert.
type anythingOfTypeArgument string
type AnythingOfTypeArgument string
// AnythingOfType returns a special value containing the
// name of the type to check for. The type name will be matched against the type name returned by [reflect.Type.String].
//
// Used in Diff and Assert.
// AnythingOfType returns an AnythingOfTypeArgument object containing the
// name of the type to check for. Used in Diff and Assert.
//
// For example:
//
// args.Assert(t, AnythingOfType("string"), AnythingOfType("int"))
// Assert(t, AnythingOfType("string"), AnythingOfType("int"))
func AnythingOfType(t string) AnythingOfTypeArgument {
return anythingOfTypeArgument(t)
return AnythingOfTypeArgument(t)
}
// IsTypeArgument is a struct that contains the type of an argument
// for use when type checking. This is an alternative to [AnythingOfType].
// Used in [Arguments.Diff] and [Arguments.Assert].
// for use when type checking. This is an alternative to AnythingOfType.
// Used in Diff and Assert.
type IsTypeArgument struct {
t reflect.Type
t interface{}
}
// IsType returns an IsTypeArgument object containing the type to check for.
// You can provide a zero-value of the type to check. This is an
// alternative to [AnythingOfType]. Used in [Arguments.Diff] and [Arguments.Assert].
// alternative to AnythingOfType. Used in Diff and Assert.
//
// For example:
//
// args.Assert(t, IsType(""), IsType(0))
// Assert(t, IsType(""), IsType(0))
func IsType(t interface{}) *IsTypeArgument {
return &IsTypeArgument{t: reflect.TypeOf(t)}
}
// FunctionalOptionsArgument contains a list of functional options arguments
// expected for use when matching a list of arguments.
type FunctionalOptionsArgument struct {
values []interface{}
}
// String returns the string representation of FunctionalOptionsArgument
func (f *FunctionalOptionsArgument) String() string {
var name string
if len(f.values) > 0 {
name = "[]" + reflect.TypeOf(f.values[0]).String()
}
return strings.Replace(fmt.Sprintf("%#v", f.values), "[]interface {}", name, 1)
}
// FunctionalOptions returns an [FunctionalOptionsArgument] object containing
// the expected functional-options to check for.
//
// For example:
//
// args.Assert(t, FunctionalOptions(foo.Opt1("strValue"), foo.Opt2(613)))
func FunctionalOptions(values ...interface{}) *FunctionalOptionsArgument {
return &FunctionalOptionsArgument{
values: values,
}
return &IsTypeArgument{t: t}
}
// argumentMatcher performs custom argument matching, returning whether or
@ -908,11 +746,10 @@ func (f argumentMatcher) String() string {
// and false otherwise.
//
// Example:
// m.On("Do", MatchedBy(func(req *http.Request) bool { return req.Host == "example.com" }))
//
// m.On("Do", MatchedBy(func(req *http.Request) bool { return req.Host == "example.com" }))
//
// fn must be a function accepting a single argument (of the expected type)
// which returns a bool. If fn doesn't match the required signature,
// |fn|, must be a function accepting a single argument (of the expected type)
// which returns a bool. If |fn| doesn't match the required signature,
// MatchedBy() panics.
func MatchedBy(fn interface{}) argumentMatcher {
fnType := reflect.TypeOf(fn)
@ -948,8 +785,6 @@ func (args Arguments) Is(objects ...interface{}) bool {
return true
}
type outputRenderer func() string
// Diff gets a string describing the differences between the arguments
// and the specified objects.
//
@ -957,7 +792,7 @@ type outputRenderer func() string
func (args Arguments) Diff(objects []interface{}) (string, int) {
// TODO: could return string as error and nil for No difference
var outputBuilder strings.Builder
output := "\n"
var differences int
maxArgCount := len(args)
@ -965,118 +800,56 @@ func (args Arguments) Diff(objects []interface{}) (string, int) {
maxArgCount = len(objects)
}
outputRenderers := []outputRenderer{}
for i := 0; i < maxArgCount; i++ {
i := i
var actual, expected interface{}
var actualFmt, expectedFmt func() string
var actualFmt, expectedFmt string
if len(objects) <= i {
actual = "(Missing)"
actualFmt = func() string {
return "(Missing)"
}
actualFmt = "(Missing)"
} else {
actual = objects[i]
actualFmt = func() string {
return fmt.Sprintf("(%[1]T=%[1]v)", actual)
}
actualFmt = fmt.Sprintf("(%[1]T=%[1]v)", actual)
}
if len(args) <= i {
expected = "(Missing)"
expectedFmt = func() string {
return "(Missing)"
}
expectedFmt = "(Missing)"
} else {
expected = args[i]
expectedFmt = func() string {
return fmt.Sprintf("(%[1]T=%[1]v)", expected)
}
expectedFmt = fmt.Sprintf("(%[1]T=%[1]v)", expected)
}
if matcher, ok := expected.(argumentMatcher); ok {
var matches bool
func() {
defer func() {
if r := recover(); r != nil {
actualFmt = func() string {
return fmt.Sprintf("panic in argument matcher: %v", r)
}
}
}()
matches = matcher.Matches(actual)
}()
if matches {
outputRenderers = append(outputRenderers, func() string {
return fmt.Sprintf("\t%d: PASS: %s matched by %s\n", i, actualFmt(), matcher)
})
if matcher.Matches(actual) {
output = fmt.Sprintf("%s\t%d: PASS: %s matched by %s\n", output, i, actualFmt, matcher)
} else {
differences++
outputRenderers = append(outputRenderers, func() string {
return fmt.Sprintf("\t%d: FAIL: %s not matched by %s\n", i, actualFmt(), matcher)
})
output = fmt.Sprintf("%s\t%d: FAIL: %s not matched by %s\n", output, i, actualFmt, matcher)
}
} else if reflect.TypeOf(expected) == reflect.TypeOf((*AnythingOfTypeArgument)(nil)).Elem() {
// type checking
if reflect.TypeOf(actual).Name() != string(expected.(AnythingOfTypeArgument)) && reflect.TypeOf(actual).String() != string(expected.(AnythingOfTypeArgument)) {
// not match
differences++
output = fmt.Sprintf("%s\t%d: FAIL: type %s != type %s - %s\n", output, i, expected, reflect.TypeOf(actual).Name(), actualFmt)
}
} else if reflect.TypeOf(expected) == reflect.TypeOf((*IsTypeArgument)(nil)) {
t := expected.(*IsTypeArgument).t
if reflect.TypeOf(t) != reflect.TypeOf(actual) {
differences++
output = fmt.Sprintf("%s\t%d: FAIL: type %s != type %s - %s\n", output, i, reflect.TypeOf(t).Name(), reflect.TypeOf(actual).Name(), actualFmt)
}
} else {
switch expected := expected.(type) {
case anythingOfTypeArgument:
// type checking
if reflect.TypeOf(actual).Name() != string(expected) && reflect.TypeOf(actual).String() != string(expected) {
// not match
differences++
outputRenderers = append(outputRenderers, func() string {
return fmt.Sprintf("\t%d: FAIL: type %s != type %s - %s\n", i, expected, reflect.TypeOf(actual).Name(), actualFmt())
})
}
case *IsTypeArgument:
actualT := reflect.TypeOf(actual)
if actualT != expected.t {
differences++
outputRenderers = append(outputRenderers, func() string {
return fmt.Sprintf("\t%d: FAIL: type %s != type %s - %s\n", i, expected.t.Name(), actualT.Name(), actualFmt())
})
}
case *FunctionalOptionsArgument:
var name string
if len(expected.values) > 0 {
name = "[]" + reflect.TypeOf(expected.values[0]).String()
}
// normal checking
const tName = "[]interface{}"
if name != reflect.TypeOf(actual).String() && len(expected.values) != 0 {
differences++
outputRenderers = append(outputRenderers, func() string {
return fmt.Sprintf("\t%d: FAIL: type %s != type %s - %s\n", i, tName, reflect.TypeOf(actual).Name(), actualFmt())
})
} else {
if ef, af := assertOpts(expected.values, actual); ef == "" && af == "" {
// match
outputRenderers = append(outputRenderers, func() string {
return fmt.Sprintf("\t%d: PASS: %s == %s\n", i, tName, tName)
})
} else {
// not match
differences++
outputRenderers = append(outputRenderers, func() string {
return fmt.Sprintf("\t%d: FAIL: %s != %s\n", i, af, ef)
})
}
}
default:
if assert.ObjectsAreEqual(expected, Anything) || assert.ObjectsAreEqual(actual, Anything) || assert.ObjectsAreEqual(actual, expected) {
// match
outputRenderers = append(outputRenderers, func() string {
return fmt.Sprintf("\t%d: PASS: %s == %s\n", i, actualFmt(), expectedFmt())
})
} else {
// not match
differences++
outputRenderers = append(outputRenderers, func() string {
return fmt.Sprintf("\t%d: FAIL: %s != %s\n", i, actualFmt(), expectedFmt())
})
}
if assert.ObjectsAreEqual(expected, Anything) || assert.ObjectsAreEqual(actual, Anything) || assert.ObjectsAreEqual(actual, expected) {
// match
output = fmt.Sprintf("%s\t%d: PASS: %s == %s\n", output, i, actualFmt, expectedFmt)
} else {
// not match
differences++
output = fmt.Sprintf("%s\t%d: FAIL: %s != %s\n", output, i, actualFmt, expectedFmt)
}
}
@ -1086,12 +859,7 @@ func (args Arguments) Diff(objects []interface{}) (string, int) {
return "No differences.", differences
}
outputBuilder.WriteString("\n")
for _, r := range outputRenderers {
outputBuilder.WriteString(r())
}
return outputBuilder.String(), differences
return output, differences
}
// Assert compares the arguments with the specified objects and fails if
@ -1163,7 +931,7 @@ func (args Arguments) Error(index int) error {
return nil
}
if s, ok = obj.(error); !ok {
panic(fmt.Sprintf("assert: arguments: Error(%d) failed because object wasn't correct type: %v", index, obj))
panic(fmt.Sprintf("assert: arguments: Error(%d) failed because object wasn't correct type: %v", index, args.Get(index)))
}
return s
}
@ -1248,89 +1016,3 @@ var spewConfig = spew.ConfigState{
type tHelper interface {
Helper()
}
func assertOpts(expected, actual interface{}) (expectedFmt, actualFmt string) {
expectedOpts := reflect.ValueOf(expected)
actualOpts := reflect.ValueOf(actual)
var expectedFuncs []*runtime.Func
var expectedNames []string
for i := 0; i < expectedOpts.Len(); i++ {
f := runtimeFunc(expectedOpts.Index(i).Interface())
expectedFuncs = append(expectedFuncs, f)
expectedNames = append(expectedNames, funcName(f))
}
var actualFuncs []*runtime.Func
var actualNames []string
for i := 0; i < actualOpts.Len(); i++ {
f := runtimeFunc(actualOpts.Index(i).Interface())
actualFuncs = append(actualFuncs, f)
actualNames = append(actualNames, funcName(f))
}
if expectedOpts.Len() != actualOpts.Len() {
expectedFmt = fmt.Sprintf("%v", expectedNames)
actualFmt = fmt.Sprintf("%v", actualNames)
return
}
for i := 0; i < expectedOpts.Len(); i++ {
if !isFuncSame(expectedFuncs[i], actualFuncs[i]) {
expectedFmt = expectedNames[i]
actualFmt = actualNames[i]
return
}
expectedOpt := expectedOpts.Index(i).Interface()
actualOpt := actualOpts.Index(i).Interface()
ot := reflect.TypeOf(expectedOpt)
var expectedValues []reflect.Value
var actualValues []reflect.Value
if ot.NumIn() == 0 {
return
}
for i := 0; i < ot.NumIn(); i++ {
vt := ot.In(i).Elem()
expectedValues = append(expectedValues, reflect.New(vt))
actualValues = append(actualValues, reflect.New(vt))
}
reflect.ValueOf(expectedOpt).Call(expectedValues)
reflect.ValueOf(actualOpt).Call(actualValues)
for i := 0; i < ot.NumIn(); i++ {
if expectedArg, actualArg := expectedValues[i].Interface(), actualValues[i].Interface(); !assert.ObjectsAreEqual(expectedArg, actualArg) {
expectedFmt = fmt.Sprintf("%s(%T) -> %#v", expectedNames[i], expectedArg, expectedArg)
actualFmt = fmt.Sprintf("%s(%T) -> %#v", expectedNames[i], actualArg, actualArg)
return
}
}
}
return "", ""
}
func runtimeFunc(opt interface{}) *runtime.Func {
return runtime.FuncForPC(reflect.ValueOf(opt).Pointer())
}
func funcName(f *runtime.Func) string {
name := f.Name()
trimmed := strings.TrimSuffix(path.Base(name), path.Ext(name))
splitted := strings.Split(trimmed, ".")
if len(splitted) == 0 {
return trimmed
}
return splitted[len(splitted)-1]
}
func isFuncSame(f1, f2 *runtime.Func) bool {
f1File, f1Loc := f1.FileLine(f1.Entry())
f2File, f2Loc := f2.FileLine(f2.Entry())
return f1File == f2File && f1Loc == f2Loc
}

File diff suppressed because it is too large Load Diff

View File

@ -1,30 +1,27 @@
// Package require implements the same assertions as the `assert` package but
// stops test execution when a test fails.
//
// # Example Usage
// Example Usage
//
// The following is a complete example using require in a standard test function:
// import (
// "testing"
// "github.com/stretchr/testify/require"
// )
//
// import (
// "testing"
// "github.com/stretchr/testify/require"
// )
// func TestSomething(t *testing.T) {
//
// func TestSomething(t *testing.T) {
// var a string = "Hello"
// var b string = "Hello"
//
// var a string = "Hello"
// var b string = "Hello"
// require.Equal(t, a, b, "The two words should be the same.")
//
// require.Equal(t, a, b, "The two words should be the same.")
// }
//
// }
//
// # Assertions
// Assertions
//
// The `require` package have same global functions as in the `assert` package,
// but instead of returning a boolean result they call `t.FailNow()`.
// A consequence of this is that it must be called from the goroutine running
// the test function, not from other goroutines created during the test.
//
// Every assertion function also takes an optional string message as the final argument,
// allowing custom error messages to be appended to the message the assertion method outputs.

View File

@ -7,8 +7,6 @@ import (
)
func TestImplementsWrapper(t *testing.T) {
t.Parallel()
require := New(t)
require.Implements((*AssertionTesterInterface)(nil), new(AssertionTesterConformingObject))
@ -21,23 +19,7 @@ func TestImplementsWrapper(t *testing.T) {
}
}
func TestIsNotTypeWrapper(t *testing.T) {
t.Parallel()
require := New(t)
require.IsNotType(new(AssertionTesterNonConformingObject), new(AssertionTesterConformingObject))
mockT := new(MockT)
mockRequire := New(mockT)
mockRequire.IsNotType(new(AssertionTesterConformingObject), new(AssertionTesterConformingObject))
if !mockT.Failed {
t.Error("Check should fail")
}
}
func TestIsTypeWrapper(t *testing.T) {
t.Parallel()
require := New(t)
require.IsType(new(AssertionTesterConformingObject), new(AssertionTesterConformingObject))
@ -50,8 +32,6 @@ func TestIsTypeWrapper(t *testing.T) {
}
func TestEqualWrapper(t *testing.T) {
t.Parallel()
require := New(t)
require.Equal(1, 1)
@ -64,8 +44,6 @@ func TestEqualWrapper(t *testing.T) {
}
func TestNotEqualWrapper(t *testing.T) {
t.Parallel()
require := New(t)
require.NotEqual(1, 2)
@ -78,8 +56,6 @@ func TestNotEqualWrapper(t *testing.T) {
}
func TestExactlyWrapper(t *testing.T) {
t.Parallel()
require := New(t)
a := float32(1)
@ -97,8 +73,6 @@ func TestExactlyWrapper(t *testing.T) {
}
func TestNotNilWrapper(t *testing.T) {
t.Parallel()
require := New(t)
require.NotNil(t, new(AssertionTesterConformingObject))
@ -111,8 +85,6 @@ func TestNotNilWrapper(t *testing.T) {
}
func TestNilWrapper(t *testing.T) {
t.Parallel()
require := New(t)
require.Nil(nil)
@ -125,8 +97,6 @@ func TestNilWrapper(t *testing.T) {
}
func TestTrueWrapper(t *testing.T) {
t.Parallel()
require := New(t)
require.True(true)
@ -139,8 +109,6 @@ func TestTrueWrapper(t *testing.T) {
}
func TestFalseWrapper(t *testing.T) {
t.Parallel()
require := New(t)
require.False(false)
@ -153,8 +121,6 @@ func TestFalseWrapper(t *testing.T) {
}
func TestContainsWrapper(t *testing.T) {
t.Parallel()
require := New(t)
require.Contains("Hello World", "Hello")
@ -167,8 +133,6 @@ func TestContainsWrapper(t *testing.T) {
}
func TestNotContainsWrapper(t *testing.T) {
t.Parallel()
require := New(t)
require.NotContains("Hello World", "Hello!")
@ -181,8 +145,6 @@ func TestNotContainsWrapper(t *testing.T) {
}
func TestPanicsWrapper(t *testing.T) {
t.Parallel()
require := New(t)
require.Panics(func() {
panic("Panic!")
@ -197,8 +159,6 @@ func TestPanicsWrapper(t *testing.T) {
}
func TestNotPanicsWrapper(t *testing.T) {
t.Parallel()
require := New(t)
require.NotPanics(func() {})
@ -213,8 +173,6 @@ func TestNotPanicsWrapper(t *testing.T) {
}
func TestNoErrorWrapper(t *testing.T) {
t.Parallel()
require := New(t)
require.NoError(nil)
@ -227,8 +185,6 @@ func TestNoErrorWrapper(t *testing.T) {
}
func TestErrorWrapper(t *testing.T) {
t.Parallel()
require := New(t)
require.Error(errors.New("some error"))
@ -241,8 +197,6 @@ func TestErrorWrapper(t *testing.T) {
}
func TestErrorContainsWrapper(t *testing.T) {
t.Parallel()
require := New(t)
require.ErrorContains(errors.New("some error: another error"), "some error")
@ -255,8 +209,6 @@ func TestErrorContainsWrapper(t *testing.T) {
}
func TestEqualErrorWrapper(t *testing.T) {
t.Parallel()
require := New(t)
require.EqualError(errors.New("some error"), "some error")
@ -269,8 +221,6 @@ func TestEqualErrorWrapper(t *testing.T) {
}
func TestEmptyWrapper(t *testing.T) {
t.Parallel()
require := New(t)
require.Empty("")
@ -283,8 +233,6 @@ func TestEmptyWrapper(t *testing.T) {
}
func TestNotEmptyWrapper(t *testing.T) {
t.Parallel()
require := New(t)
require.NotEmpty("x")
@ -297,8 +245,6 @@ func TestNotEmptyWrapper(t *testing.T) {
}
func TestWithinDurationWrapper(t *testing.T) {
t.Parallel()
require := New(t)
a := time.Now()
b := a.Add(10 * time.Second)
@ -314,8 +260,6 @@ func TestWithinDurationWrapper(t *testing.T) {
}
func TestInDeltaWrapper(t *testing.T) {
t.Parallel()
require := New(t)
require.InDelta(1.001, 1, 0.01)
@ -328,8 +272,6 @@ func TestInDeltaWrapper(t *testing.T) {
}
func TestZeroWrapper(t *testing.T) {
t.Parallel()
require := New(t)
require.Zero(0)
@ -342,8 +284,6 @@ func TestZeroWrapper(t *testing.T) {
}
func TestNotZeroWrapper(t *testing.T) {
t.Parallel()
require := New(t)
require.NotZero(1)
@ -356,8 +296,6 @@ func TestNotZeroWrapper(t *testing.T) {
}
func TestJSONEqWrapper_EqualSONString(t *testing.T) {
t.Parallel()
mockT := new(MockT)
mockRequire := New(mockT)
@ -368,8 +306,6 @@ func TestJSONEqWrapper_EqualSONString(t *testing.T) {
}
func TestJSONEqWrapper_EquivalentButNotEqual(t *testing.T) {
t.Parallel()
mockT := new(MockT)
mockRequire := New(mockT)
@ -380,8 +316,6 @@ func TestJSONEqWrapper_EquivalentButNotEqual(t *testing.T) {
}
func TestJSONEqWrapper_HashOfArraysAndHashes(t *testing.T) {
t.Parallel()
mockT := new(MockT)
mockRequire := New(mockT)
@ -393,8 +327,6 @@ func TestJSONEqWrapper_HashOfArraysAndHashes(t *testing.T) {
}
func TestJSONEqWrapper_Array(t *testing.T) {
t.Parallel()
mockT := new(MockT)
mockRequire := New(mockT)
@ -405,8 +337,6 @@ func TestJSONEqWrapper_Array(t *testing.T) {
}
func TestJSONEqWrapper_HashAndArrayNotEquivalent(t *testing.T) {
t.Parallel()
mockT := new(MockT)
mockRequire := New(mockT)
@ -417,8 +347,6 @@ func TestJSONEqWrapper_HashAndArrayNotEquivalent(t *testing.T) {
}
func TestJSONEqWrapper_HashesNotEquivalent(t *testing.T) {
t.Parallel()
mockT := new(MockT)
mockRequire := New(mockT)
@ -429,8 +357,6 @@ func TestJSONEqWrapper_HashesNotEquivalent(t *testing.T) {
}
func TestJSONEqWrapper_ActualIsNotJSON(t *testing.T) {
t.Parallel()
mockT := new(MockT)
mockRequire := New(mockT)
@ -441,8 +367,6 @@ func TestJSONEqWrapper_ActualIsNotJSON(t *testing.T) {
}
func TestJSONEqWrapper_ExpectedIsNotJSON(t *testing.T) {
t.Parallel()
mockT := new(MockT)
mockRequire := New(mockT)
@ -453,8 +377,6 @@ func TestJSONEqWrapper_ExpectedIsNotJSON(t *testing.T) {
}
func TestJSONEqWrapper_ExpectedAndActualNotJSON(t *testing.T) {
t.Parallel()
mockT := new(MockT)
mockRequire := New(mockT)
@ -465,8 +387,6 @@ func TestJSONEqWrapper_ExpectedAndActualNotJSON(t *testing.T) {
}
func TestJSONEqWrapper_ArraysOfDifferentOrder(t *testing.T) {
t.Parallel()
mockT := new(MockT)
mockRequire := New(mockT)
@ -477,8 +397,6 @@ func TestJSONEqWrapper_ArraysOfDifferentOrder(t *testing.T) {
}
func TestYAMLEqWrapper_EqualYAMLString(t *testing.T) {
t.Parallel()
mockT := new(MockT)
mockRequire := New(mockT)
@ -489,8 +407,6 @@ func TestYAMLEqWrapper_EqualYAMLString(t *testing.T) {
}
func TestYAMLEqWrapper_EquivalentButNotEqual(t *testing.T) {
t.Parallel()
mockT := new(MockT)
mockRequire := New(mockT)
@ -501,8 +417,6 @@ func TestYAMLEqWrapper_EquivalentButNotEqual(t *testing.T) {
}
func TestYAMLEqWrapper_HashOfArraysAndHashes(t *testing.T) {
t.Parallel()
mockT := new(MockT)
mockRequire := New(mockT)
@ -539,8 +453,6 @@ array:
}
func TestYAMLEqWrapper_Array(t *testing.T) {
t.Parallel()
mockT := new(MockT)
mockRequire := New(mockT)
@ -551,8 +463,6 @@ func TestYAMLEqWrapper_Array(t *testing.T) {
}
func TestYAMLEqWrapper_HashAndArrayNotEquivalent(t *testing.T) {
t.Parallel()
mockT := new(MockT)
mockRequire := New(mockT)
@ -563,8 +473,6 @@ func TestYAMLEqWrapper_HashAndArrayNotEquivalent(t *testing.T) {
}
func TestYAMLEqWrapper_HashesNotEquivalent(t *testing.T) {
t.Parallel()
mockT := new(MockT)
mockRequire := New(mockT)
@ -575,8 +483,6 @@ func TestYAMLEqWrapper_HashesNotEquivalent(t *testing.T) {
}
func TestYAMLEqWrapper_ActualIsSimpleString(t *testing.T) {
t.Parallel()
mockT := new(MockT)
mockRequire := New(mockT)
@ -587,8 +493,6 @@ func TestYAMLEqWrapper_ActualIsSimpleString(t *testing.T) {
}
func TestYAMLEqWrapper_ExpectedIsSimpleString(t *testing.T) {
t.Parallel()
mockT := new(MockT)
mockRequire := New(mockT)
@ -599,8 +503,6 @@ func TestYAMLEqWrapper_ExpectedIsSimpleString(t *testing.T) {
}
func TestYAMLEqWrapper_ExpectedAndActualSimpleString(t *testing.T) {
t.Parallel()
mockT := new(MockT)
mockRequire := New(mockT)
@ -611,8 +513,6 @@ func TestYAMLEqWrapper_ExpectedAndActualSimpleString(t *testing.T) {
}
func TestYAMLEqWrapper_ArraysOfDifferentOrder(t *testing.T) {
t.Parallel()
mockT := new(MockT)
mockRequire := New(mockT)

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
{{ replace .Comment "assert." "require."}}
{{.Comment}}
func {{.DocInfo.Name}}(t TestingT, {{.Params}}) {
if h, ok := t.(tHelper); ok { h.Helper() }
if assert.{{.DocInfo.Name}}(t, {{.ForwardedParams}}) { return }

File diff suppressed because it is too large Load Diff

View File

@ -6,7 +6,7 @@ type TestingT interface {
FailNow()
}
type tHelper = interface {
type tHelper interface {
Helper()
}

View File

@ -5,8 +5,6 @@ import (
"errors"
"testing"
"time"
"github.com/stretchr/testify/assert"
)
// AssertionTesterInterface defines an interface to be used for testing assertion methods
@ -29,9 +27,6 @@ type MockT struct {
Failed bool
}
// Helper is like [testing.T.Helper] but does nothing.
func (MockT) Helper() {}
func (t *MockT) FailNow() {
t.Failed = true
}
@ -41,7 +36,6 @@ func (t *MockT) Errorf(format string, args ...interface{}) {
}
func TestImplements(t *testing.T) {
t.Parallel()
Implements(t, (*AssertionTesterInterface)(nil), new(AssertionTesterConformingObject))
@ -53,7 +47,6 @@ func TestImplements(t *testing.T) {
}
func TestIsType(t *testing.T) {
t.Parallel()
IsType(t, new(AssertionTesterConformingObject), new(AssertionTesterConformingObject))
@ -65,7 +58,6 @@ func TestIsType(t *testing.T) {
}
func TestEqual(t *testing.T) {
t.Parallel()
Equal(t, 1, 1)
@ -78,7 +70,6 @@ func TestEqual(t *testing.T) {
}
func TestNotEqual(t *testing.T) {
t.Parallel()
NotEqual(t, 1, 2)
mockT := new(MockT)
@ -89,7 +80,6 @@ func TestNotEqual(t *testing.T) {
}
func TestExactly(t *testing.T) {
t.Parallel()
a := float32(1)
b := float32(1)
@ -105,7 +95,6 @@ func TestExactly(t *testing.T) {
}
func TestNotNil(t *testing.T) {
t.Parallel()
NotNil(t, new(AssertionTesterConformingObject))
@ -117,7 +106,6 @@ func TestNotNil(t *testing.T) {
}
func TestNil(t *testing.T) {
t.Parallel()
Nil(t, nil)
@ -129,7 +117,6 @@ func TestNil(t *testing.T) {
}
func TestTrue(t *testing.T) {
t.Parallel()
True(t, true)
@ -141,7 +128,6 @@ func TestTrue(t *testing.T) {
}
func TestFalse(t *testing.T) {
t.Parallel()
False(t, false)
@ -153,7 +139,6 @@ func TestFalse(t *testing.T) {
}
func TestContains(t *testing.T) {
t.Parallel()
Contains(t, "Hello World", "Hello")
@ -165,7 +150,6 @@ func TestContains(t *testing.T) {
}
func TestNotContains(t *testing.T) {
t.Parallel()
NotContains(t, "Hello World", "Hello!")
@ -177,7 +161,6 @@ func TestNotContains(t *testing.T) {
}
func TestPanics(t *testing.T) {
t.Parallel()
Panics(t, func() {
panic("Panic!")
@ -191,7 +174,6 @@ func TestPanics(t *testing.T) {
}
func TestNotPanics(t *testing.T) {
t.Parallel()
NotPanics(t, func() {})
@ -205,7 +187,6 @@ func TestNotPanics(t *testing.T) {
}
func TestNoError(t *testing.T) {
t.Parallel()
NoError(t, nil)
@ -217,7 +198,6 @@ func TestNoError(t *testing.T) {
}
func TestError(t *testing.T) {
t.Parallel()
Error(t, errors.New("some error"))
@ -229,7 +209,6 @@ func TestError(t *testing.T) {
}
func TestErrorContains(t *testing.T) {
t.Parallel()
ErrorContains(t, errors.New("some error: another error"), "some error")
@ -241,7 +220,6 @@ func TestErrorContains(t *testing.T) {
}
func TestEqualError(t *testing.T) {
t.Parallel()
EqualError(t, errors.New("some error"), "some error")
@ -253,7 +231,6 @@ func TestEqualError(t *testing.T) {
}
func TestEmpty(t *testing.T) {
t.Parallel()
Empty(t, "")
@ -265,7 +242,6 @@ func TestEmpty(t *testing.T) {
}
func TestNotEmpty(t *testing.T) {
t.Parallel()
NotEmpty(t, "x")
@ -277,7 +253,6 @@ func TestNotEmpty(t *testing.T) {
}
func TestWithinDuration(t *testing.T) {
t.Parallel()
a := time.Now()
b := a.Add(10 * time.Second)
@ -292,7 +267,6 @@ func TestWithinDuration(t *testing.T) {
}
func TestInDelta(t *testing.T) {
t.Parallel()
InDelta(t, 1.001, 1, 0.01)
@ -304,7 +278,6 @@ func TestInDelta(t *testing.T) {
}
func TestZero(t *testing.T) {
t.Parallel()
Zero(t, "")
@ -316,7 +289,6 @@ func TestZero(t *testing.T) {
}
func TestNotZero(t *testing.T) {
t.Parallel()
NotZero(t, "x")
@ -328,8 +300,6 @@ func TestNotZero(t *testing.T) {
}
func TestJSONEq_EqualSONString(t *testing.T) {
t.Parallel()
mockT := new(MockT)
JSONEq(mockT, `{"hello": "world", "foo": "bar"}`, `{"hello": "world", "foo": "bar"}`)
if mockT.Failed {
@ -338,8 +308,6 @@ func TestJSONEq_EqualSONString(t *testing.T) {
}
func TestJSONEq_EquivalentButNotEqual(t *testing.T) {
t.Parallel()
mockT := new(MockT)
JSONEq(mockT, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`)
if mockT.Failed {
@ -348,8 +316,6 @@ func TestJSONEq_EquivalentButNotEqual(t *testing.T) {
}
func TestJSONEq_HashOfArraysAndHashes(t *testing.T) {
t.Parallel()
mockT := new(MockT)
JSONEq(mockT, "{\r\n\t\"numeric\": 1.5,\r\n\t\"array\": [{\"foo\": \"bar\"}, 1, \"string\", [\"nested\", \"array\", 5.5]],\r\n\t\"hash\": {\"nested\": \"hash\", \"nested_slice\": [\"this\", \"is\", \"nested\"]},\r\n\t\"string\": \"foo\"\r\n}",
"{\r\n\t\"numeric\": 1.5,\r\n\t\"hash\": {\"nested\": \"hash\", \"nested_slice\": [\"this\", \"is\", \"nested\"]},\r\n\t\"string\": \"foo\",\r\n\t\"array\": [{\"foo\": \"bar\"}, 1, \"string\", [\"nested\", \"array\", 5.5]]\r\n}")
@ -359,8 +325,6 @@ func TestJSONEq_HashOfArraysAndHashes(t *testing.T) {
}
func TestJSONEq_Array(t *testing.T) {
t.Parallel()
mockT := new(MockT)
JSONEq(mockT, `["foo", {"hello": "world", "nested": "hash"}]`, `["foo", {"nested": "hash", "hello": "world"}]`)
if mockT.Failed {
@ -369,8 +333,6 @@ func TestJSONEq_Array(t *testing.T) {
}
func TestJSONEq_HashAndArrayNotEquivalent(t *testing.T) {
t.Parallel()
mockT := new(MockT)
JSONEq(mockT, `["foo", {"hello": "world", "nested": "hash"}]`, `{"foo": "bar", {"nested": "hash", "hello": "world"}}`)
if !mockT.Failed {
@ -379,8 +341,6 @@ func TestJSONEq_HashAndArrayNotEquivalent(t *testing.T) {
}
func TestJSONEq_HashesNotEquivalent(t *testing.T) {
t.Parallel()
mockT := new(MockT)
JSONEq(mockT, `{"foo": "bar"}`, `{"foo": "bar", "hello": "world"}`)
if !mockT.Failed {
@ -389,8 +349,6 @@ func TestJSONEq_HashesNotEquivalent(t *testing.T) {
}
func TestJSONEq_ActualIsNotJSON(t *testing.T) {
t.Parallel()
mockT := new(MockT)
JSONEq(mockT, `{"foo": "bar"}`, "Not JSON")
if !mockT.Failed {
@ -399,8 +357,6 @@ func TestJSONEq_ActualIsNotJSON(t *testing.T) {
}
func TestJSONEq_ExpectedIsNotJSON(t *testing.T) {
t.Parallel()
mockT := new(MockT)
JSONEq(mockT, "Not JSON", `{"foo": "bar", "hello": "world"}`)
if !mockT.Failed {
@ -409,8 +365,6 @@ func TestJSONEq_ExpectedIsNotJSON(t *testing.T) {
}
func TestJSONEq_ExpectedAndActualNotJSON(t *testing.T) {
t.Parallel()
mockT := new(MockT)
JSONEq(mockT, "Not JSON", "Not JSON")
if !mockT.Failed {
@ -419,8 +373,6 @@ func TestJSONEq_ExpectedAndActualNotJSON(t *testing.T) {
}
func TestJSONEq_ArraysOfDifferentOrder(t *testing.T) {
t.Parallel()
mockT := new(MockT)
JSONEq(mockT, `["foo", {"hello": "world", "nested": "hash"}]`, `[{ "hello": "world", "nested": "hash"}, "foo"]`)
if !mockT.Failed {
@ -429,8 +381,6 @@ func TestJSONEq_ArraysOfDifferentOrder(t *testing.T) {
}
func TestYAMLEq_EqualYAMLString(t *testing.T) {
t.Parallel()
mockT := new(MockT)
YAMLEq(mockT, `{"hello": "world", "foo": "bar"}`, `{"hello": "world", "foo": "bar"}`)
if mockT.Failed {
@ -439,8 +389,6 @@ func TestYAMLEq_EqualYAMLString(t *testing.T) {
}
func TestYAMLEq_EquivalentButNotEqual(t *testing.T) {
t.Parallel()
mockT := new(MockT)
YAMLEq(mockT, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`)
if mockT.Failed {
@ -449,8 +397,6 @@ func TestYAMLEq_EquivalentButNotEqual(t *testing.T) {
}
func TestYAMLEq_HashOfArraysAndHashes(t *testing.T) {
t.Parallel()
mockT := new(MockT)
expected := `
numeric: 1.5
@ -484,8 +430,6 @@ array:
}
func TestYAMLEq_Array(t *testing.T) {
t.Parallel()
mockT := new(MockT)
YAMLEq(mockT, `["foo", {"hello": "world", "nested": "hash"}]`, `["foo", {"nested": "hash", "hello": "world"}]`)
if mockT.Failed {
@ -494,8 +438,6 @@ func TestYAMLEq_Array(t *testing.T) {
}
func TestYAMLEq_HashAndArrayNotEquivalent(t *testing.T) {
t.Parallel()
mockT := new(MockT)
YAMLEq(mockT, `["foo", {"hello": "world", "nested": "hash"}]`, `{"foo": "bar", {"nested": "hash", "hello": "world"}}`)
if !mockT.Failed {
@ -504,8 +446,6 @@ func TestYAMLEq_HashAndArrayNotEquivalent(t *testing.T) {
}
func TestYAMLEq_HashesNotEquivalent(t *testing.T) {
t.Parallel()
mockT := new(MockT)
YAMLEq(mockT, `{"foo": "bar"}`, `{"foo": "bar", "hello": "world"}`)
if !mockT.Failed {
@ -514,8 +454,6 @@ func TestYAMLEq_HashesNotEquivalent(t *testing.T) {
}
func TestYAMLEq_ActualIsSimpleString(t *testing.T) {
t.Parallel()
mockT := new(MockT)
YAMLEq(mockT, `{"foo": "bar"}`, "Simple String")
if !mockT.Failed {
@ -524,8 +462,6 @@ func TestYAMLEq_ActualIsSimpleString(t *testing.T) {
}
func TestYAMLEq_ExpectedIsSimpleString(t *testing.T) {
t.Parallel()
mockT := new(MockT)
YAMLEq(mockT, "Simple String", `{"foo": "bar", "hello": "world"}`)
if !mockT.Failed {
@ -534,8 +470,6 @@ func TestYAMLEq_ExpectedIsSimpleString(t *testing.T) {
}
func TestYAMLEq_ExpectedAndActualSimpleString(t *testing.T) {
t.Parallel()
mockT := new(MockT)
YAMLEq(mockT, "Simple String", "Simple String")
if mockT.Failed {
@ -544,8 +478,6 @@ func TestYAMLEq_ExpectedAndActualSimpleString(t *testing.T) {
}
func TestYAMLEq_ArraysOfDifferentOrder(t *testing.T) {
t.Parallel()
mockT := new(MockT)
YAMLEq(mockT, `["foo", {"hello": "world", "nested": "hash"}]`, `[{ "hello": "world", "nested": "hash"}, "foo"]`)
if !mockT.Failed {
@ -584,8 +516,6 @@ func ExampleComparisonAssertionFunc() {
}
func TestComparisonAssertionFunc(t *testing.T) {
t.Parallel()
type iface interface {
Name() string
}
@ -647,8 +577,6 @@ func ExampleValueAssertionFunc() {
}
func TestValueAssertionFunc(t *testing.T) {
t.Parallel()
tests := []struct {
name string
value interface{}
@ -695,8 +623,6 @@ func ExampleBoolAssertionFunc() {
}
func TestBoolAssertionFunc(t *testing.T) {
t.Parallel()
tests := []struct {
name string
value bool
@ -740,8 +666,6 @@ func ExampleErrorAssertionFunc() {
}
func TestErrorAssertionFunc(t *testing.T) {
t.Parallel()
tests := []struct {
name string
err error
@ -757,34 +681,3 @@ func TestErrorAssertionFunc(t *testing.T) {
})
}
}
func TestEventuallyWithTFalse(t *testing.T) {
t.Parallel()
mockT := new(MockT)
condition := func(collect *assert.CollectT) {
True(collect, false)
}
EventuallyWithT(mockT, condition, 100*time.Millisecond, 20*time.Millisecond)
True(t, mockT.Failed, "Check should fail")
}
func TestEventuallyWithTTrue(t *testing.T) {
t.Parallel()
mockT := new(MockT)
counter := 0
condition := func(collect *assert.CollectT) {
defer func() {
counter += 1
}()
True(collect, counter == 1)
}
EventuallyWithT(mockT, condition, 100*time.Millisecond, 20*time.Millisecond)
False(t, mockT.Failed, "Check should pass")
Equal(t, 2, counter, "Condition is expected to be called 2 times")
}

View File

@ -5,8 +5,6 @@
// or individual tests (depending on which interface(s) you
// implement).
//
// The suite package does not support parallel tests. See [issue 934].
//
// A testing suite is usually built by first extending the built-in
// suite functionality from suite.Suite in testify. Alternatively,
// you could reproduce that logic on your own if you wanted (you
@ -31,40 +29,37 @@
// Suite object has assertion methods.
//
// A crude example:
// // Basic imports
// import (
// "testing"
// "github.com/stretchr/testify/assert"
// "github.com/stretchr/testify/suite"
// )
//
// // Basic imports
// import (
// "testing"
// "github.com/stretchr/testify/assert"
// "github.com/stretchr/testify/suite"
// )
// // Define the suite, and absorb the built-in basic suite
// // functionality from testify - including a T() method which
// // returns the current testing context
// type ExampleTestSuite struct {
// suite.Suite
// VariableThatShouldStartAtFive int
// }
//
// // Define the suite, and absorb the built-in basic suite
// // functionality from testify - including a T() method which
// // returns the current testing context
// type ExampleTestSuite struct {
// suite.Suite
// VariableThatShouldStartAtFive int
// }
// // Make sure that VariableThatShouldStartAtFive is set to five
// // before each test
// func (suite *ExampleTestSuite) SetupTest() {
// suite.VariableThatShouldStartAtFive = 5
// }
//
// // Make sure that VariableThatShouldStartAtFive is set to five
// // before each test
// func (suite *ExampleTestSuite) SetupTest() {
// suite.VariableThatShouldStartAtFive = 5
// }
// // All methods that begin with "Test" are run as tests within a
// // suite.
// func (suite *ExampleTestSuite) TestExample() {
// assert.Equal(suite.T(), 5, suite.VariableThatShouldStartAtFive)
// suite.Equal(5, suite.VariableThatShouldStartAtFive)
// }
//
// // All methods that begin with "Test" are run as tests within a
// // suite.
// func (suite *ExampleTestSuite) TestExample() {
// assert.Equal(suite.T(), 5, suite.VariableThatShouldStartAtFive)
// suite.Equal(5, suite.VariableThatShouldStartAtFive)
// }
//
// // In order for 'go test' to run this suite, we need to create
// // a normal test function and pass our suite to suite.Run
// func TestExampleTestSuite(t *testing.T) {
// suite.Run(t, new(ExampleTestSuite))
// }
//
// [issue 934]: https://github.com/stretchr/testify/issues/934
// // In order for 'go test' to run this suite, we need to create
// // a normal test function and pass our suite to suite.Run
// func TestExampleTestSuite(t *testing.T) {
// suite.Run(t, new(ExampleTestSuite))
// }
package suite

View File

@ -7,7 +7,6 @@ import "testing"
type TestingSuite interface {
T() *testing.T
SetT(*testing.T)
SetS(suite TestingSuite)
}
// SetupAllSuite has a SetupSuite method, which will run before the
@ -52,15 +51,3 @@ type AfterTest interface {
type WithStats interface {
HandleStats(suiteName string, stats *SuiteInformation)
}
// SetupSubTest has a SetupSubTest method, which will run before each
// subtest in the suite.
type SetupSubTest interface {
SetupSubTest()
}
// TearDownSubTest has a TearDownSubTest method, which will run after
// each subtest in the suite have been run.
type TearDownSubTest interface {
TearDownSubTest()
}

View File

@ -16,30 +16,26 @@ type TestInformation struct {
}
func newSuiteInformation() *SuiteInformation {
testStats := make(map[string]*TestInformation)
return &SuiteInformation{
TestStats: make(map[string]*TestInformation),
TestStats: testStats,
}
}
func (s *SuiteInformation) start(testName string) {
if s == nil {
return
}
func (s SuiteInformation) start(testName string) {
s.TestStats[testName] = &TestInformation{
TestName: testName,
Start: time.Now(),
}
}
func (s *SuiteInformation) end(testName string, passed bool) {
if s == nil {
return
}
func (s SuiteInformation) end(testName string, passed bool) {
s.TestStats[testName].End = time.Now()
s.TestStats[testName].Passed = passed
}
func (s *SuiteInformation) Passed() bool {
func (s SuiteInformation) Passed() bool {
for _, stats := range s.TestStats {
if !stats.Passed {
return false

View File

@ -27,14 +27,3 @@ func TestPassedReturnsFalseWhenSomeTestFails(t *testing.T) {
assert.False(t, sinfo.Passed())
}
func TestPassedReturnsFalseWhenAllTestsFail(t *testing.T) {
sinfo := newSuiteInformation()
sinfo.TestStats = map[string]*TestInformation{
"Test1": {TestName: "Test1", Passed: false},
"Test2": {TestName: "Test2", Passed: false},
"Test3": {TestName: "Test3", Passed: false},
}
assert.False(t, sinfo.Passed())
}

View File

@ -7,7 +7,6 @@ import (
"reflect"
"regexp"
"runtime/debug"
"strings"
"sync"
"testing"
"time"
@ -16,19 +15,16 @@ import (
"github.com/stretchr/testify/require"
)
var allTestsFilter = func(_, _ string) (bool, error) { return true, nil }
var matchMethod = flag.String("testify.m", "", "regular expression to select tests of the testify suite to run")
// Suite is a basic testing suite with methods for storing and
// retrieving the current *testing.T context.
type Suite struct {
*assert.Assertions
mu sync.RWMutex
require *require.Assertions
t *testing.T
// Parent suite to have access to the implemented methods of parent struct
s TestingSuite
}
// T retrieves the current *testing.T context.
@ -47,18 +43,12 @@ func (suite *Suite) SetT(t *testing.T) {
suite.require = require.New(t)
}
// SetS needs to set the current test suite as parent
// to get access to the parent methods
func (suite *Suite) SetS(s TestingSuite) {
suite.s = s
}
// Require returns a require context for suite.
func (suite *Suite) Require() *require.Assertions {
suite.mu.Lock()
defer suite.mu.Unlock()
if suite.require == nil {
panic("'Require' must not be called before 'Run' or 'SetT'")
suite.require = require.New(suite.T())
}
return suite.require
}
@ -72,19 +62,13 @@ func (suite *Suite) Assert() *assert.Assertions {
suite.mu.Lock()
defer suite.mu.Unlock()
if suite.Assertions == nil {
panic("'Assert' must not be called before 'Run' or 'SetT'")
suite.Assertions = assert.New(suite.T())
}
return suite.Assertions
}
func recoverAndFailOnPanic(t *testing.T) {
t.Helper()
func failOnPanic(t *testing.T) {
r := recover()
failOnPanic(t, r)
}
func failOnPanic(t *testing.T, r interface{}) {
t.Helper()
if r != nil {
t.Errorf("test panicked: %v\n%s", r, debug.Stack())
t.FailNow()
@ -97,80 +81,67 @@ func failOnPanic(t *testing.T, r interface{}) {
// Provides compatibility with go test pkg -run TestSuite/TestName/SubTestName.
func (suite *Suite) Run(name string, subtest func()) bool {
oldT := suite.T()
defer suite.SetT(oldT)
return oldT.Run(name, func(t *testing.T) {
suite.SetT(t)
defer suite.SetT(oldT)
defer recoverAndFailOnPanic(t)
if setupSubTest, ok := suite.s.(SetupSubTest); ok {
setupSubTest.SetupSubTest()
}
if tearDownSubTest, ok := suite.s.(TearDownSubTest); ok {
defer tearDownSubTest.TearDownSubTest()
}
subtest()
})
}
type test = struct {
name string
run func(t *testing.T)
}
// Run takes a testing suite and runs all of the tests attached
// to it.
func Run(t *testing.T, suite TestingSuite) {
defer recoverAndFailOnPanic(t)
defer failOnPanic(t)
suite.SetT(t)
suite.SetS(suite)
var suiteSetupDone bool
var stats *SuiteInformation
if _, ok := suite.(WithStats); ok {
stats = newSuiteInformation()
}
var tests []test
tests := []testing.InternalTest{}
methodFinder := reflect.TypeOf(suite)
suiteName := methodFinder.Elem().Name()
var matchMethodRE *regexp.Regexp
if *matchMethod != "" {
var err error
matchMethodRE, err = regexp.Compile(*matchMethod)
if err != nil {
fmt.Fprintf(os.Stderr, "testify: invalid regexp for -m: %s\n", err)
os.Exit(1)
}
}
for i := 0; i < methodFinder.NumMethod(); i++ {
method := methodFinder.Method(i)
if !strings.HasPrefix(method.Name, "Test") {
continue
ok, err := methodFilter(method.Name)
if err != nil {
fmt.Fprintf(os.Stderr, "testify: invalid regexp for -m: %s\n", err)
os.Exit(1)
}
// Apply -testify.m filter
if matchMethodRE != nil && !matchMethodRE.MatchString(method.Name) {
if !ok {
continue
}
test := test{
name: method.Name,
run: func(t *testing.T) {
if !suiteSetupDone {
if stats != nil {
stats.Start = time.Now()
}
if setupAllSuite, ok := suite.(SetupAllSuite); ok {
setupAllSuite.SetupSuite()
}
suiteSetupDone = true
}
test := testing.InternalTest{
Name: method.Name,
F: func(t *testing.T) {
parentT := suite.T()
suite.SetT(t)
defer recoverAndFailOnPanic(t)
defer failOnPanic(t)
defer func() {
t.Helper()
r := recover()
stats.end(method.Name, !t.Failed() && r == nil)
if stats != nil {
passed := !t.Failed()
stats.end(method.Name, passed)
}
if afterTestSuite, ok := suite.(AfterTest); ok {
afterTestSuite.AfterTest(suiteName, method.Name)
@ -181,7 +152,6 @@ func Run(t *testing.T, suite TestingSuite) {
}
suite.SetT(parentT)
failOnPanic(t, r)
}()
if setupTestSuite, ok := suite.(SetupTestSuite); ok {
@ -191,47 +161,59 @@ func Run(t *testing.T, suite TestingSuite) {
beforeTestSuite.BeforeTest(methodFinder.Elem().Name(), method.Name)
}
stats.start(method.Name)
if stats != nil {
stats.start(method.Name)
}
method.Func.Call([]reflect.Value{reflect.ValueOf(suite)})
},
}
tests = append(tests, test)
}
if suiteSetupDone {
defer func() {
if tearDownAllSuite, ok := suite.(TearDownAllSuite); ok {
tearDownAllSuite.TearDownSuite()
}
if len(tests) == 0 {
return
if suiteWithStats, measureStats := suite.(WithStats); measureStats {
stats.End = time.Now()
suiteWithStats.HandleStats(suiteName, stats)
}
}()
}
if stats != nil {
stats.Start = time.Now()
}
if setupAllSuite, ok := suite.(SetupAllSuite); ok {
setupAllSuite.SetupSuite()
}
defer func() {
if tearDownAllSuite, ok := suite.(TearDownAllSuite); ok {
tearDownAllSuite.TearDownSuite()
}
if suiteWithStats, measureStats := suite.(WithStats); measureStats {
stats.End = time.Now()
suiteWithStats.HandleStats(suiteName, stats)
}
}()
runTests(t, tests)
}
func runTests(t *testing.T, tests []test) {
// Filtering method according to set regular expression
// specified command-line argument -m
func methodFilter(name string) (bool, error) {
if ok, _ := regexp.MatchString("^Test", name); !ok {
return false, nil
}
return regexp.MatchString(*matchMethod, name)
}
func runTests(t testing.TB, tests []testing.InternalTest) {
if len(tests) == 0 {
t.Log("warning: no tests to run")
return
}
r, ok := t.(runner)
if !ok { // backwards compatibility with Go 1.6 and below
if !testing.RunTests(allTestsFilter, tests) {
t.Fail()
}
return
}
for _, test := range tests {
t.Run(test.name, test.run)
r.Run(test.Name, test.F)
}
}
type runner interface {
Run(name string, f func(t *testing.T)) bool
}

View File

@ -4,7 +4,7 @@ import (
"bytes"
"errors"
"flag"
"io"
"io/ioutil"
"math/rand"
"os"
"os/exec"
@ -16,30 +16,25 @@ import (
"github.com/stretchr/testify/require"
)
// allTestsFilter is a yes filter for testing.RunTests
func allTestsFilter(pat, str string) (bool, error) {
return true, nil
}
// SuiteRequireTwice is intended to test the usage of suite.Require in two
// different tests
type SuiteRequireTwice struct{ Suite }
// TestSuiteRequireTwice checks for regressions of issue #149 where
// suite.requirements was not initialized in suite.SetT()
// suite.requirements was not initialised in suite.SetT()
// A regression would result on these tests panicking rather than failing.
func TestSuiteRequireTwice(t *testing.T) {
ok := testing.RunTests(
allTestsFilter,
[]testing.InternalTest{{
Name: t.Name() + "/SuiteRequireTwice",
Name: "TestSuiteRequireTwice",
F: func(t *testing.T) {
suite := new(SuiteRequireTwice)
Run(t, suite)
},
}},
)
assert.False(t, ok)
assert.Equal(t, false, ok)
}
func (s *SuiteRequireTwice) TestRequireOne() {
@ -109,31 +104,31 @@ func TestSuiteRecoverPanic(t *testing.T) {
ok := true
panickingTests := []testing.InternalTest{
{
Name: t.Name() + "/InSetupSuite",
Name: "TestPanicInSetupSuite",
F: func(t *testing.T) { Run(t, &panickingSuite{panicInSetupSuite: true}) },
},
{
Name: t.Name() + "/InSetupTest",
Name: "TestPanicInSetupTest",
F: func(t *testing.T) { Run(t, &panickingSuite{panicInSetupTest: true}) },
},
{
Name: t.Name() + "InBeforeTest",
Name: "TestPanicInBeforeTest",
F: func(t *testing.T) { Run(t, &panickingSuite{panicInBeforeTest: true}) },
},
{
Name: t.Name() + "/InTest",
Name: "TestPanicInTest",
F: func(t *testing.T) { Run(t, &panickingSuite{panicInTest: true}) },
},
{
Name: t.Name() + "/InAfterTest",
Name: "TestPanicInAfterTest",
F: func(t *testing.T) { Run(t, &panickingSuite{panicInAfterTest: true}) },
},
{
Name: t.Name() + "/InTearDownTest",
Name: "TestPanicInTearDownTest",
F: func(t *testing.T) { Run(t, &panickingSuite{panicInTearDownTest: true}) },
},
{
Name: t.Name() + "/InTearDownSuite",
Name: "TestPanicInTearDownSuite",
F: func(t *testing.T) { Run(t, &panickingSuite{panicInTearDownSuite: true}) },
},
}
@ -156,19 +151,14 @@ type SuiteTester struct {
Suite
// Keep counts of how many times each method is run.
SetupSuiteRunCount int
TearDownSuiteRunCount int
SetupTestRunCount int
TearDownTestRunCount int
TestOneRunCount int
TestTwoRunCount int
TestSubtestRunCount int
NonTestMethodRunCount int
SetupSubTestRunCount int
TearDownSubTestRunCount int
SetupSubTestNames []string
TearDownSubTestNames []string
SetupSuiteRunCount int
TearDownSuiteRunCount int
SetupTestRunCount int
TearDownTestRunCount int
TestOneRunCount int
TestTwoRunCount int
TestSubtestRunCount int
NonTestMethodRunCount int
SuiteNameBefore []string
TestNameBefore []string
@ -265,16 +255,6 @@ func (suite *SuiteTester) TestSubtest() {
}
}
func (suite *SuiteTester) TearDownSubTest() {
suite.TearDownSubTestNames = append(suite.TearDownSubTestNames, suite.T().Name())
suite.TearDownSubTestRunCount++
}
func (suite *SuiteTester) SetupSubTest() {
suite.SetupSubTestNames = append(suite.SetupSubTestNames, suite.T().Name())
suite.SetupSubTestRunCount++
}
type SuiteSkipTester struct {
// Include our basic suite logic.
Suite
@ -311,13 +291,13 @@ func TestRunSuite(t *testing.T) {
// The suite was only run once, so the SetupSuite and TearDownSuite
// methods should have each been run only once.
assert.Equal(t, 1, suiteTester.SetupSuiteRunCount)
assert.Equal(t, 1, suiteTester.TearDownSuiteRunCount)
assert.Equal(t, suiteTester.SetupSuiteRunCount, 1)
assert.Equal(t, suiteTester.TearDownSuiteRunCount, 1)
assert.Len(t, suiteTester.SuiteNameAfter, 4)
assert.Len(t, suiteTester.SuiteNameBefore, 4)
assert.Len(t, suiteTester.TestNameAfter, 4)
assert.Len(t, suiteTester.TestNameBefore, 4)
assert.Equal(t, len(suiteTester.SuiteNameAfter), 4)
assert.Equal(t, len(suiteTester.SuiteNameBefore), 4)
assert.Equal(t, len(suiteTester.TestNameAfter), 4)
assert.Equal(t, len(suiteTester.TestNameBefore), 4)
assert.Contains(t, suiteTester.TestNameAfter, "TestOne")
assert.Contains(t, suiteTester.TestNameAfter, "TestTwo")
@ -329,12 +309,6 @@ func TestRunSuite(t *testing.T) {
assert.Contains(t, suiteTester.TestNameBefore, "TestSkip")
assert.Contains(t, suiteTester.TestNameBefore, "TestSubtest")
assert.Contains(t, suiteTester.SetupSubTestNames, "TestRunSuite/TestSubtest/first")
assert.Contains(t, suiteTester.SetupSubTestNames, "TestRunSuite/TestSubtest/second")
assert.Contains(t, suiteTester.TearDownSubTestNames, "TestRunSuite/TestSubtest/first")
assert.Contains(t, suiteTester.TearDownSubTestNames, "TestRunSuite/TestSubtest/second")
for _, suiteName := range suiteTester.SuiteNameAfter {
assert.Equal(t, "SuiteTester", suiteName)
}
@ -354,20 +328,17 @@ func TestRunSuite(t *testing.T) {
// There are four test methods (TestOne, TestTwo, TestSkip, and TestSubtest), so
// the SetupTest and TearDownTest methods (which should be run once for
// each test) should have been run four times.
assert.Equal(t, 4, suiteTester.SetupTestRunCount)
assert.Equal(t, 4, suiteTester.TearDownTestRunCount)
assert.Equal(t, suiteTester.SetupTestRunCount, 4)
assert.Equal(t, suiteTester.TearDownTestRunCount, 4)
// Each test should have been run once.
assert.Equal(t, 1, suiteTester.TestOneRunCount)
assert.Equal(t, 1, suiteTester.TestTwoRunCount)
assert.Equal(t, 1, suiteTester.TestSubtestRunCount)
assert.Equal(t, 2, suiteTester.TearDownSubTestRunCount)
assert.Equal(t, 2, suiteTester.SetupSubTestRunCount)
assert.Equal(t, suiteTester.TestOneRunCount, 1)
assert.Equal(t, suiteTester.TestTwoRunCount, 1)
assert.Equal(t, suiteTester.TestSubtestRunCount, 1)
// Methods that don't match the test method identifier shouldn't
// have been run at all.
assert.Equal(t, 0, suiteTester.NonTestMethodRunCount)
assert.Equal(t, suiteTester.NonTestMethodRunCount, 0)
suiteSkipTester := new(SuiteSkipTester)
Run(t, suiteSkipTester)
@ -375,8 +346,8 @@ func TestRunSuite(t *testing.T) {
// The suite was only run once, so the SetupSuite and TearDownSuite
// methods should have each been run only once, even though SetupSuite
// called Skip()
assert.Equal(t, 1, suiteSkipTester.SetupSuiteRunCount)
assert.Equal(t, 1, suiteSkipTester.TearDownSuiteRunCount)
assert.Equal(t, suiteSkipTester.SetupSuiteRunCount, 1)
assert.Equal(t, suiteSkipTester.TearDownSuiteRunCount, 1)
}
@ -445,7 +416,7 @@ func (sc *StdoutCapture) StopCapture() (string, error) {
}
os.Stdout.Close()
os.Stdout = sc.oldStdout
bytes, err := io.ReadAll(sc.readPipe)
bytes, err := ioutil.ReadAll(sc.readPipe)
if err != nil {
return "", err
}
@ -456,7 +427,7 @@ func TestSuiteLogging(t *testing.T) {
suiteLoggingTester := new(SuiteLoggingTester)
capture := StdoutCapture{}
internalTest := testing.InternalTest{
Name: t.Name() + "/SuiteLoggingTester",
Name: "SomeTest",
F: func(subT *testing.T) {
Run(subT, suiteLoggingTester)
},
@ -497,7 +468,7 @@ func (s *CallOrderSuite) SetupSuite() {
func (s *CallOrderSuite) TearDownSuite() {
s.call("TearDownSuite")
assert.Equal(s.T(), "SetupSuite;SetupTest;Test A;SetupSubTest;SubTest A1;TearDownSubTest;SetupSubTest;SubTest A2;TearDownSubTest;TearDownTest;SetupTest;Test B;SetupSubTest;SubTest B1;TearDownSubTest;SetupSubTest;SubTest B2;TearDownSubTest;TearDownTest;TearDownSuite", strings.Join(s.callOrder, ";"))
assert.Equal(s.T(), "SetupSuite;SetupTest;Test A;TearDownTest;SetupTest;Test B;TearDownTest;TearDownSuite", strings.Join(s.callOrder, ";"))
}
func (s *CallOrderSuite) SetupTest() {
s.call("SetupTest")
@ -507,32 +478,12 @@ func (s *CallOrderSuite) TearDownTest() {
s.call("TearDownTest")
}
func (s *CallOrderSuite) SetupSubTest() {
s.call("SetupSubTest")
}
func (s *CallOrderSuite) TearDownSubTest() {
s.call("TearDownSubTest")
}
func (s *CallOrderSuite) Test_A() {
s.call("Test A")
s.Run("SubTest A1", func() {
s.call("SubTest A1")
})
s.Run("SubTest A2", func() {
s.call("SubTest A2")
})
}
func (s *CallOrderSuite) Test_B() {
s.call("Test B")
s.Run("SubTest B1", func() {
s.call("SubTest B1")
})
s.Run("SubTest B2", func() {
s.call("SubTest B2")
})
}
type suiteWithStats struct {
@ -550,37 +501,19 @@ func (s *suiteWithStats) TestSomething() {
s.Equal(1, 1)
}
func (s *suiteWithStats) TestPanic() {
panic("oops")
}
func TestSuiteWithStats(t *testing.T) {
suiteWithStats := new(suiteWithStats)
suiteSuccess := testing.RunTests(allTestsFilter, []testing.InternalTest{
{
Name: t.Name() + "/suiteWithStats",
F: func(t *testing.T) {
Run(t, suiteWithStats)
},
},
})
require.False(t, suiteSuccess, "suiteWithStats should report test failure because of panic in TestPanic")
Run(t, suiteWithStats)
assert.True(t, suiteWithStats.wasCalled)
assert.NotZero(t, suiteWithStats.stats.Start)
assert.NotZero(t, suiteWithStats.stats.End)
assert.False(t, suiteWithStats.stats.Passed())
assert.True(t, suiteWithStats.stats.Passed())
testStats := suiteWithStats.stats.TestStats
assert.NotZero(t, testStats["TestSomething"].Start)
assert.NotZero(t, testStats["TestSomething"].End)
assert.True(t, testStats["TestSomething"].Passed)
assert.NotZero(t, testStats["TestPanic"].Start)
assert.NotZero(t, testStats["TestPanic"].End)
assert.False(t, testStats["TestPanic"].Passed)
testStats := suiteWithStats.stats.TestStats["TestSomething"]
assert.NotZero(t, testStats.Start)
assert.NotZero(t, testStats.End)
assert.True(t, testStats.Passed)
}
// FailfastSuite will test the behavior when running with the failfast flag
@ -602,51 +535,21 @@ func TestFailfastSuite(t *testing.T) {
ok := testing.RunTests(
allTestsFilter,
[]testing.InternalTest{{
Name: t.Name() + "/FailfastSuite",
Name: "TestFailfastSuite",
F: func(t *testing.T) {
Run(t, s)
},
}},
)
assert.False(t, ok)
var expect []string
assert.Equal(t, false, ok)
if failFast {
// Test A Fails and because we are running with failfast Test B never runs and we proceed straight to TearDownSuite
expect = []string{"SetupSuite", "SetupTest", "Test A Fails", "TearDownTest", "TearDownSuite"}
assert.Equal(t, "SetupSuite;SetupTest;Test A Fails;TearDownTest;TearDownSuite", strings.Join(s.callOrder, ";"))
} else {
// Test A Fails and because we are running without failfast we continue and run Test B and then proceed to TearDownSuite
expect = []string{"SetupSuite", "SetupTest", "Test A Fails", "TearDownTest", "SetupTest", "Test B Passes", "TearDownTest", "TearDownSuite"}
assert.Equal(t, "SetupSuite;SetupTest;Test A Fails;TearDownTest;SetupTest;Test B Passes;TearDownTest;TearDownSuite", strings.Join(s.callOrder, ";"))
}
callOrderAssert(t, expect, s.callOrder)
}
type tHelper interface {
Helper()
}
// callOrderAssert is a help with confirms that asserts that expect
// matches one or more times in callOrder. This makes it compatible
// with go test flag -count=X where X > 1.
func callOrderAssert(t *testing.T, expect, callOrder []string) {
var ti interface{} = t
if h, ok := ti.(tHelper); ok {
h.Helper()
}
callCount := len(callOrder)
expectCount := len(expect)
if callCount > expectCount && callCount%expectCount == 0 {
// Command line flag -count=X where X > 1.
for len(callOrder) >= expectCount {
assert.Equal(t, expect, callOrder[:expectCount])
callOrder = callOrder[expectCount:]
}
return
}
assert.Equal(t, expect, callOrder)
}
func TestFailfastSuiteFailFastOn(t *testing.T) {
// To test this with failfast on (and isolated from other intended test failures in our test suite) we launch it in its own process
cmd := exec.Command("go", "test", "-v", "-race", "-run", "TestFailfastSuite", "-failfast")
@ -684,70 +587,3 @@ func (s *FailfastSuite) Test_B_Passes() {
s.call("Test B Passes")
s.Require().True(true)
}
type subtestPanicSuite struct {
Suite
inTearDownSuite bool
inTearDownTest bool
inTearDownSubTest bool
}
func (s *subtestPanicSuite) TearDownSuite() {
s.inTearDownSuite = true
}
func (s *subtestPanicSuite) TearDownTest() {
s.inTearDownTest = true
}
func (s *subtestPanicSuite) TearDownSubTest() {
s.inTearDownSubTest = true
}
func (s *subtestPanicSuite) TestSubtestPanic() {
ok := s.Run("subtest", func() {
panic("panic")
})
s.False(ok, "subtest failure is expected")
}
func TestSubtestPanic(t *testing.T) {
suite := new(subtestPanicSuite)
ok := testing.RunTests(
allTestsFilter,
[]testing.InternalTest{{
Name: t.Name() + "/subtestPanicSuite",
F: func(t *testing.T) {
Run(t, suite)
},
}},
)
assert.False(t, ok, "TestSubtestPanic/subtest should make the testsuite fail")
assert.True(t, suite.inTearDownSubTest)
assert.True(t, suite.inTearDownTest)
assert.True(t, suite.inTearDownSuite)
}
type unInitializedSuite struct {
Suite
}
// TestUnInitializedSuites asserts the behavior of the suite methods when the
// suite is not initialized
func TestUnInitializedSuites(t *testing.T) {
t.Run("should panic on Require", func(t *testing.T) {
suite := new(unInitializedSuite)
assert.Panics(t, func() {
suite.Require().True(true)
})
})
t.Run("should panic on Assert", func(t *testing.T) {
suite := new(unInitializedSuite)
assert.Panics(t, func() {
suite.Assert().True(true)
})
})
}