mirror of https://github.com/stretchr/testify.git
Compare commits
No commits in common. "master" and "v1.7.0" have entirely different histories.
|
@ -1,12 +0,0 @@
|
||||||
#!/bin/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
|
|
|
@ -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 -->
|
|
|
@ -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? -->
|
|
|
@ -1,10 +0,0 @@
|
||||||
version: 2
|
|
||||||
updates:
|
|
||||||
- package-ecosystem: gomod
|
|
||||||
directory: /
|
|
||||||
schedule:
|
|
||||||
interval: daily
|
|
||||||
- package-ecosystem: github-actions
|
|
||||||
directory: /
|
|
||||||
schedule:
|
|
||||||
interval: daily
|
|
|
@ -1,41 +0,0 @@
|
||||||
name: All builds
|
|
||||||
on: [push, pull_request]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
go_version:
|
|
||||||
- stable
|
|
||||||
- oldstable
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Setup Go
|
|
||||||
uses: actions/setup-go@v5
|
|
||||||
with:
|
|
||||||
go-version: ${{ matrix.go_version }}
|
|
||||||
- run: npm install -g mdsf-cli
|
|
||||||
- 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 ./...
|
|
|
@ -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
|
|
|
@ -22,9 +22,3 @@ _testmain.go
|
||||||
*.exe
|
*.exe
|
||||||
|
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
||||||
# Output of "go test -c"
|
|
||||||
/assert/assert.test
|
|
||||||
/require/require.test
|
|
||||||
/suite/suite.test
|
|
||||||
/mock/mock.test
|
|
||||||
|
|
12
.mdsf.json
12
.mdsf.json
|
@ -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"
|
|
||||||
]
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
language: go
|
||||||
|
os: linux
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
include:
|
||||||
|
- go: "1.13.x"
|
||||||
|
env: GO111MODULE=off
|
||||||
|
- go: "1.13.x"
|
||||||
|
env: GO111MODULE=on
|
||||||
|
- go: "1.14.x"
|
||||||
|
env: GO111MODULE=off
|
||||||
|
- go: "1.14.x"
|
||||||
|
env: GO111MODULE=on
|
||||||
|
- go: master
|
||||||
|
env: GO111MODULE=on
|
||||||
|
- go: master
|
||||||
|
env: GO111MODULE=off
|
||||||
|
script:
|
||||||
|
- ./.travis.gogenerate.sh
|
||||||
|
- ./.travis.gofmt.sh
|
||||||
|
- ./.travis.govet.sh
|
||||||
|
- go test -v -race ./...
|
12
EMERITUS.md
12
EMERITUS.md
|
@ -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.
|
|
|
@ -3,15 +3,7 @@
|
||||||
The individuals listed below are active in the project and have the ability to approve and merge
|
The individuals listed below are active in the project and have the ability to approve and merge
|
||||||
pull requests.
|
pull requests.
|
||||||
|
|
||||||
|
* @glesica
|
||||||
* @boyan-soubachov
|
* @boyan-soubachov
|
||||||
* @dolmen
|
* @mvdkleijn
|
||||||
* @MovieStoreGuy
|
|
||||||
* @brackendawson
|
|
||||||
|
|
||||||
## Approvers
|
|
||||||
|
|
||||||
The individuals listed below are active in the project and have the ability to approve pull
|
|
||||||
requests.
|
|
||||||
|
|
||||||
* @arjunmahishi
|
|
||||||
* @ccoVeille
|
|
||||||
|
|
92
README.md
92
README.md
|
@ -1,11 +1,9 @@
|
||||||
Testify - Thou Shalt Write Tests
|
Testify - Thou Shalt Write Tests
|
||||||
================================
|
================================
|
||||||
|
|
||||||
> [!NOTE]
|
ℹ️ 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
|
||||||
> 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).
|
|
||||||
|
|
||||||
[](https://github.com/stretchr/testify/actions/workflows/main.yml) [](https://goreportcard.com/report/github.com/stretchr/testify) [](https://pkg.go.dev/github.com/stretchr/testify)
|
[](https://travis-ci.org/stretchr/testify) [](https://goreportcard.com/report/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.
|
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:
|
Get started:
|
||||||
|
|
||||||
* Install testify with [one line of code](#installation), or [update it with another](#staying-up-to-date)
|
* 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
|
* For an introduction to writing test code in Go, see http://golang.org/doc/code.html#Testing
|
||||||
* Check out the API Documentation https://pkg.go.dev/github.com/stretchr/testify
|
* Check out the API Documentation http://godoc.org/github.com/stretchr/testify
|
||||||
* Use [testifylint](https://github.com/Antonboom/testifylint) (via [golangci-lint](https://golangci-lint.run/)) to avoid common mistakes
|
* To make your testing life easier, check out our other project, [gorc](http://github.com/stretchr/gorc)
|
||||||
* A little about [Test-Driven Development (TDD)](https://en.wikipedia.org/wiki/Test-driven_development)
|
* 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.
|
The `assert` package provides some helpful methods that allow you to write better test code in Go.
|
||||||
|
@ -39,11 +39,11 @@ package yours
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestSomething(t *testing.T) {
|
func TestSomething(t *testing.T) {
|
||||||
|
|
||||||
// assert equality
|
// assert equality
|
||||||
assert.Equal(t, 123, 123, "they should be equal")
|
assert.Equal(t, 123, 123, "they should be equal")
|
||||||
|
|
||||||
|
@ -55,10 +55,13 @@ func TestSomething(t *testing.T) {
|
||||||
|
|
||||||
// assert for not nil (good when you expect something)
|
// assert for not nil (good when you expect something)
|
||||||
if assert.NotNil(t, object) {
|
if assert.NotNil(t, object) {
|
||||||
|
|
||||||
// now we know that object isn't nil, we are safe to make
|
// now we know that object isn't nil, we are safe to make
|
||||||
// further assertions without causing any errors
|
// further assertions without causing any errors
|
||||||
assert.Equal(t, "Something", object.Value)
|
assert.Equal(t, "Something", object.Value)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -72,7 +75,6 @@ package yours
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -90,6 +92,7 @@ func TestSomething(t *testing.T) {
|
||||||
|
|
||||||
// assert for not nil (good when you expect something)
|
// assert for not nil (good when you expect something)
|
||||||
if assert.NotNil(object) {
|
if assert.NotNil(object) {
|
||||||
|
|
||||||
// now we know that object isn't nil, we are safe to make
|
// now we know that object isn't nil, we are safe to make
|
||||||
// further assertions without causing any errors
|
// further assertions without causing any errors
|
||||||
assert.Equal("Something", object.Value)
|
assert.Equal("Something", object.Value)
|
||||||
|
@ -97,28 +100,25 @@ func TestSomething(t *testing.T) {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
[`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.
|
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.
|
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
|
```go
|
||||||
package yours
|
package yours
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/mock"
|
"github.com/stretchr/testify/mock"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -128,7 +128,7 @@ import (
|
||||||
|
|
||||||
// MyMockedObject is a mocked object that implements an interface
|
// MyMockedObject is a mocked object that implements an interface
|
||||||
// that describes an object that the code I am testing relies on.
|
// that describes an object that the code I am testing relies on.
|
||||||
type MyMockedObject struct {
|
type MyMockedObject struct{
|
||||||
mock.Mock
|
mock.Mock
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,8 +140,10 @@ type MyMockedObject struct {
|
||||||
//
|
//
|
||||||
// NOTE: This method is not being tested here, code that uses this object is.
|
// NOTE: This method is not being tested here, code that uses this object is.
|
||||||
func (m *MyMockedObject) DoSomething(number int) (bool, error) {
|
func (m *MyMockedObject) DoSomething(number int) (bool, error) {
|
||||||
|
|
||||||
args := m.Called(number)
|
args := m.Called(number)
|
||||||
return args.Bool(0), args.Error(1)
|
return args.Bool(0), args.Error(1)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -151,10 +153,11 @@ func (m *MyMockedObject) DoSomething(number int) (bool, error) {
|
||||||
// TestSomething is an example of how to use our test object to
|
// TestSomething is an example of how to use our test object to
|
||||||
// make assertions about some target code we are testing.
|
// make assertions about some target code we are testing.
|
||||||
func TestSomething(t *testing.T) {
|
func TestSomething(t *testing.T) {
|
||||||
|
|
||||||
// create an instance of our test object
|
// create an instance of our test object
|
||||||
testObj := new(MyMockedObject)
|
testObj := new(MyMockedObject)
|
||||||
|
|
||||||
// set up expectations
|
// setup expectations
|
||||||
testObj.On("DoSomething", 123).Return(true, nil)
|
testObj.On("DoSomething", 123).Return(true, nil)
|
||||||
|
|
||||||
// call the code we are testing
|
// call the code we are testing
|
||||||
|
@ -162,6 +165,8 @@ func TestSomething(t *testing.T) {
|
||||||
|
|
||||||
// assert that the expectations were met
|
// assert that the expectations were met
|
||||||
testObj.AssertExpectations(t)
|
testObj.AssertExpectations(t)
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestSomethingWithPlaceholder is a second example of how to use our test object to
|
// TestSomethingWithPlaceholder is a second example of how to use our test object to
|
||||||
|
@ -170,10 +175,11 @@ func TestSomething(t *testing.T) {
|
||||||
// data being passed in is normally dynamically generated and cannot be
|
// data being passed in is normally dynamically generated and cannot be
|
||||||
// predicted beforehand (eg. containing hashes that are time sensitive)
|
// predicted beforehand (eg. containing hashes that are time sensitive)
|
||||||
func TestSomethingWithPlaceholder(t *testing.T) {
|
func TestSomethingWithPlaceholder(t *testing.T) {
|
||||||
|
|
||||||
// create an instance of our test object
|
// create an instance of our test object
|
||||||
testObj := new(MyMockedObject)
|
testObj := new(MyMockedObject)
|
||||||
|
|
||||||
// set up expectations with a placeholder in the argument list
|
// setup expectations with a placeholder in the argument list
|
||||||
testObj.On("DoSomething", mock.Anything).Return(true, nil)
|
testObj.On("DoSomething", mock.Anything).Return(true, nil)
|
||||||
|
|
||||||
// call the code we are testing
|
// call the code we are testing
|
||||||
|
@ -182,43 +188,18 @@ func TestSomethingWithPlaceholder(t *testing.T) {
|
||||||
// assert that the expectations were met
|
// assert that the expectations were met
|
||||||
testObj.AssertExpectations(t)
|
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:
|
An example suite is shown below:
|
||||||
|
|
||||||
|
@ -226,7 +207,6 @@ An example suite is shown below:
|
||||||
// Basic imports
|
// Basic imports
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/suite"
|
"github.com/stretchr/testify/suite"
|
||||||
)
|
)
|
||||||
|
@ -260,7 +240,7 @@ func TestExampleTestSuite(t *testing.T) {
|
||||||
|
|
||||||
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 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:
|
`Suite` object has assertion methods:
|
||||||
|
|
||||||
|
@ -268,7 +248,6 @@ For more information on writing suites, check out the [API documentation for the
|
||||||
// Basic imports
|
// Basic imports
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/suite"
|
"github.com/stretchr/testify/suite"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -322,12 +301,13 @@ package yours
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestSomething(t *testing.T) {
|
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
|
Supported go versions
|
||||||
==================
|
==================
|
||||||
|
|
||||||
We currently support the most recent major Go versions from 1.19 onward.
|
We support the two major Go versions, which are 1.13 and 1.14 at the moment.
|
||||||
|
|
||||||
------
|
------
|
||||||
|
|
||||||
|
@ -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.
|
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.
|
We also chat on the [Gophers Slack](https://gophers.slack.com) group in the `#testify` and `#testify-dev` channels.
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@ import (
|
||||||
"go/token"
|
"go/token"
|
||||||
"go/types"
|
"go/types"
|
||||||
"io"
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
|
@ -100,15 +101,13 @@ func parseTemplates() (*template.Template, *template.Template, error) {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
if *tmplFile != "" {
|
if *tmplFile != "" {
|
||||||
f, err := os.ReadFile(*tmplFile)
|
f, err := ioutil.ReadFile(*tmplFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
funcTemplate = string(f)
|
funcTemplate = string(f)
|
||||||
}
|
}
|
||||||
tmpl, err := template.New("function").Funcs(template.FuncMap{
|
tmpl, err := template.New("function").Parse(funcTemplate)
|
||||||
"replace": strings.ReplaceAll,
|
|
||||||
}).Parse(funcTemplate)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
@ -182,7 +181,7 @@ func parsePackageSource(pkg string) (*types.Scope, *doc.Package, error) {
|
||||||
files := make(map[string]*ast.File)
|
files := make(map[string]*ast.File)
|
||||||
fileList := make([]*ast.File, len(pd.GoFiles))
|
fileList := make([]*ast.File, len(pd.GoFiles))
|
||||||
for i, fname := range 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 {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
@ -298,8 +297,10 @@ func (f *testFunc) CommentWithoutT(receiver string) string {
|
||||||
return strings.Replace(f.Comment(), search, replace, -1)
|
return strings.Replace(f.Comment(), search, replace, -1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Standard header https://go.dev/s/generatedcode.
|
var headerTemplate = `/*
|
||||||
var headerTemplate = `// 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 {{.Name}}
|
package {{.Name}}
|
||||||
|
|
||||||
|
|
|
@ -1,19 +1,14 @@
|
||||||
package assert
|
package assert
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"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 int
|
||||||
type CompareType = compareResult
|
|
||||||
|
|
||||||
type compareResult int
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
compareLess compareResult = iota - 1
|
compareLess CompareType = iota - 1
|
||||||
compareEqual
|
compareEqual
|
||||||
compareGreater
|
compareGreater
|
||||||
)
|
)
|
||||||
|
@ -31,18 +26,13 @@ var (
|
||||||
uint32Type = reflect.TypeOf(uint32(1))
|
uint32Type = reflect.TypeOf(uint32(1))
|
||||||
uint64Type = reflect.TypeOf(uint64(1))
|
uint64Type = reflect.TypeOf(uint64(1))
|
||||||
|
|
||||||
uintptrType = reflect.TypeOf(uintptr(1))
|
|
||||||
|
|
||||||
float32Type = reflect.TypeOf(float32(1))
|
float32Type = reflect.TypeOf(float32(1))
|
||||||
float64Type = reflect.TypeOf(float64(1))
|
float64Type = reflect.TypeOf(float64(1))
|
||||||
|
|
||||||
stringType = reflect.TypeOf("")
|
stringType = reflect.TypeOf("")
|
||||||
|
|
||||||
timeType = reflect.TypeOf(time.Time{})
|
|
||||||
bytesType = reflect.TypeOf([]byte{})
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func compare(obj1, obj2 interface{}, kind reflect.Kind) (compareResult, bool) {
|
func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) {
|
||||||
obj1Value := reflect.ValueOf(obj1)
|
obj1Value := reflect.ValueOf(obj1)
|
||||||
obj2Value := reflect.ValueOf(obj2)
|
obj2Value := reflect.ValueOf(obj2)
|
||||||
|
|
||||||
|
@ -309,73 +299,6 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (compareResult, bool) {
|
||||||
return compareLess, true
|
return compareLess, true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Check for known struct types we can check for compare results.
|
|
||||||
case reflect.Struct:
|
|
||||||
{
|
|
||||||
// All structs enter here. We're not interested in most types.
|
|
||||||
if !obj1Value.CanConvert(timeType) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
// time.Time can be compared!
|
|
||||||
timeObj1, ok := obj1.(time.Time)
|
|
||||||
if !ok {
|
|
||||||
timeObj1 = obj1Value.Convert(timeType).Interface().(time.Time)
|
|
||||||
}
|
|
||||||
|
|
||||||
timeObj2, ok := obj2.(time.Time)
|
|
||||||
if !ok {
|
|
||||||
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 compareEqual, false
|
return compareEqual, false
|
||||||
|
@ -387,11 +310,7 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (compareResult, bool) {
|
||||||
// assert.Greater(t, float64(2), float64(1))
|
// assert.Greater(t, float64(2), float64(1))
|
||||||
// assert.Greater(t, "b", "a")
|
// assert.Greater(t, "b", "a")
|
||||||
func Greater(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
|
func Greater(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
|
||||||
if h, ok := t.(tHelper); ok {
|
return compareTwoValues(t, e1, e2, []CompareType{compareGreater}, "\"%v\" is not greater than \"%v\"", msgAndArgs)
|
||||||
h.Helper()
|
|
||||||
}
|
|
||||||
failMessage := fmt.Sprintf("\"%v\" is not greater than \"%v\"", e1, e2)
|
|
||||||
return compareTwoValues(t, e1, e2, []compareResult{compareGreater}, failMessage, msgAndArgs...)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GreaterOrEqual asserts that the first element is greater than or equal to the second
|
// GreaterOrEqual asserts that the first element is greater than or equal to the second
|
||||||
|
@ -401,11 +320,7 @@ func Greater(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface
|
||||||
// assert.GreaterOrEqual(t, "b", "a")
|
// assert.GreaterOrEqual(t, "b", "a")
|
||||||
// assert.GreaterOrEqual(t, "b", "b")
|
// assert.GreaterOrEqual(t, "b", "b")
|
||||||
func GreaterOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
|
func GreaterOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
|
||||||
if h, ok := t.(tHelper); ok {
|
return compareTwoValues(t, e1, e2, []CompareType{compareGreater, compareEqual}, "\"%v\" is not greater than or equal to \"%v\"", msgAndArgs)
|
||||||
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...)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Less asserts that the first element is less than the second
|
// Less asserts that the first element is less than the second
|
||||||
|
@ -414,11 +329,7 @@ func GreaterOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...in
|
||||||
// assert.Less(t, float64(1), float64(2))
|
// assert.Less(t, float64(1), float64(2))
|
||||||
// assert.Less(t, "a", "b")
|
// assert.Less(t, "a", "b")
|
||||||
func Less(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
|
func Less(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
|
||||||
if h, ok := t.(tHelper); ok {
|
return compareTwoValues(t, e1, e2, []CompareType{compareLess}, "\"%v\" is not less than \"%v\"", msgAndArgs)
|
||||||
h.Helper()
|
|
||||||
}
|
|
||||||
failMessage := fmt.Sprintf("\"%v\" is not less than \"%v\"", e1, e2)
|
|
||||||
return compareTwoValues(t, e1, e2, []compareResult{compareLess}, failMessage, msgAndArgs...)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// LessOrEqual asserts that the first element is less than or equal to the second
|
// LessOrEqual asserts that the first element is less than or equal to the second
|
||||||
|
@ -428,11 +339,7 @@ func Less(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{})
|
||||||
// assert.LessOrEqual(t, "a", "b")
|
// assert.LessOrEqual(t, "a", "b")
|
||||||
// assert.LessOrEqual(t, "b", "b")
|
// assert.LessOrEqual(t, "b", "b")
|
||||||
func LessOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
|
func LessOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
|
||||||
if h, ok := t.(tHelper); ok {
|
return compareTwoValues(t, e1, e2, []CompareType{compareLess, compareEqual}, "\"%v\" is not less than or equal to \"%v\"", msgAndArgs)
|
||||||
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...)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Positive asserts that the specified element is positive
|
// Positive asserts that the specified element is positive
|
||||||
|
@ -440,12 +347,8 @@ func LessOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...inter
|
||||||
// assert.Positive(t, 1)
|
// assert.Positive(t, 1)
|
||||||
// assert.Positive(t, 1.23)
|
// assert.Positive(t, 1.23)
|
||||||
func Positive(t TestingT, e interface{}, msgAndArgs ...interface{}) bool {
|
func Positive(t TestingT, e interface{}, msgAndArgs ...interface{}) bool {
|
||||||
if h, ok := t.(tHelper); ok {
|
|
||||||
h.Helper()
|
|
||||||
}
|
|
||||||
zero := reflect.Zero(reflect.TypeOf(e))
|
zero := reflect.Zero(reflect.TypeOf(e))
|
||||||
failMessage := fmt.Sprintf("\"%v\" is not positive", e)
|
return compareTwoValues(t, e, zero.Interface(), []CompareType{compareGreater}, "\"%v\" is not positive", msgAndArgs)
|
||||||
return compareTwoValues(t, e, zero.Interface(), []compareResult{compareGreater}, failMessage, msgAndArgs...)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Negative asserts that the specified element is negative
|
// Negative asserts that the specified element is negative
|
||||||
|
@ -453,15 +356,11 @@ func Positive(t TestingT, e interface{}, msgAndArgs ...interface{}) bool {
|
||||||
// assert.Negative(t, -1)
|
// assert.Negative(t, -1)
|
||||||
// assert.Negative(t, -1.23)
|
// assert.Negative(t, -1.23)
|
||||||
func Negative(t TestingT, e interface{}, msgAndArgs ...interface{}) bool {
|
func Negative(t TestingT, e interface{}, msgAndArgs ...interface{}) bool {
|
||||||
if h, ok := t.(tHelper); ok {
|
|
||||||
h.Helper()
|
|
||||||
}
|
|
||||||
zero := reflect.Zero(reflect.TypeOf(e))
|
zero := reflect.Zero(reflect.TypeOf(e))
|
||||||
failMessage := fmt.Sprintf("\"%v\" is not negative", e)
|
return compareTwoValues(t, e, zero.Interface(), []CompareType{compareLess}, "\"%v\" is not negative", msgAndArgs)
|
||||||
return compareTwoValues(t, e, zero.Interface(), []compareResult{compareLess}, failMessage, 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 {
|
if h, ok := t.(tHelper); ok {
|
||||||
h.Helper()
|
h.Helper()
|
||||||
}
|
}
|
||||||
|
@ -474,17 +373,17 @@ func compareTwoValues(t TestingT, e1 interface{}, e2 interface{}, allowedCompare
|
||||||
|
|
||||||
compareResult, isComparable := compare(e1, e2, e1Kind)
|
compareResult, isComparable := compare(e1, e2, e1Kind)
|
||||||
if !isComparable {
|
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) {
|
if !containsValue(allowedComparesResults, compareResult) {
|
||||||
return Fail(t, failMessage, msgAndArgs...)
|
return Fail(t, fmt.Sprintf(failMessage, e1, e2), msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func containsValue(values []compareResult, value compareResult) bool {
|
func containsValue(values []CompareType, value CompareType) bool {
|
||||||
for _, v := range values {
|
for _, v := range values {
|
||||||
if v == value {
|
if v == value {
|
||||||
return true
|
return true
|
||||||
|
|
|
@ -4,13 +4,10 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
"runtime"
|
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestCompare(t *testing.T) {
|
func TestCompare(t *testing.T) {
|
||||||
type customString string
|
|
||||||
type customInt int
|
type customInt int
|
||||||
type customInt8 int8
|
type customInt8 int8
|
||||||
type customInt16 int16
|
type customInt16 int16
|
||||||
|
@ -23,9 +20,7 @@ func TestCompare(t *testing.T) {
|
||||||
type customUInt64 uint64
|
type customUInt64 uint64
|
||||||
type customFloat32 float32
|
type customFloat32 float32
|
||||||
type customFloat64 float64
|
type customFloat64 float64
|
||||||
type customUintptr uintptr
|
type customString string
|
||||||
type customTime time.Time
|
|
||||||
type customBytes []byte
|
|
||||||
for _, currCase := range []struct {
|
for _, currCase := range []struct {
|
||||||
less interface{}
|
less interface{}
|
||||||
greater interface{}
|
greater interface{}
|
||||||
|
@ -56,13 +51,6 @@ func TestCompare(t *testing.T) {
|
||||||
{less: customFloat32(1.23), greater: customFloat32(2.23), cType: "float32"},
|
{less: customFloat32(1.23), greater: customFloat32(2.23), cType: "float32"},
|
||||||
{less: float64(1.23), greater: float64(2.34), cType: "float64"},
|
{less: float64(1.23), greater: float64(2.34), cType: "float64"},
|
||||||
{less: customFloat64(1.23), greater: customFloat64(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())
|
resLess, isComparable := compare(currCase.less, currCase.greater, reflect.ValueOf(currCase.less).Kind())
|
||||||
if !isComparable {
|
if !isComparable {
|
||||||
|
@ -70,8 +58,7 @@ func TestCompare(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if resLess != compareLess {
|
if resLess != compareLess {
|
||||||
t.Errorf("object less (%v) should be less than greater (%v) for type "+currCase.cType,
|
t.Errorf("object less should be less than greater for type " + currCase.cType)
|
||||||
currCase.less, currCase.greater)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
resGreater, isComparable := compare(currCase.greater, currCase.less, reflect.ValueOf(currCase.less).Kind())
|
resGreater, isComparable := compare(currCase.greater, currCase.less, reflect.ValueOf(currCase.less).Kind())
|
||||||
|
@ -96,7 +83,6 @@ func TestCompare(t *testing.T) {
|
||||||
|
|
||||||
type outputT struct {
|
type outputT struct {
|
||||||
buf *bytes.Buffer
|
buf *bytes.Buffer
|
||||||
helpers map[string]struct{}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements TestingT
|
// Implements TestingT
|
||||||
|
@ -105,27 +91,6 @@ func (t *outputT) Errorf(format string, args ...interface{}) {
|
||||||
t.buf.WriteString(s)
|
t.buf.WriteString(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *outputT) Helper() {
|
|
||||||
if t.helpers == nil {
|
|
||||||
t.helpers = make(map[string]struct{})
|
|
||||||
}
|
|
||||||
t.helpers[callerName(1)] = struct{}{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// callerName gives the function name (qualified with a package path)
|
|
||||||
// for the caller after skip frames (where 0 means the current function).
|
|
||||||
func callerName(skip int) string {
|
|
||||||
// Make room for the skip PC.
|
|
||||||
var pc [1]uintptr
|
|
||||||
n := runtime.Callers(skip+2, pc[:]) // skip + runtime.Callers + callerName
|
|
||||||
if n == 0 {
|
|
||||||
panic("testing: zero callers found")
|
|
||||||
}
|
|
||||||
frames := runtime.CallersFrames(pc[:n])
|
|
||||||
frame, _ := frames.Next()
|
|
||||||
return frame.Function
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGreater(t *testing.T) {
|
func TestGreater(t *testing.T) {
|
||||||
mockT := new(testing.T)
|
mockT := new(testing.T)
|
||||||
|
|
||||||
|
@ -159,14 +124,10 @@ func TestGreater(t *testing.T) {
|
||||||
{less: uint64(1), greater: uint64(2), msg: `"1" is not greater than "2"`},
|
{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: 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: 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)}
|
out := &outputT{buf: bytes.NewBuffer(nil)}
|
||||||
False(t, Greater(out, currCase.less, currCase.greater))
|
False(t, Greater(out, currCase.less, currCase.greater))
|
||||||
Contains(t, out.buf.String(), currCase.msg)
|
Contains(t, string(out.buf.Bytes()), currCase.msg)
|
||||||
Contains(t, out.helpers, "github.com/stretchr/testify/assert.Greater")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -203,14 +164,10 @@ func TestGreaterOrEqual(t *testing.T) {
|
||||||
{less: uint64(1), greater: uint64(2), msg: `"1" is not greater than or equal to "2"`},
|
{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: 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: 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)}
|
out := &outputT{buf: bytes.NewBuffer(nil)}
|
||||||
False(t, GreaterOrEqual(out, currCase.less, currCase.greater))
|
False(t, GreaterOrEqual(out, currCase.less, currCase.greater))
|
||||||
Contains(t, out.buf.String(), currCase.msg)
|
Contains(t, string(out.buf.Bytes()), currCase.msg)
|
||||||
Contains(t, out.helpers, "github.com/stretchr/testify/assert.GreaterOrEqual")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -247,14 +204,10 @@ func TestLess(t *testing.T) {
|
||||||
{less: uint64(1), greater: uint64(2), msg: `"2" is not less than "1"`},
|
{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: 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: 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)}
|
out := &outputT{buf: bytes.NewBuffer(nil)}
|
||||||
False(t, Less(out, currCase.greater, currCase.less))
|
False(t, Less(out, currCase.greater, currCase.less))
|
||||||
Contains(t, out.buf.String(), currCase.msg)
|
Contains(t, string(out.buf.Bytes()), currCase.msg)
|
||||||
Contains(t, out.helpers, "github.com/stretchr/testify/assert.Less")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -291,14 +244,10 @@ func TestLessOrEqual(t *testing.T) {
|
||||||
{less: uint64(1), greater: uint64(2), msg: `"2" is not less than or equal to "1"`},
|
{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: 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: 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)}
|
out := &outputT{buf: bytes.NewBuffer(nil)}
|
||||||
False(t, LessOrEqual(out, currCase.greater, currCase.less))
|
False(t, LessOrEqual(out, currCase.greater, currCase.less))
|
||||||
Contains(t, out.buf.String(), currCase.msg)
|
Contains(t, string(out.buf.Bytes()), currCase.msg)
|
||||||
Contains(t, out.helpers, "github.com/stretchr/testify/assert.LessOrEqual")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -336,8 +285,7 @@ func TestPositive(t *testing.T) {
|
||||||
} {
|
} {
|
||||||
out := &outputT{buf: bytes.NewBuffer(nil)}
|
out := &outputT{buf: bytes.NewBuffer(nil)}
|
||||||
False(t, Positive(out, currCase.e))
|
False(t, Positive(out, currCase.e))
|
||||||
Contains(t, out.buf.String(), currCase.msg)
|
Contains(t, string(out.buf.Bytes()), currCase.msg)
|
||||||
Contains(t, out.helpers, "github.com/stretchr/testify/assert.Positive")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -375,8 +323,7 @@ func TestNegative(t *testing.T) {
|
||||||
} {
|
} {
|
||||||
out := &outputT{buf: bytes.NewBuffer(nil)}
|
out := &outputT{buf: bytes.NewBuffer(nil)}
|
||||||
False(t, Negative(out, currCase.e))
|
False(t, Negative(out, currCase.e))
|
||||||
Contains(t, out.buf.String(), currCase.msg)
|
Contains(t, string(out.buf.Bytes()), currCase.msg)
|
||||||
Contains(t, out.helpers, "github.com/stretchr/testify/assert.Negative")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -393,8 +340,8 @@ func Test_compareTwoValuesDifferentValuesTypes(t *testing.T) {
|
||||||
{v1: float64(12), v2: "123"},
|
{v1: float64(12), v2: "123"},
|
||||||
{v1: "float(12)", v2: float64(1)},
|
{v1: "float(12)", v2: float64(1)},
|
||||||
} {
|
} {
|
||||||
result := compareTwoValues(mockT, currCase.v1, currCase.v2, []compareResult{compareLess, compareEqual, compareGreater}, "testFailMessage")
|
compareResult := compareTwoValues(mockT, currCase.v1, currCase.v2, []CompareType{compareLess, compareEqual, compareGreater}, "testFailMessage")
|
||||||
False(t, result)
|
False(t, compareResult)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -410,10 +357,10 @@ func Test_compareTwoValuesNotComparableValues(t *testing.T) {
|
||||||
}{
|
}{
|
||||||
{v1: CompareStruct{}, v2: CompareStruct{}},
|
{v1: CompareStruct{}, v2: CompareStruct{}},
|
||||||
{v1: map[string]int{}, v2: map[string]int{}},
|
{v1: map[string]int{}, v2: map[string]int{}},
|
||||||
{v1: make([]int, 5), v2: make([]int, 5)},
|
{v1: make([]int, 5, 5), v2: make([]int, 5, 5)},
|
||||||
} {
|
} {
|
||||||
result := compareTwoValues(mockT, currCase.v1, currCase.v2, []compareResult{compareLess, compareEqual, compareGreater}, "testFailMessage")
|
compareResult := compareTwoValues(mockT, currCase.v1, currCase.v2, []CompareType{compareLess, compareEqual, compareGreater}, "testFailMessage")
|
||||||
False(t, result)
|
False(t, compareResult)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -423,50 +370,32 @@ func Test_compareTwoValuesCorrectCompareResult(t *testing.T) {
|
||||||
for _, currCase := range []struct {
|
for _, currCase := range []struct {
|
||||||
v1 interface{}
|
v1 interface{}
|
||||||
v2 interface{}
|
v2 interface{}
|
||||||
allowedResults []compareResult
|
compareTypes []CompareType
|
||||||
}{
|
}{
|
||||||
{v1: 1, v2: 2, allowedResults: []compareResult{compareLess}},
|
{v1: 1, v2: 2, compareTypes: []CompareType{compareLess}},
|
||||||
{v1: 1, v2: 2, allowedResults: []compareResult{compareLess, compareEqual}},
|
{v1: 1, v2: 2, compareTypes: []CompareType{compareLess, compareEqual}},
|
||||||
{v1: 2, v2: 2, allowedResults: []compareResult{compareGreater, compareEqual}},
|
{v1: 2, v2: 2, compareTypes: []CompareType{compareGreater, compareEqual}},
|
||||||
{v1: 2, v2: 2, allowedResults: []compareResult{compareEqual}},
|
{v1: 2, v2: 2, compareTypes: []CompareType{compareEqual}},
|
||||||
{v1: 2, v2: 1, allowedResults: []compareResult{compareEqual, compareGreater}},
|
{v1: 2, v2: 1, compareTypes: []CompareType{compareEqual, compareGreater}},
|
||||||
{v1: 2, v2: 1, allowedResults: []compareResult{compareGreater}},
|
{v1: 2, v2: 1, compareTypes: []CompareType{compareGreater}},
|
||||||
} {
|
} {
|
||||||
result := compareTwoValues(mockT, currCase.v1, currCase.v2, currCase.allowedResults, "testFailMessage")
|
compareResult := compareTwoValues(mockT, currCase.v1, currCase.v2, currCase.compareTypes, "testFailMessage")
|
||||||
True(t, result)
|
True(t, compareResult)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_containsValue(t *testing.T) {
|
func Test_containsValue(t *testing.T) {
|
||||||
for _, currCase := range []struct {
|
for _, currCase := range []struct {
|
||||||
values []compareResult
|
values []CompareType
|
||||||
value compareResult
|
value CompareType
|
||||||
result bool
|
result bool
|
||||||
}{
|
}{
|
||||||
{values: []compareResult{compareGreater}, value: compareGreater, result: true},
|
{values: []CompareType{compareGreater}, value: compareGreater, result: true},
|
||||||
{values: []compareResult{compareGreater, compareLess}, value: compareGreater, result: true},
|
{values: []CompareType{compareGreater, compareLess}, value: compareGreater, result: true},
|
||||||
{values: []compareResult{compareGreater, compareLess}, value: compareLess, result: true},
|
{values: []CompareType{compareGreater, compareLess}, value: compareLess, result: true},
|
||||||
{values: []compareResult{compareGreater, compareLess}, value: compareEqual, result: false},
|
{values: []CompareType{compareGreater, compareLess}, value: compareEqual, result: false},
|
||||||
} {
|
} {
|
||||||
result := containsValue(currCase.values, currCase.value)
|
compareResult := containsValue(currCase.values, currCase.value)
|
||||||
Equal(t, currCase.result, result)
|
Equal(t, currCase.result, compareResult)
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestComparingMsgAndArgsForwarding(t *testing.T) {
|
|
||||||
msgAndArgs := []interface{}{"format %s %x", "this", 0xc001}
|
|
||||||
expectedOutput := "format this c001\n"
|
|
||||||
funcs := []func(t TestingT){
|
|
||||||
func(t TestingT) { Greater(t, 1, 2, msgAndArgs...) },
|
|
||||||
func(t TestingT) { GreaterOrEqual(t, 1, 2, msgAndArgs...) },
|
|
||||||
func(t TestingT) { Less(t, 2, 1, msgAndArgs...) },
|
|
||||||
func(t TestingT) { LessOrEqual(t, 2, 1, msgAndArgs...) },
|
|
||||||
func(t TestingT) { Positive(t, 0, msgAndArgs...) },
|
|
||||||
func(t TestingT) { Negative(t, 0, msgAndArgs...) },
|
|
||||||
}
|
|
||||||
for _, f := range funcs {
|
|
||||||
out := &outputT{buf: bytes.NewBuffer(nil)}
|
|
||||||
f(out)
|
|
||||||
Contains(t, out.buf.String(), expectedOutput)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
package assert
|
||||||
|
|
||||||
|
@ -87,25 +90,8 @@ func EqualErrorf(t TestingT, theError error, errString string, msg string, args
|
||||||
return EqualError(t, theError, errString, append([]interface{}{msg}, args...)...)
|
return EqualError(t, theError, errString, append([]interface{}{msg}, args...)...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// EqualExportedValuesf asserts that the types of two objects are equal and their public
|
// EqualValuesf asserts that two objects are equal or convertable to the same types
|
||||||
// fields are also equal. This is useful for comparing structs that have private fields
|
// and equal.
|
||||||
// that could potentially differ.
|
|
||||||
//
|
|
||||||
// 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 {
|
func EqualValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
|
||||||
|
@ -137,18 +123,6 @@ func ErrorAsf(t TestingT, err error, target interface{}, msg string, args ...int
|
||||||
return ErrorAs(t, err, target, append([]interface{}{msg}, args...)...)
|
return ErrorAs(t, err, target, append([]interface{}{msg}, args...)...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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")
|
|
||||||
func ErrorContainsf(t TestingT, theError error, contains string, msg string, args ...interface{}) bool {
|
|
||||||
if h, ok := t.(tHelper); ok {
|
|
||||||
h.Helper()
|
|
||||||
}
|
|
||||||
return ErrorContains(t, theError, contains, append([]interface{}{msg}, args...)...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrorIsf asserts that at least one of the errors in err's chain matches target.
|
// ErrorIsf asserts that at least one of the errors in err's chain matches target.
|
||||||
// This is a wrapper for errors.Is.
|
// This is a wrapper for errors.Is.
|
||||||
func ErrorIsf(t TestingT, err error, target error, msg string, args ...interface{}) bool {
|
func ErrorIsf(t TestingT, err error, target error, msg string, args ...interface{}) bool {
|
||||||
|
@ -169,31 +143,6 @@ func Eventuallyf(t TestingT, condition func() bool, waitFor time.Duration, tick
|
||||||
return Eventually(t, condition, waitFor, tick, append([]interface{}{msg}, args...)...)
|
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.
|
// 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")
|
||||||
|
@ -568,23 +517,6 @@ func NotContainsf(t TestingT, s interface{}, contains interface{}, msg string, a
|
||||||
return NotContains(t, s, contains, append([]interface{}{msg}, args...)...)
|
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.
|
|
||||||
//
|
|
||||||
// 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. I.e. not nil, "", false, 0 or either
|
// 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.
|
// a slice or a channel with len == 0.
|
||||||
//
|
//
|
||||||
|
@ -621,16 +553,7 @@ func NotEqualValuesf(t TestingT, expected interface{}, actual interface{}, msg s
|
||||||
return NotEqualValues(t, expected, actual, append([]interface{}{msg}, args...)...)
|
return NotEqualValues(t, expected, actual, append([]interface{}{msg}, args...)...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NotErrorAsf 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.
|
||||||
// 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.
|
|
||||||
// This is a wrapper for errors.Is.
|
// This is a wrapper for errors.Is.
|
||||||
func NotErrorIsf(t TestingT, err error, target error, msg string, args ...interface{}) bool {
|
func NotErrorIsf(t TestingT, err error, target error, msg string, args ...interface{}) bool {
|
||||||
if h, ok := t.(tHelper); ok {
|
if h, ok := t.(tHelper); ok {
|
||||||
|
@ -639,16 +562,6 @@ func NotErrorIsf(t TestingT, err error, target error, msg string, args ...interf
|
||||||
return NotErrorIs(t, err, target, append([]interface{}{msg}, args...)...)
|
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.
|
// 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")
|
||||||
|
@ -693,12 +606,10 @@ func NotSamef(t TestingT, expected interface{}, actual interface{}, msg string,
|
||||||
return NotSame(t, expected, actual, append([]interface{}{msg}, args...)...)
|
return NotSame(t, expected, actual, append([]interface{}{msg}, args...)...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NotSubsetf asserts that the specified list(array, slice...) or map does NOT
|
// NotSubsetf asserts that the specified list(array, slice...) contains not all
|
||||||
// contain all elements given in the specified subset list(array, slice...) or
|
// elements given in the specified subset(array, slice...).
|
||||||
// map.
|
|
||||||
//
|
//
|
||||||
// assert.NotSubsetf(t, [1, 3, 4], [1, 2], "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")
|
||||||
// assert.NotSubsetf(t, {"x": 1, "y": 2}, {"z": 3}, "error message %s", "formatted")
|
|
||||||
func NotSubsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) bool {
|
func NotSubsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) bool {
|
||||||
if h, ok := t.(tHelper); ok {
|
if h, ok := t.(tHelper); ok {
|
||||||
h.Helper()
|
h.Helper()
|
||||||
|
@ -782,11 +693,10 @@ func Samef(t TestingT, expected interface{}, actual interface{}, msg string, arg
|
||||||
return Same(t, expected, actual, append([]interface{}{msg}, args...)...)
|
return Same(t, expected, actual, append([]interface{}{msg}, args...)...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Subsetf asserts that the specified list(array, slice...) or map contains all
|
// Subsetf asserts that the specified list(array, slice...) contains all
|
||||||
// elements given in the specified subset list(array, slice...) or map.
|
// elements given in the specified subset(array, slice...).
|
||||||
//
|
//
|
||||||
// assert.Subsetf(t, [1, 2, 3], [1, 2], "error message %s", "formatted")
|
// assert.Subsetf(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted")
|
||||||
// assert.Subsetf(t, {"x": 1, "y": 2}, {"x": 1}, "error message %s", "formatted")
|
|
||||||
func Subsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) bool {
|
func Subsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) bool {
|
||||||
if h, ok := t.(tHelper); ok {
|
if h, ok := t.(tHelper); ok {
|
||||||
h.Helper()
|
h.Helper()
|
||||||
|
@ -814,16 +724,6 @@ func WithinDurationf(t TestingT, expected time.Time, actual time.Time, delta tim
|
||||||
return WithinDuration(t, expected, actual, delta, append([]interface{}{msg}, args...)...)
|
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.
|
// YAMLEqf asserts that two YAML strings are equivalent.
|
||||||
func YAMLEqf(t TestingT, expected string, actual string, msg string, args ...interface{}) bool {
|
func YAMLEqf(t TestingT, expected string, actual string, msg string, args ...interface{}) bool {
|
||||||
if h, ok := t.(tHelper); ok {
|
if h, ok := t.(tHelper); ok {
|
||||||
|
|
|
@ -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
|
package assert
|
||||||
|
|
||||||
|
@ -152,42 +155,8 @@ func (a *Assertions) EqualErrorf(theError error, errString string, msg string, a
|
||||||
return EqualErrorf(a.t, theError, errString, msg, args...)
|
return EqualErrorf(a.t, theError, errString, msg, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// EqualExportedValues asserts that the types of two objects are equal and their public
|
// EqualValues asserts that two objects are equal or convertable to the same types
|
||||||
// fields are also equal. This is useful for comparing structs that have private fields
|
// and equal.
|
||||||
// that could potentially differ.
|
|
||||||
//
|
|
||||||
// type S struct {
|
|
||||||
// Exported int
|
|
||||||
// notExported int
|
|
||||||
// }
|
|
||||||
// a.EqualExportedValues(S{1, 2}, S{1, 3}) => true
|
|
||||||
// a.EqualExportedValues(S{1, 2}, S{2, 3}) => false
|
|
||||||
func (a *Assertions) EqualExportedValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool {
|
|
||||||
if h, ok := a.t.(tHelper); ok {
|
|
||||||
h.Helper()
|
|
||||||
}
|
|
||||||
return EqualExportedValues(a.t, expected, actual, msgAndArgs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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.
|
|
||||||
//
|
|
||||||
// type S struct {
|
|
||||||
// Exported int
|
|
||||||
// notExported int
|
|
||||||
// }
|
|
||||||
// a.EqualExportedValuesf(S{1, 2}, S{1, 3}, "error message %s", "formatted") => true
|
|
||||||
// a.EqualExportedValuesf(S{1, 2}, S{2, 3}, "error message %s", "formatted") => false
|
|
||||||
func (a *Assertions) EqualExportedValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
|
|
||||||
if h, ok := a.t.(tHelper); ok {
|
|
||||||
h.Helper()
|
|
||||||
}
|
|
||||||
return EqualExportedValuesf(a.t, expected, actual, msg, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// EqualValues asserts that two objects are equal or convertible to the larger
|
|
||||||
// type and equal.
|
|
||||||
//
|
//
|
||||||
// a.EqualValues(uint32(123), int32(123))
|
// a.EqualValues(uint32(123), int32(123))
|
||||||
func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool {
|
func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool {
|
||||||
|
@ -197,8 +166,8 @@ func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAn
|
||||||
return EqualValues(a.t, expected, actual, msgAndArgs...)
|
return EqualValues(a.t, expected, actual, msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// EqualValuesf asserts that two objects are equal or convertible to the larger
|
// EqualValuesf asserts that two objects are equal or convertable to the same types
|
||||||
// type and equal.
|
// and equal.
|
||||||
//
|
//
|
||||||
// a.EqualValuesf(uint32(123), int32(123), "error message %s", "formatted")
|
// a.EqualValuesf(uint32(123), int32(123), "error message %s", "formatted")
|
||||||
func (a *Assertions) EqualValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
|
func (a *Assertions) EqualValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
|
||||||
|
@ -253,30 +222,6 @@ func (a *Assertions) ErrorAsf(err error, target interface{}, msg string, args ..
|
||||||
return ErrorAsf(a.t, err, target, msg, args...)
|
return ErrorAsf(a.t, err, target, msg, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ErrorContains asserts that a function returned an error (i.e. not `nil`)
|
|
||||||
// and that the error contains the specified substring.
|
|
||||||
//
|
|
||||||
// actualObj, err := SomeFunction()
|
|
||||||
// a.ErrorContains(err, expectedErrorSubString)
|
|
||||||
func (a *Assertions) ErrorContains(theError error, contains string, msgAndArgs ...interface{}) bool {
|
|
||||||
if h, ok := a.t.(tHelper); ok {
|
|
||||||
h.Helper()
|
|
||||||
}
|
|
||||||
return ErrorContains(a.t, theError, contains, msgAndArgs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrorContainsf asserts that a function returned an error (i.e. not `nil`)
|
|
||||||
// and that the error contains the specified substring.
|
|
||||||
//
|
|
||||||
// actualObj, err := SomeFunction()
|
|
||||||
// a.ErrorContainsf(err, expectedErrorSubString, "error message %s", "formatted")
|
|
||||||
func (a *Assertions) ErrorContainsf(theError error, contains string, msg string, args ...interface{}) bool {
|
|
||||||
if h, ok := a.t.(tHelper); ok {
|
|
||||||
h.Helper()
|
|
||||||
}
|
|
||||||
return ErrorContainsf(a.t, theError, contains, msg, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrorIs asserts that at least one of the errors in err's chain matches target.
|
// ErrorIs asserts that at least one of the errors in err's chain matches target.
|
||||||
// This is a wrapper for errors.Is.
|
// This is a wrapper for errors.Is.
|
||||||
func (a *Assertions) ErrorIs(err error, target error, msgAndArgs ...interface{}) bool {
|
func (a *Assertions) ErrorIs(err error, target error, msgAndArgs ...interface{}) bool {
|
||||||
|
@ -319,56 +264,6 @@ func (a *Assertions) Eventually(condition func() bool, waitFor time.Duration, ti
|
||||||
return Eventually(a.t, condition, waitFor, tick, msgAndArgs...)
|
return Eventually(a.t, condition, waitFor, tick, msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// EventuallyWithT 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
|
|
||||||
// }()
|
|
||||||
// a.EventuallyWithT(func(c *assert.CollectT) {
|
|
||||||
// // 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 (a *Assertions) EventuallyWithT(condition func(collect *CollectT), waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) bool {
|
|
||||||
if h, ok := a.t.(tHelper); ok {
|
|
||||||
h.Helper()
|
|
||||||
}
|
|
||||||
return EventuallyWithT(a.t, condition, waitFor, tick, msgAndArgs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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
|
|
||||||
// }()
|
|
||||||
// a.EventuallyWithTf(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 (a *Assertions) EventuallyWithTf(condition func(collect *CollectT), waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) bool {
|
|
||||||
if h, ok := a.t.(tHelper); ok {
|
|
||||||
h.Helper()
|
|
||||||
}
|
|
||||||
return EventuallyWithTf(a.t, condition, waitFor, tick, msg, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Eventuallyf asserts that given condition will be met in waitFor time,
|
// Eventuallyf asserts that given condition will be met in waitFor time,
|
||||||
// periodically checking target function each tick.
|
// periodically checking target function each tick.
|
||||||
//
|
//
|
||||||
|
@ -1128,40 +1023,6 @@ func (a *Assertions) NotContainsf(s interface{}, contains interface{}, msg strin
|
||||||
return NotContainsf(a.t, s, contains, msg, args...)
|
return NotContainsf(a.t, s, contains, msg, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NotElementsMatch 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.
|
|
||||||
//
|
|
||||||
// a.NotElementsMatch([1, 1, 2, 3], [1, 1, 2, 3]) -> false
|
|
||||||
//
|
|
||||||
// a.NotElementsMatch([1, 1, 2, 3], [1, 2, 3]) -> true
|
|
||||||
//
|
|
||||||
// a.NotElementsMatch([1, 2, 3], [1, 2, 4]) -> true
|
|
||||||
func (a *Assertions) NotElementsMatch(listA interface{}, listB interface{}, msgAndArgs ...interface{}) bool {
|
|
||||||
if h, ok := a.t.(tHelper); ok {
|
|
||||||
h.Helper()
|
|
||||||
}
|
|
||||||
return NotElementsMatch(a.t, listA, listB, msgAndArgs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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.
|
|
||||||
//
|
|
||||||
// a.NotElementsMatchf([1, 1, 2, 3], [1, 1, 2, 3], "error message %s", "formatted") -> false
|
|
||||||
//
|
|
||||||
// a.NotElementsMatchf([1, 1, 2, 3], [1, 2, 3], "error message %s", "formatted") -> true
|
|
||||||
//
|
|
||||||
// a.NotElementsMatchf([1, 2, 3], [1, 2, 4], "error message %s", "formatted") -> true
|
|
||||||
func (a *Assertions) NotElementsMatchf(listA interface{}, listB interface{}, msg string, args ...interface{}) bool {
|
|
||||||
if h, ok := a.t.(tHelper); ok {
|
|
||||||
h.Helper()
|
|
||||||
}
|
|
||||||
return NotElementsMatchf(a.t, listA, listB, msg, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either
|
// NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either
|
||||||
// a slice or a channel with len == 0.
|
// a slice or a channel with len == 0.
|
||||||
//
|
//
|
||||||
|
@ -1234,25 +1095,7 @@ func (a *Assertions) NotEqualf(expected interface{}, actual interface{}, msg str
|
||||||
return NotEqualf(a.t, expected, actual, msg, args...)
|
return NotEqualf(a.t, expected, actual, msg, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NotErrorAs asserts that none of the errors in err's chain matches target,
|
// NotErrorIs asserts that at none of the errors in err's chain matches target.
|
||||||
// but if so, sets target to that error value.
|
|
||||||
func (a *Assertions) NotErrorAs(err error, target interface{}, msgAndArgs ...interface{}) bool {
|
|
||||||
if h, ok := a.t.(tHelper); ok {
|
|
||||||
h.Helper()
|
|
||||||
}
|
|
||||||
return NotErrorAs(a.t, err, target, msgAndArgs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NotErrorAsf asserts that none of the errors in err's chain matches target,
|
|
||||||
// but if so, sets target to that error value.
|
|
||||||
func (a *Assertions) NotErrorAsf(err error, target interface{}, msg string, args ...interface{}) bool {
|
|
||||||
if h, ok := a.t.(tHelper); ok {
|
|
||||||
h.Helper()
|
|
||||||
}
|
|
||||||
return NotErrorAsf(a.t, err, target, msg, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NotErrorIs asserts that none of the errors in err's chain matches target.
|
|
||||||
// This is a wrapper for errors.Is.
|
// This is a wrapper for errors.Is.
|
||||||
func (a *Assertions) NotErrorIs(err error, target error, msgAndArgs ...interface{}) bool {
|
func (a *Assertions) NotErrorIs(err error, target error, msgAndArgs ...interface{}) bool {
|
||||||
if h, ok := a.t.(tHelper); ok {
|
if h, ok := a.t.(tHelper); ok {
|
||||||
|
@ -1261,7 +1104,7 @@ func (a *Assertions) NotErrorIs(err error, target error, msgAndArgs ...interface
|
||||||
return NotErrorIs(a.t, err, target, msgAndArgs...)
|
return NotErrorIs(a.t, err, target, msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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.
|
// This is a wrapper for errors.Is.
|
||||||
func (a *Assertions) NotErrorIsf(err error, target error, msg string, args ...interface{}) bool {
|
func (a *Assertions) NotErrorIsf(err error, target error, msg string, args ...interface{}) bool {
|
||||||
if h, ok := a.t.(tHelper); ok {
|
if h, ok := a.t.(tHelper); ok {
|
||||||
|
@ -1270,26 +1113,6 @@ func (a *Assertions) NotErrorIsf(err error, target error, msg string, args ...in
|
||||||
return NotErrorIsf(a.t, err, target, msg, args...)
|
return NotErrorIsf(a.t, err, target, msg, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NotImplements asserts that an object does not implement the specified interface.
|
|
||||||
//
|
|
||||||
// a.NotImplements((*MyInterface)(nil), new(MyObject))
|
|
||||||
func (a *Assertions) NotImplements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool {
|
|
||||||
if h, ok := a.t.(tHelper); ok {
|
|
||||||
h.Helper()
|
|
||||||
}
|
|
||||||
return NotImplements(a.t, interfaceObject, object, msgAndArgs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NotImplementsf asserts that an object does not implement the specified interface.
|
|
||||||
//
|
|
||||||
// a.NotImplementsf((*MyInterface)(nil), new(MyObject), "error message %s", "formatted")
|
|
||||||
func (a *Assertions) NotImplementsf(interfaceObject interface{}, object interface{}, msg string, args ...interface{}) bool {
|
|
||||||
if h, ok := a.t.(tHelper); ok {
|
|
||||||
h.Helper()
|
|
||||||
}
|
|
||||||
return NotImplementsf(a.t, interfaceObject, object, msg, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NotNil asserts that the specified object is not nil.
|
// NotNil asserts that the specified object is not nil.
|
||||||
//
|
//
|
||||||
// a.NotNil(err)
|
// a.NotNil(err)
|
||||||
|
@ -1378,12 +1201,10 @@ func (a *Assertions) NotSamef(expected interface{}, actual interface{}, msg stri
|
||||||
return NotSamef(a.t, expected, actual, msg, args...)
|
return NotSamef(a.t, expected, actual, msg, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NotSubset asserts that the specified list(array, slice...) or map does NOT
|
// NotSubset asserts that the specified list(array, slice...) contains not all
|
||||||
// contain all elements given in the specified subset list(array, slice...) or
|
// elements given in the specified subset(array, slice...).
|
||||||
// map.
|
|
||||||
//
|
//
|
||||||
// a.NotSubset([1, 3, 4], [1, 2])
|
// a.NotSubset([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]")
|
||||||
// a.NotSubset({"x": 1, "y": 2}, {"z": 3})
|
|
||||||
func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs ...interface{}) bool {
|
func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs ...interface{}) bool {
|
||||||
if h, ok := a.t.(tHelper); ok {
|
if h, ok := a.t.(tHelper); ok {
|
||||||
h.Helper()
|
h.Helper()
|
||||||
|
@ -1391,12 +1212,10 @@ func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs
|
||||||
return NotSubset(a.t, list, subset, msgAndArgs...)
|
return NotSubset(a.t, list, subset, msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NotSubsetf asserts that the specified list(array, slice...) or map does NOT
|
// NotSubsetf asserts that the specified list(array, slice...) contains not all
|
||||||
// contain all elements given in the specified subset list(array, slice...) or
|
// elements given in the specified subset(array, slice...).
|
||||||
// map.
|
|
||||||
//
|
//
|
||||||
// a.NotSubsetf([1, 3, 4], [1, 2], "error message %s", "formatted")
|
// a.NotSubsetf([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted")
|
||||||
// a.NotSubsetf({"x": 1, "y": 2}, {"z": 3}, "error message %s", "formatted")
|
|
||||||
func (a *Assertions) NotSubsetf(list interface{}, subset interface{}, msg string, args ...interface{}) bool {
|
func (a *Assertions) NotSubsetf(list interface{}, subset interface{}, msg string, args ...interface{}) bool {
|
||||||
if h, ok := a.t.(tHelper); ok {
|
if h, ok := a.t.(tHelper); ok {
|
||||||
h.Helper()
|
h.Helper()
|
||||||
|
@ -1556,11 +1375,10 @@ func (a *Assertions) Samef(expected interface{}, actual interface{}, msg string,
|
||||||
return Samef(a.t, expected, actual, msg, args...)
|
return Samef(a.t, expected, actual, msg, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Subset asserts that the specified list(array, slice...) or map contains all
|
// Subset asserts that the specified list(array, slice...) contains all
|
||||||
// elements given in the specified subset list(array, slice...) or map.
|
// elements given in the specified subset(array, slice...).
|
||||||
//
|
//
|
||||||
// a.Subset([1, 2, 3], [1, 2])
|
// a.Subset([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]")
|
||||||
// a.Subset({"x": 1, "y": 2}, {"x": 1})
|
|
||||||
func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ...interface{}) bool {
|
func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ...interface{}) bool {
|
||||||
if h, ok := a.t.(tHelper); ok {
|
if h, ok := a.t.(tHelper); ok {
|
||||||
h.Helper()
|
h.Helper()
|
||||||
|
@ -1568,11 +1386,10 @@ func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ...
|
||||||
return Subset(a.t, list, subset, msgAndArgs...)
|
return Subset(a.t, list, subset, msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Subsetf asserts that the specified list(array, slice...) or map contains all
|
// Subsetf asserts that the specified list(array, slice...) contains all
|
||||||
// elements given in the specified subset list(array, slice...) or map.
|
// elements given in the specified subset(array, slice...).
|
||||||
//
|
//
|
||||||
// a.Subsetf([1, 2, 3], [1, 2], "error message %s", "formatted")
|
// a.Subsetf([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted")
|
||||||
// a.Subsetf({"x": 1, "y": 2}, {"x": 1}, "error message %s", "formatted")
|
|
||||||
func (a *Assertions) Subsetf(list interface{}, subset interface{}, msg string, args ...interface{}) bool {
|
func (a *Assertions) Subsetf(list interface{}, subset interface{}, msg string, args ...interface{}) bool {
|
||||||
if h, ok := a.t.(tHelper); ok {
|
if h, ok := a.t.(tHelper); ok {
|
||||||
h.Helper()
|
h.Helper()
|
||||||
|
@ -1620,26 +1437,6 @@ func (a *Assertions) WithinDurationf(expected time.Time, actual time.Time, delta
|
||||||
return WithinDurationf(a.t, expected, actual, delta, msg, args...)
|
return WithinDurationf(a.t, expected, actual, delta, msg, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithinRange asserts that a time is within a time range (inclusive).
|
|
||||||
//
|
|
||||||
// a.WithinRange(time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second))
|
|
||||||
func (a *Assertions) WithinRange(actual time.Time, start time.Time, end time.Time, msgAndArgs ...interface{}) bool {
|
|
||||||
if h, ok := a.t.(tHelper); ok {
|
|
||||||
h.Helper()
|
|
||||||
}
|
|
||||||
return WithinRange(a.t, actual, start, end, msgAndArgs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithinRangef asserts that a time is within a time range (inclusive).
|
|
||||||
//
|
|
||||||
// a.WithinRangef(time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second), "error message %s", "formatted")
|
|
||||||
func (a *Assertions) WithinRangef(actual time.Time, start time.Time, end time.Time, msg string, args ...interface{}) bool {
|
|
||||||
if h, ok := a.t.(tHelper); ok {
|
|
||||||
h.Helper()
|
|
||||||
}
|
|
||||||
return WithinRangef(a.t, actual, start, end, msg, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// YAMLEq asserts that two YAML strings are equivalent.
|
// YAMLEq asserts that two YAML strings are equivalent.
|
||||||
func (a *Assertions) YAMLEq(expected string, actual string, msgAndArgs ...interface{}) bool {
|
func (a *Assertions) YAMLEq(expected string, actual string, msgAndArgs ...interface{}) bool {
|
||||||
if h, ok := a.t.(tHelper); ok {
|
if h, ok := a.t.(tHelper); ok {
|
||||||
|
|
|
@ -6,7 +6,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// isOrdered checks that collection contains orderable elements.
|
// 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()
|
objKind := reflect.TypeOf(object).Kind()
|
||||||
if objKind != reflect.Slice && objKind != reflect.Array {
|
if objKind != reflect.Slice && objKind != reflect.Array {
|
||||||
return false
|
return false
|
||||||
|
@ -33,7 +33,7 @@ func isOrdered(t TestingT, object interface{}, allowedComparesResults []compareR
|
||||||
compareResult, isComparable := compare(prevValueInterface, valueInterface, firstValueKind)
|
compareResult, isComparable := compare(prevValueInterface, valueInterface, firstValueKind)
|
||||||
|
|
||||||
if !isComparable {
|
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) {
|
if !containsValue(allowedComparesResults, compareResult) {
|
||||||
|
@ -50,7 +50,7 @@ func isOrdered(t TestingT, object interface{}, allowedComparesResults []compareR
|
||||||
// assert.IsIncreasing(t, []float{1, 2})
|
// assert.IsIncreasing(t, []float{1, 2})
|
||||||
// assert.IsIncreasing(t, []string{"a", "b"})
|
// assert.IsIncreasing(t, []string{"a", "b"})
|
||||||
func IsIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
|
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
|
// IsNonIncreasing asserts that the collection is not increasing
|
||||||
|
@ -59,7 +59,7 @@ func IsIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) boo
|
||||||
// assert.IsNonIncreasing(t, []float{2, 1})
|
// assert.IsNonIncreasing(t, []float{2, 1})
|
||||||
// assert.IsNonIncreasing(t, []string{"b", "a"})
|
// assert.IsNonIncreasing(t, []string{"b", "a"})
|
||||||
func IsNonIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
|
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
|
// IsDecreasing asserts that the collection is decreasing
|
||||||
|
@ -68,7 +68,7 @@ func IsNonIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{})
|
||||||
// assert.IsDecreasing(t, []float{2, 1})
|
// assert.IsDecreasing(t, []float{2, 1})
|
||||||
// assert.IsDecreasing(t, []string{"b", "a"})
|
// assert.IsDecreasing(t, []string{"b", "a"})
|
||||||
func IsDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
|
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
|
// IsNonDecreasing asserts that the collection is not decreasing
|
||||||
|
@ -77,5 +77,5 @@ func IsDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) boo
|
||||||
// assert.IsNonDecreasing(t, []float{1, 2})
|
// assert.IsNonDecreasing(t, []float{1, 2})
|
||||||
// assert.IsNonDecreasing(t, []string{"a", "b"})
|
// assert.IsNonDecreasing(t, []string{"a", "b"})
|
||||||
func IsNonDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
|
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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,7 @@ func TestIsIncreasing(t *testing.T) {
|
||||||
} {
|
} {
|
||||||
out := &outputT{buf: bytes.NewBuffer(nil)}
|
out := &outputT{buf: bytes.NewBuffer(nil)}
|
||||||
False(t, IsIncreasing(out, currCase.collection))
|
False(t, IsIncreasing(out, currCase.collection))
|
||||||
Contains(t, out.buf.String(), currCase.msg)
|
Contains(t, string(out.buf.Bytes()), currCase.msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,7 +91,7 @@ func TestIsNonIncreasing(t *testing.T) {
|
||||||
} {
|
} {
|
||||||
out := &outputT{buf: bytes.NewBuffer(nil)}
|
out := &outputT{buf: bytes.NewBuffer(nil)}
|
||||||
False(t, IsNonIncreasing(out, currCase.collection))
|
False(t, IsNonIncreasing(out, currCase.collection))
|
||||||
Contains(t, out.buf.String(), currCase.msg)
|
Contains(t, string(out.buf.Bytes()), currCase.msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,7 +136,7 @@ func TestIsDecreasing(t *testing.T) {
|
||||||
} {
|
} {
|
||||||
out := &outputT{buf: bytes.NewBuffer(nil)}
|
out := &outputT{buf: bytes.NewBuffer(nil)}
|
||||||
False(t, IsDecreasing(out, currCase.collection))
|
False(t, IsDecreasing(out, currCase.collection))
|
||||||
Contains(t, out.buf.String(), currCase.msg)
|
Contains(t, string(out.buf.Bytes()), currCase.msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,23 +181,6 @@ func TestIsNonDecreasing(t *testing.T) {
|
||||||
} {
|
} {
|
||||||
out := &outputT{buf: bytes.NewBuffer(nil)}
|
out := &outputT{buf: bytes.NewBuffer(nil)}
|
||||||
False(t, IsNonDecreasing(out, currCase.collection))
|
False(t, IsNonDecreasing(out, currCase.collection))
|
||||||
Contains(t, out.buf.String(), currCase.msg)
|
Contains(t, string(out.buf.Bytes()), currCase.msg)
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestOrderingMsgAndArgsForwarding(t *testing.T) {
|
|
||||||
msgAndArgs := []interface{}{"format %s %x", "this", 0xc001}
|
|
||||||
expectedOutput := "format this c001\n"
|
|
||||||
collection := []int{1, 2, 1}
|
|
||||||
funcs := []func(t TestingT){
|
|
||||||
func(t TestingT) { IsIncreasing(t, collection, msgAndArgs...) },
|
|
||||||
func(t TestingT) { IsNonIncreasing(t, collection, msgAndArgs...) },
|
|
||||||
func(t TestingT) { IsDecreasing(t, collection, msgAndArgs...) },
|
|
||||||
func(t TestingT) { IsNonDecreasing(t, collection, msgAndArgs...) },
|
|
||||||
}
|
|
||||||
for _, f := range funcs {
|
|
||||||
out := &outputT{buf: bytes.NewBuffer(nil)}
|
|
||||||
f(out)
|
|
||||||
Contains(t, out.buf.String(), expectedOutput)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,9 +1,8 @@
|
||||||
// Package assert provides a set of comprehensive testing tools for use with the normal Go testing system.
|
// Package assert provides a set of comprehensive testing tools for use with the normal Go testing system.
|
||||||
//
|
//
|
||||||
// # Example Usage
|
// Example Usage
|
||||||
//
|
//
|
||||||
// The following is a complete example using assert in a standard test function:
|
// The following is a complete example using assert in a standard test function:
|
||||||
//
|
|
||||||
// import (
|
// import (
|
||||||
// "testing"
|
// "testing"
|
||||||
// "github.com/stretchr/testify/assert"
|
// "github.com/stretchr/testify/assert"
|
||||||
|
@ -34,7 +33,7 @@
|
||||||
// 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.
|
// 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
|
// All assertion functions take, as the first argument, the `*testing.T` object provided by the
|
||||||
|
|
|
@ -315,25 +315,6 @@ func TestErrorWrapper(t *testing.T) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestErrorContainsWrapper(t *testing.T) {
|
|
||||||
assert := New(t)
|
|
||||||
mockAssert := New(new(testing.T))
|
|
||||||
|
|
||||||
// start with a nil error
|
|
||||||
var err error
|
|
||||||
assert.False(mockAssert.ErrorContains(err, ""),
|
|
||||||
"ErrorContains should return false for nil arg")
|
|
||||||
|
|
||||||
// now set an error
|
|
||||||
err = errors.New("some error: another error")
|
|
||||||
assert.False(mockAssert.ErrorContains(err, "different error"),
|
|
||||||
"ErrorContains should return false for different error string")
|
|
||||||
assert.True(mockAssert.ErrorContains(err, "some error"),
|
|
||||||
"ErrorContains should return true")
|
|
||||||
assert.True(mockAssert.ErrorContains(err, "another error"),
|
|
||||||
"ErrorContains should return true")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestEqualErrorWrapper(t *testing.T) {
|
func TestEqualErrorWrapper(t *testing.T) {
|
||||||
assert := New(t)
|
assert := New(t)
|
||||||
mockAssert := New(new(testing.T))
|
mockAssert := New(new(testing.T))
|
||||||
|
@ -546,7 +527,7 @@ func TestRegexpWrapper(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range cases {
|
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))
|
False(t, assert.Regexp(regexp.MustCompile(tc.rx), tc.str))
|
||||||
True(t, assert.NotRegexp(tc.rx, tc.str))
|
True(t, assert.NotRegexp(tc.rx, tc.str))
|
||||||
True(t, assert.NotRegexp(regexp.MustCompile(tc.rx), tc.str))
|
True(t, assert.NotRegexp(regexp.MustCompile(tc.rx), tc.str))
|
||||||
|
|
|
@ -12,7 +12,7 @@ import (
|
||||||
// an error if building a new request fails.
|
// an error if building a new request fails.
|
||||||
func httpCode(handler http.HandlerFunc, method, url string, values url.Values) (int, error) {
|
func httpCode(handler http.HandlerFunc, method, url string, values url.Values) (int, error) {
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
req, err := http.NewRequest(method, url, http.NoBody)
|
req, err := http.NewRequest(method, url, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return -1, err
|
return -1, err
|
||||||
}
|
}
|
||||||
|
@ -32,12 +32,12 @@ func HTTPSuccess(t TestingT, handler http.HandlerFunc, method, url string, value
|
||||||
}
|
}
|
||||||
code, err := httpCode(handler, method, url, values)
|
code, err := httpCode(handler, method, url, values)
|
||||||
if err != nil {
|
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
|
isSuccessCode := code >= http.StatusOK && code <= http.StatusPartialContent
|
||||||
if !isSuccessCode {
|
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
|
return isSuccessCode
|
||||||
|
@ -54,12 +54,12 @@ func HTTPRedirect(t TestingT, handler http.HandlerFunc, method, url string, valu
|
||||||
}
|
}
|
||||||
code, err := httpCode(handler, method, url, values)
|
code, err := httpCode(handler, method, url, values)
|
||||||
if err != nil {
|
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
|
isRedirectCode := code >= http.StatusMultipleChoices && code <= http.StatusTemporaryRedirect
|
||||||
if !isRedirectCode {
|
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
|
return isRedirectCode
|
||||||
|
@ -76,12 +76,12 @@ func HTTPError(t TestingT, handler http.HandlerFunc, method, url string, values
|
||||||
}
|
}
|
||||||
code, err := httpCode(handler, method, url, values)
|
code, err := httpCode(handler, method, url, values)
|
||||||
if err != nil {
|
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
|
isErrorCode := code >= http.StatusBadRequest
|
||||||
if !isErrorCode {
|
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
|
return isErrorCode
|
||||||
|
@ -98,12 +98,12 @@ func HTTPStatusCode(t TestingT, handler http.HandlerFunc, method, url string, va
|
||||||
}
|
}
|
||||||
code, err := httpCode(handler, method, url, values)
|
code, err := httpCode(handler, method, url, values)
|
||||||
if err != nil {
|
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
|
successful := code == statuscode
|
||||||
if !successful {
|
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
|
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.
|
// empty string if building a new request fails.
|
||||||
func HTTPBody(handler http.HandlerFunc, method, url string, values url.Values) string {
|
func HTTPBody(handler http.HandlerFunc, method, url string, values url.Values) string {
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
if len(values) > 0 {
|
req, err := http.NewRequest(method, url+"?"+values.Encode(), nil)
|
||||||
url += "?" + values.Encode()
|
|
||||||
}
|
|
||||||
req, err := http.NewRequest(method, url, http.NoBody)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
@ -138,7 +135,7 @@ func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method, url string,
|
||||||
|
|
||||||
contains := strings.Contains(body, fmt.Sprint(str))
|
contains := strings.Contains(body, fmt.Sprint(str))
|
||||||
if !contains {
|
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
|
return contains
|
||||||
|
@ -158,7 +155,7 @@ func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, method, url strin
|
||||||
|
|
||||||
contains := strings.Contains(body, fmt.Sprint(str))
|
contains := strings.Contains(body, fmt.Sprint(str))
|
||||||
if contains {
|
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
|
return !contains
|
||||||
|
|
|
@ -2,7 +2,6 @@ package assert
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"testing"
|
"testing"
|
||||||
|
@ -12,12 +11,6 @@ func httpOK(w http.ResponseWriter, r *http.Request) {
|
||||||
w.WriteHeader(http.StatusOK)
|
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) {
|
func httpRedirect(w http.ResponseWriter, r *http.Request) {
|
||||||
w.WriteHeader(http.StatusTemporaryRedirect)
|
w.WriteHeader(http.StatusTemporaryRedirect)
|
||||||
}
|
}
|
||||||
|
@ -41,33 +34,21 @@ func TestHTTPSuccess(t *testing.T) {
|
||||||
assert.Equal(HTTPSuccess(mockT2, httpRedirect, "GET", "/", nil), false)
|
assert.Equal(HTTPSuccess(mockT2, httpRedirect, "GET", "/", nil), false)
|
||||||
assert.True(mockT2.Failed())
|
assert.True(mockT2.Failed())
|
||||||
|
|
||||||
mockT3 := new(mockTestingT)
|
mockT3 := new(testing.T)
|
||||||
assert.Equal(HTTPSuccess(
|
assert.Equal(HTTPSuccess(mockT3, httpError, "GET", "/", nil), false)
|
||||||
mockT3, httpError, "GET", "/", nil,
|
|
||||||
"was not expecting a failure here",
|
|
||||||
), false)
|
|
||||||
assert.True(mockT3.Failed())
|
assert.True(mockT3.Failed())
|
||||||
assert.Contains(mockT3.errorString(), "was not expecting a failure here")
|
|
||||||
|
|
||||||
mockT4 := new(testing.T)
|
mockT4 := new(testing.T)
|
||||||
assert.Equal(HTTPSuccess(mockT4, httpStatusCode, "GET", "/", nil), false)
|
assert.Equal(HTTPSuccess(mockT4, httpStatusCode, "GET", "/", nil), false)
|
||||||
assert.True(mockT4.Failed())
|
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) {
|
func TestHTTPRedirect(t *testing.T) {
|
||||||
assert := New(t)
|
assert := New(t)
|
||||||
|
|
||||||
mockT1 := new(mockTestingT)
|
mockT1 := new(testing.T)
|
||||||
assert.Equal(HTTPRedirect(
|
assert.Equal(HTTPRedirect(mockT1, httpOK, "GET", "/", nil), false)
|
||||||
mockT1, httpOK, "GET", "/", nil,
|
|
||||||
"was expecting a 3xx status code. Got 200.",
|
|
||||||
), false)
|
|
||||||
assert.True(mockT1.Failed())
|
assert.True(mockT1.Failed())
|
||||||
assert.Contains(mockT1.errorString(), "was expecting a 3xx status code. Got 200.")
|
|
||||||
|
|
||||||
mockT2 := new(testing.T)
|
mockT2 := new(testing.T)
|
||||||
assert.Equal(HTTPRedirect(mockT2, httpRedirect, "GET", "/", nil), true)
|
assert.Equal(HTTPRedirect(mockT2, httpRedirect, "GET", "/", nil), true)
|
||||||
|
@ -89,13 +70,9 @@ func TestHTTPError(t *testing.T) {
|
||||||
assert.Equal(HTTPError(mockT1, httpOK, "GET", "/", nil), false)
|
assert.Equal(HTTPError(mockT1, httpOK, "GET", "/", nil), false)
|
||||||
assert.True(mockT1.Failed())
|
assert.True(mockT1.Failed())
|
||||||
|
|
||||||
mockT2 := new(mockTestingT)
|
mockT2 := new(testing.T)
|
||||||
assert.Equal(HTTPError(
|
assert.Equal(HTTPError(mockT2, httpRedirect, "GET", "/", nil), false)
|
||||||
mockT2, httpRedirect, "GET", "/", nil,
|
|
||||||
"Expected this request to error out. But it didn't",
|
|
||||||
), false)
|
|
||||||
assert.True(mockT2.Failed())
|
assert.True(mockT2.Failed())
|
||||||
assert.Contains(mockT2.errorString(), "Expected this request to error out. But it didn't")
|
|
||||||
|
|
||||||
mockT3 := new(testing.T)
|
mockT3 := new(testing.T)
|
||||||
assert.Equal(HTTPError(mockT3, httpError, "GET", "/", nil), true)
|
assert.Equal(HTTPError(mockT3, httpError, "GET", "/", nil), true)
|
||||||
|
@ -117,13 +94,9 @@ func TestHTTPStatusCode(t *testing.T) {
|
||||||
assert.Equal(HTTPStatusCode(mockT2, httpRedirect, "GET", "/", nil, http.StatusSwitchingProtocols), false)
|
assert.Equal(HTTPStatusCode(mockT2, httpRedirect, "GET", "/", nil, http.StatusSwitchingProtocols), false)
|
||||||
assert.True(mockT2.Failed())
|
assert.True(mockT2.Failed())
|
||||||
|
|
||||||
mockT3 := new(mockTestingT)
|
mockT3 := new(testing.T)
|
||||||
assert.Equal(HTTPStatusCode(
|
assert.Equal(HTTPStatusCode(mockT3, httpError, "GET", "/", nil, http.StatusSwitchingProtocols), false)
|
||||||
mockT3, httpError, "GET", "/", nil, http.StatusSwitchingProtocols,
|
|
||||||
"Expected the status code to be %d", http.StatusSwitchingProtocols,
|
|
||||||
), false)
|
|
||||||
assert.True(mockT3.Failed())
|
assert.True(mockT3.Failed())
|
||||||
assert.Contains(mockT3.errorString(), "Expected the status code to be 101")
|
|
||||||
|
|
||||||
mockT4 := new(testing.T)
|
mockT4 := new(testing.T)
|
||||||
assert.Equal(HTTPStatusCode(mockT4, httpStatusCode, "GET", "/", nil, http.StatusSwitchingProtocols), true)
|
assert.Equal(HTTPStatusCode(mockT4, httpStatusCode, "GET", "/", nil, http.StatusSwitchingProtocols), true)
|
||||||
|
@ -149,7 +122,7 @@ func TestHTTPStatusesWrapper(t *testing.T) {
|
||||||
|
|
||||||
func httpHelloName(w http.ResponseWriter, r *http.Request) {
|
func httpHelloName(w http.ResponseWriter, r *http.Request) {
|
||||||
name := r.FormValue("name")
|
name := r.FormValue("name")
|
||||||
_, _ = fmt.Fprintf(w, "Hello, %s!", name)
|
w.Write([]byte(fmt.Sprintf("Hello, %s!", name)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHTTPRequestWithNoParams(t *testing.T) {
|
func TestHTTPRequestWithNoParams(t *testing.T) {
|
||||||
|
@ -183,21 +156,15 @@ func TestHTTPRequestWithParams(t *testing.T) {
|
||||||
|
|
||||||
func TestHttpBody(t *testing.T) {
|
func TestHttpBody(t *testing.T) {
|
||||||
assert := New(t)
|
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"}}, "Hello, World!"))
|
||||||
assert.True(HTTPBodyContains(mockT, httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "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(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"}}, "Hello, World!"))
|
||||||
assert.False(HTTPBodyNotContains(
|
assert.False(HTTPBodyNotContains(mockT, httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "World"))
|
||||||
mockT, httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "World",
|
|
||||||
"Expected the request body to not contain 'World'. But it did.",
|
|
||||||
))
|
|
||||||
assert.True(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) {
|
func TestHttpBodyWrappers(t *testing.T) {
|
||||||
|
@ -211,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"}}, "Hello, World!"))
|
||||||
assert.False(mockAssert.HTTPBodyNotContains(httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "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"))
|
assert.True(mockAssert.HTTPBodyNotContains(httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "world"))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
|
|
@ -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"))
|
|
||||||
}
|
|
|
@ -1,25 +0,0 @@
|
||||||
//go:build testify_yaml_custom && !testify_yaml_fail && !testify_yaml_default
|
|
||||||
// +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
|
|
|
@ -1,37 +0,0 @@
|
||||||
//go:build !testify_yaml_fail && !testify_yaml_custom
|
|
||||||
// +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)
|
|
||||||
}
|
|
|
@ -1,18 +0,0 @@
|
||||||
//go:build testify_yaml_fail && !testify_yaml_custom && !testify_yaml_default
|
|
||||||
// +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
|
|
||||||
}
|
|
18
doc.go
18
doc.go
|
@ -1,15 +1,23 @@
|
||||||
|
// ** 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.
|
// 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 assert package provides a comprehensive set of assertion functions that tie in to the Go testing system.
|
// The assert package provides a comprehensive set of assertion functions that tie in to the Go testing system.
|
||||||
//
|
//
|
||||||
|
// The http package contains tools to make it easier to test http activity using the Go testing system.
|
||||||
|
//
|
||||||
// The mock package provides a system by which it is possible to mock your objects and verify calls are happening as expected.
|
// The mock package provides a system by which it is possible to mock your objects and verify calls are happening as expected.
|
||||||
//
|
//
|
||||||
// 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.
|
// 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.
|
||||||
//
|
|
||||||
// A [golangci-lint] compatible linter for testify is available called [testifylint].
|
|
||||||
//
|
|
||||||
// [golangci-lint]: https://golangci-lint.run/
|
|
||||||
// [testifylint]: https://github.com/Antonboom/testifylint
|
|
||||||
package testify
|
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"
|
||||||
|
)
|
||||||
|
|
14
go.mod
14
go.mod
|
@ -1,16 +1,10 @@
|
||||||
module github.com/stretchr/testify
|
module github.com/stretchr/testify
|
||||||
|
|
||||||
// This should match the minimum supported version that is tested in
|
go 1.13
|
||||||
// .github/workflows/main.yml
|
|
||||||
go 1.17
|
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/davecgh/go-spew v1.1.1
|
github.com/davecgh/go-spew v1.1.0
|
||||||
github.com/pmezard/go-difflib v1.0.0
|
github.com/pmezard/go-difflib v1.0.0
|
||||||
github.com/stretchr/objx v0.5.2
|
github.com/stretchr/objx v0.1.0
|
||||||
gopkg.in/yaml.v3 v3.0.1
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c
|
||||||
)
|
)
|
||||||
|
|
||||||
// Break dependency cycle with objx.
|
|
||||||
// See https://github.com/stretchr/objx/pull/140
|
|
||||||
exclude github.com/stretchr/testify v1.8.2
|
|
||||||
|
|
14
go.sum
14
go.sum
|
@ -1,18 +1,10 @@
|
||||||
|
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
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 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
|
||||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
|
||||||
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/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
|
||||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
|
||||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
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/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
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=
|
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
// Deprecated: Use [net/http/httptest] instead.
|
// Package http DEPRECATED USE net/http/httptest
|
||||||
package http
|
package http
|
||||||
|
|
|
@ -4,7 +4,7 @@ import (
|
||||||
"net/http"
|
"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 {
|
type TestResponseWriter struct {
|
||||||
|
|
||||||
// StatusCode is the last int written by the call to WriteHeader(int)
|
// StatusCode is the last int written by the call to WriteHeader(int)
|
||||||
|
@ -17,7 +17,7 @@ type TestResponseWriter struct {
|
||||||
header http.Header
|
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 {
|
func (rw *TestResponseWriter) Header() http.Header {
|
||||||
|
|
||||||
if rw.header == nil {
|
if rw.header == nil {
|
||||||
|
@ -27,7 +27,7 @@ func (rw *TestResponseWriter) Header() http.Header {
|
||||||
return rw.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) {
|
func (rw *TestResponseWriter) Write(bytes []byte) (int, error) {
|
||||||
|
|
||||||
// assume 200 success if no header has been set
|
// 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) {
|
func (rw *TestResponseWriter) WriteHeader(i int) {
|
||||||
rw.StatusCode = i
|
rw.StatusCode = i
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,12 +6,12 @@ import (
|
||||||
"github.com/stretchr/testify/mock"
|
"github.com/stretchr/testify/mock"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Deprecated: Use [net/http/httptest] instead.
|
// TestRoundTripper DEPRECATED USE net/http/httptest
|
||||||
type TestRoundTripper struct {
|
type TestRoundTripper struct {
|
||||||
mock.Mock
|
mock.Mock
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: Use [net/http/httptest] instead.
|
// RoundTrip DEPRECATED USE net/http/httptest
|
||||||
func (t *TestRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
|
func (t *TestRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||||
args := t.Called(req)
|
args := t.Called(req)
|
||||||
return args.Get(0).(*http.Response), args.Error(1)
|
return args.Get(0).(*http.Response), args.Error(1)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// Package mock provides a system by which it is possible to mock your objects
|
// Package mock provides a system by which it is possible to mock your objects
|
||||||
// and verify calls are happening as expected.
|
// 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
|
// The mock package provides an object, Mock, that tracks activity on another object. It is usually
|
||||||
// embedded into a test object as shown below:
|
// embedded into a test object as shown below:
|
||||||
|
|
442
mock/mock.go
442
mock/mock.go
|
@ -3,7 +3,6 @@ package mock
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"path"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
"regexp"
|
"regexp"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
@ -14,13 +13,9 @@ import (
|
||||||
"github.com/davecgh/go-spew/spew"
|
"github.com/davecgh/go-spew/spew"
|
||||||
"github.com/pmezard/go-difflib/difflib"
|
"github.com/pmezard/go-difflib/difflib"
|
||||||
"github.com/stretchr/objx"
|
"github.com/stretchr/objx"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
// regex for GCCGO functions
|
|
||||||
var gccgoRE = regexp.MustCompile(`\.pN\d+_`)
|
|
||||||
|
|
||||||
// TestingT is an interface wrapper around *testing.T
|
// TestingT is an interface wrapper around *testing.T
|
||||||
type TestingT interface {
|
type TestingT interface {
|
||||||
Logf(format string, args ...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
|
// if the PanicMsg is set to a non nil string the function call will panic
|
||||||
// irrespective of other settings
|
// irrespective of other settings
|
||||||
PanicMsg *string
|
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{
|
return &Call{
|
||||||
Parent: parent,
|
Parent: parent,
|
||||||
Method: methodName,
|
Method: methodName,
|
||||||
Arguments: methodArguments,
|
Arguments: methodArguments,
|
||||||
ReturnArguments: returnArguments,
|
ReturnArguments: make([]interface{}, 0),
|
||||||
callerInfo: callerInfo,
|
callerInfo: callerInfo,
|
||||||
Repeatability: 0,
|
Repeatability: 0,
|
||||||
WaitFor: nil,
|
WaitFor: nil,
|
||||||
|
@ -114,7 +106,7 @@ func (c *Call) Return(returnArguments ...interface{}) *Call {
|
||||||
return c
|
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 {
|
func (c *Call) Panic(msg string) *Call {
|
||||||
|
@ -126,21 +118,21 @@ func (c *Call) Panic(msg string) *Call {
|
||||||
return c
|
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 {
|
func (c *Call) Once() *Call {
|
||||||
return c.Times(1)
|
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 {
|
func (c *Call) Twice() *Call {
|
||||||
return c.Times(2)
|
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.
|
// of times.
|
||||||
//
|
//
|
||||||
// Mock.On("MyMethod", arg1, arg2).Return(returnArg1, returnArg2).Times(5)
|
// Mock.On("MyMethod", arg1, arg2).Return(returnArg1, returnArg2).Times(5)
|
||||||
|
@ -202,98 +194,11 @@ func (c *Call) Maybe() *Call {
|
||||||
// Mock.
|
// Mock.
|
||||||
// On("MyMethod", 1).Return(nil).
|
// On("MyMethod", 1).Return(nil).
|
||||||
// On("MyOtherMethod", 'a', 'b', 'c').Return(errors.New("Some Error"))
|
// On("MyOtherMethod", 'a', 'b', 'c').Return(errors.New("Some Error"))
|
||||||
//
|
|
||||||
//go:noinline
|
//go:noinline
|
||||||
func (c *Call) On(methodName string, arguments ...interface{}) *Call {
|
func (c *Call) On(methodName string, arguments ...interface{}) *Call {
|
||||||
return c.Parent.On(methodName, arguments...)
|
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.
|
// 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
|
// For an example of its usage, refer to the "Example Usage" section at the top
|
||||||
// of this document.
|
// of this document.
|
||||||
|
@ -316,17 +221,10 @@ type Mock struct {
|
||||||
mutex sync.Mutex
|
mutex sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
// String provides a %v format string for Mock.
|
|
||||||
// Note: this is used implicitly by Arguments.Diff if a Mock is passed.
|
|
||||||
// It exists because go's default %v formatting traverses the struct
|
|
||||||
// without acquiring the mutex, which is detected by go test -race.
|
|
||||||
func (m *Mock) String() string {
|
|
||||||
return fmt.Sprintf("%[1]T<%[1]p>", m)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestData holds any data that might be useful for testing. Testify ignores
|
// TestData holds any data that might be useful for testing. Testify ignores
|
||||||
// this data completely allowing you to do whatever you like with it.
|
// this data completely allowing you to do whatever you like with it.
|
||||||
func (m *Mock) TestData() objx.Map {
|
func (m *Mock) TestData() objx.Map {
|
||||||
|
|
||||||
if m.testData == nil {
|
if m.testData == nil {
|
||||||
m.testData = make(objx.Map)
|
m.testData = make(objx.Map)
|
||||||
}
|
}
|
||||||
|
@ -338,10 +236,7 @@ func (m *Mock) TestData() objx.Map {
|
||||||
Setting expectations
|
Setting expectations
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Test sets the [TestingT] on which errors will be reported, otherwise errors
|
// Test sets the test struct variable of the mock object
|
||||||
// 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.
|
|
||||||
func (m *Mock) Test(t TestingT) {
|
func (m *Mock) Test(t TestingT) {
|
||||||
m.mutex.Lock()
|
m.mutex.Lock()
|
||||||
defer m.mutex.Unlock()
|
defer m.mutex.Unlock()
|
||||||
|
@ -375,8 +270,7 @@ func (m *Mock) On(methodName string, arguments ...interface{}) *Call {
|
||||||
|
|
||||||
m.mutex.Lock()
|
m.mutex.Lock()
|
||||||
defer m.mutex.Unlock()
|
defer m.mutex.Unlock()
|
||||||
|
c := newCall(m, methodName, assert.CallerInfo(), arguments...)
|
||||||
c := newCall(m, methodName, assert.CallerInfo(), arguments, make([]interface{}, 0))
|
|
||||||
m.ExpectedCalls = append(m.ExpectedCalls, c)
|
m.ExpectedCalls = append(m.ExpectedCalls, c)
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
@ -452,14 +346,11 @@ func (m *Mock) findClosestCall(method string, arguments ...interface{}) (*Call,
|
||||||
}
|
}
|
||||||
|
|
||||||
func callString(method string, arguments Arguments, includeArgumentValues bool) string {
|
func callString(method string, arguments Arguments, includeArgumentValues bool) string {
|
||||||
|
|
||||||
var argValsString string
|
var argValsString string
|
||||||
if includeArgumentValues {
|
if includeArgumentValues {
|
||||||
var argVals []string
|
var argVals []string
|
||||||
for argIndex, arg := range arguments {
|
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))
|
argVals = append(argVals, fmt.Sprintf("%d: %#v", argIndex, arg))
|
||||||
}
|
}
|
||||||
argValsString = fmt.Sprintf("\n\t\t%s", strings.Join(argVals, "\n\t\t"))
|
argValsString = fmt.Sprintf("\n\t\t%s", strings.Join(argVals, "\n\t\t"))
|
||||||
|
@ -479,12 +370,13 @@ func (m *Mock) Called(arguments ...interface{}) Arguments {
|
||||||
panic("Couldn't get the caller information")
|
panic("Couldn't get the caller information")
|
||||||
}
|
}
|
||||||
functionPath := runtime.FuncForPC(pc).Name()
|
functionPath := runtime.FuncForPC(pc).Name()
|
||||||
// Next four lines are required to use GCCGO function naming conventions.
|
//Next four lines are required to use GCCGO function naming conventions.
|
||||||
// For Ex: github_com_docker_libkv_store_mock.WatchTree.pN39_github_com_docker_libkv_store_mock.Mock
|
//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
|
//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>.
|
//With GCCGO we need to remove interface information starting from pN<dd>.
|
||||||
if gccgoRE.MatchString(functionPath) {
|
re := regexp.MustCompile("\\.pN\\d+_")
|
||||||
functionPath = gccgoRE.Split(functionPath, -1)[0]
|
if re.MatchString(functionPath) {
|
||||||
|
functionPath = re.Split(functionPath, -1)[0]
|
||||||
}
|
}
|
||||||
parts := strings.Split(functionPath, ".")
|
parts := strings.Split(functionPath, ".")
|
||||||
functionName := parts[len(parts)-1]
|
functionName := parts[len(parts)-1]
|
||||||
|
@ -497,14 +389,14 @@ func (m *Mock) Called(arguments ...interface{}) Arguments {
|
||||||
// If Call.WaitFor is set, blocks until the channel is closed or receives a message.
|
// If Call.WaitFor is set, blocks until the channel is closed or receives a message.
|
||||||
func (m *Mock) MethodCalled(methodName string, arguments ...interface{}) Arguments {
|
func (m *Mock) MethodCalled(methodName string, arguments ...interface{}) Arguments {
|
||||||
m.mutex.Lock()
|
m.mutex.Lock()
|
||||||
// TODO: could combine expected and closes in single loop
|
//TODO: could combine expected and closes in single loop
|
||||||
found, call := m.findExpectedCall(methodName, arguments...)
|
found, call := m.findExpectedCall(methodName, arguments...)
|
||||||
|
|
||||||
if found < 0 {
|
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 {
|
if call != nil {
|
||||||
m.mutex.Unlock()
|
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
|
// we have to fail here - because we don't know what to do
|
||||||
// as the return arguments. This is because:
|
// as the return arguments. This is because:
|
||||||
|
@ -516,34 +408,14 @@ func (m *Mock) MethodCalled(methodName string, arguments ...interface{}) Argumen
|
||||||
m.mutex.Unlock()
|
m.mutex.Unlock()
|
||||||
|
|
||||||
if closestCall != nil {
|
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, arguments, true),
|
||||||
callString(methodName, closestCall.Arguments, true),
|
callString(methodName, closestCall.Arguments, true),
|
||||||
diffArguments(closestCall.Arguments, arguments),
|
diffArguments(closestCall.Arguments, arguments),
|
||||||
strings.TrimSpace(mismatch),
|
strings.TrimSpace(mismatch),
|
||||||
assert.CallerInfo(),
|
|
||||||
)
|
)
|
||||||
} else {
|
} 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())
|
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())
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -555,7 +427,7 @@ func (m *Mock) MethodCalled(methodName string, arguments ...interface{}) Argumen
|
||||||
call.totalCalls++
|
call.totalCalls++
|
||||||
|
|
||||||
// add the call
|
// 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()
|
m.mutex.Unlock()
|
||||||
|
|
||||||
// block if specified
|
// block if specified
|
||||||
|
@ -591,7 +463,7 @@ func (m *Mock) MethodCalled(methodName string, arguments ...interface{}) Argumen
|
||||||
Assertions
|
Assertions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
type assertExpectationiser interface {
|
type assertExpectationser interface {
|
||||||
AssertExpectations(TestingT) bool
|
AssertExpectations(TestingT) bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -604,11 +476,11 @@ func AssertExpectationsForObjects(t TestingT, testObjects ...interface{}) bool {
|
||||||
h.Helper()
|
h.Helper()
|
||||||
}
|
}
|
||||||
for _, obj := range testObjects {
|
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)")
|
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) {
|
if !m.AssertExpectations(t) {
|
||||||
t.Logf("Expectations didn't match for Mock: %+v", reflect.TypeOf(m))
|
t.Logf("Expectations didn't match for Mock: %+v", reflect.TypeOf(m))
|
||||||
return false
|
return false
|
||||||
|
@ -620,42 +492,37 @@ func AssertExpectationsForObjects(t TestingT, testObjects ...interface{}) bool {
|
||||||
// AssertExpectations asserts that everything specified with On and Return was
|
// AssertExpectations asserts that everything specified with On and Return was
|
||||||
// in fact called as expected. Calls may have occurred in any order.
|
// in fact called as expected. Calls may have occurred in any order.
|
||||||
func (m *Mock) AssertExpectations(t TestingT) bool {
|
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 {
|
if h, ok := t.(tHelper); ok {
|
||||||
h.Helper()
|
h.Helper()
|
||||||
}
|
}
|
||||||
|
|
||||||
m.mutex.Lock()
|
m.mutex.Lock()
|
||||||
defer m.mutex.Unlock()
|
defer m.mutex.Unlock()
|
||||||
|
var somethingMissing bool
|
||||||
var failedExpectations int
|
var failedExpectations int
|
||||||
|
|
||||||
// iterate through each expectation
|
// iterate through each expectation
|
||||||
expectedCalls := m.expectedCalls()
|
expectedCalls := m.expectedCalls()
|
||||||
for _, expectedCall := range expectedCalls {
|
for _, expectedCall := range expectedCalls {
|
||||||
satisfied, reason := m.checkExpectation(expectedCall)
|
if !expectedCall.optional && !m.methodWasCalled(expectedCall.Method, expectedCall.Arguments) && expectedCall.totalCalls == 0 {
|
||||||
if !satisfied {
|
somethingMissing = true
|
||||||
failedExpectations++
|
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())
|
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
|
return !somethingMissing
|
||||||
}
|
|
||||||
|
|
||||||
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())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// AssertNumberOfCalls asserts that the method was called expectedCalls times.
|
// AssertNumberOfCalls asserts that the method was called expectedCalls times.
|
||||||
|
@ -789,80 +656,34 @@ const (
|
||||||
Anything = "mock.Anything"
|
Anything = "mock.Anything"
|
||||||
)
|
)
|
||||||
|
|
||||||
// AnythingOfTypeArgument contains the type of an argument
|
// AnythingOfTypeArgument is a string that 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
|
|
||||||
// for use when type checking. Used in Diff and Assert.
|
// for use when type checking. Used in Diff and Assert.
|
||||||
type anythingOfTypeArgument string
|
type AnythingOfTypeArgument string
|
||||||
|
|
||||||
// AnythingOfType returns a special value containing the
|
// AnythingOfType returns an AnythingOfTypeArgument object containing the
|
||||||
// name of the type to check for. The type name will be matched against the type name returned by [reflect.Type.String].
|
// name of the type to check for. Used in Diff and Assert.
|
||||||
//
|
|
||||||
// Used in Diff and Assert.
|
|
||||||
//
|
//
|
||||||
// For example:
|
// For example:
|
||||||
//
|
// Assert(t, AnythingOfType("string"), AnythingOfType("int"))
|
||||||
// args.Assert(t, AnythingOfType("string"), AnythingOfType("int"))
|
|
||||||
func AnythingOfType(t string) AnythingOfTypeArgument {
|
func AnythingOfType(t string) AnythingOfTypeArgument {
|
||||||
return anythingOfTypeArgument(t)
|
return AnythingOfTypeArgument(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsTypeArgument is a struct that contains the type of an argument
|
// IsTypeArgument is a struct that contains the type of an argument
|
||||||
// for use when type checking. This is an alternative to [AnythingOfType].
|
// for use when type checking. This is an alternative to AnythingOfType.
|
||||||
// Used in [Arguments.Diff] and [Arguments.Assert].
|
// Used in Diff and Assert.
|
||||||
type IsTypeArgument struct {
|
type IsTypeArgument struct {
|
||||||
t reflect.Type
|
t interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsType returns an IsTypeArgument object containing the type to check for.
|
// 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
|
// 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:
|
// For example:
|
||||||
//
|
// Assert(t, IsType(""), IsType(0))
|
||||||
// args.Assert(t, IsType(""), IsType(0))
|
|
||||||
func IsType(t interface{}) *IsTypeArgument {
|
func IsType(t interface{}) *IsTypeArgument {
|
||||||
return &IsTypeArgument{t: reflect.TypeOf(t)}
|
return &IsTypeArgument{t: 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,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// argumentMatcher performs custom argument matching, returning whether or
|
// argumentMatcher performs custom argument matching, returning whether or
|
||||||
|
@ -899,7 +720,7 @@ func (f argumentMatcher) Matches(argument interface{}) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f argumentMatcher) String() string {
|
func (f argumentMatcher) String() string {
|
||||||
return fmt.Sprintf("func(%s) bool", f.fn.Type().In(0).String())
|
return fmt.Sprintf("func(%s) bool", f.fn.Type().In(0).Name())
|
||||||
}
|
}
|
||||||
|
|
||||||
// MatchedBy can be used to match a mock call based on only certain properties
|
// MatchedBy can be used to match a mock call based on only certain properties
|
||||||
|
@ -908,11 +729,10 @@ func (f argumentMatcher) String() string {
|
||||||
// and false otherwise.
|
// and false otherwise.
|
||||||
//
|
//
|
||||||
// Example:
|
// 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)
|
// |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,
|
// which returns a bool. If |fn| doesn't match the required signature,
|
||||||
// MatchedBy() panics.
|
// MatchedBy() panics.
|
||||||
func MatchedBy(fn interface{}) argumentMatcher {
|
func MatchedBy(fn interface{}) argumentMatcher {
|
||||||
fnType := reflect.TypeOf(fn)
|
fnType := reflect.TypeOf(fn)
|
||||||
|
@ -953,12 +773,12 @@ func (args Arguments) Is(objects ...interface{}) bool {
|
||||||
//
|
//
|
||||||
// Returns the diff string and number of differences found.
|
// Returns the diff string and number of differences found.
|
||||||
func (args Arguments) Diff(objects []interface{}) (string, int) {
|
func (args Arguments) Diff(objects []interface{}) (string, int) {
|
||||||
// TODO: could return string as error and nil for No difference
|
//TODO: could return string as error and nil for No difference
|
||||||
|
|
||||||
output := "\n"
|
var output = "\n"
|
||||||
var differences int
|
var differences int
|
||||||
|
|
||||||
maxArgCount := len(args)
|
var maxArgCount = len(args)
|
||||||
if len(objects) > maxArgCount {
|
if len(objects) > maxArgCount {
|
||||||
maxArgCount = len(objects)
|
maxArgCount = len(objects)
|
||||||
}
|
}
|
||||||
|
@ -984,58 +804,31 @@ func (args Arguments) Diff(objects []interface{}) (string, int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if matcher, ok := expected.(argumentMatcher); ok {
|
if matcher, ok := expected.(argumentMatcher); ok {
|
||||||
var matches bool
|
if matcher.Matches(actual) {
|
||||||
func() {
|
|
||||||
defer func() {
|
|
||||||
if r := recover(); r != nil {
|
|
||||||
actualFmt = fmt.Sprintf("panic in argument matcher: %v", r)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
matches = matcher.Matches(actual)
|
|
||||||
}()
|
|
||||||
if matches {
|
|
||||||
output = fmt.Sprintf("%s\t%d: PASS: %s matched by %s\n", output, i, actualFmt, matcher)
|
output = fmt.Sprintf("%s\t%d: PASS: %s matched by %s\n", output, i, actualFmt, matcher)
|
||||||
} else {
|
} else {
|
||||||
differences++
|
differences++
|
||||||
output = fmt.Sprintf("%s\t%d: FAIL: %s not matched by %s\n", output, i, actualFmt, matcher)
|
output = fmt.Sprintf("%s\t%d: FAIL: %s not matched by %s\n", output, i, actualFmt, matcher)
|
||||||
}
|
}
|
||||||
} else {
|
} else if reflect.TypeOf(expected) == reflect.TypeOf((*AnythingOfTypeArgument)(nil)).Elem() {
|
||||||
switch expected := expected.(type) {
|
|
||||||
case anythingOfTypeArgument:
|
|
||||||
// type checking
|
// type checking
|
||||||
if reflect.TypeOf(actual).Name() != string(expected) && reflect.TypeOf(actual).String() != string(expected) {
|
if reflect.TypeOf(actual).Name() != string(expected.(AnythingOfTypeArgument)) && reflect.TypeOf(actual).String() != string(expected.(AnythingOfTypeArgument)) {
|
||||||
// not match
|
// not match
|
||||||
differences++
|
differences++
|
||||||
output = fmt.Sprintf("%s\t%d: FAIL: type %s != type %s - %s\n", output, i, expected, reflect.TypeOf(actual).Name(), actualFmt)
|
output = fmt.Sprintf("%s\t%d: FAIL: type %s != type %s - %s\n", output, i, expected, reflect.TypeOf(actual).Name(), actualFmt)
|
||||||
}
|
}
|
||||||
case *IsTypeArgument:
|
|
||||||
actualT := reflect.TypeOf(actual)
|
|
||||||
if actualT != expected.t {
|
|
||||||
differences++
|
|
||||||
output = fmt.Sprintf("%s\t%d: FAIL: type %s != type %s - %s\n", output, i, expected.t.Name(), actualT.Name(), actualFmt)
|
|
||||||
}
|
|
||||||
case *FunctionalOptionsArgument:
|
|
||||||
var name string
|
|
||||||
if len(expected.values) > 0 {
|
|
||||||
name = "[]" + reflect.TypeOf(expected.values[0]).String()
|
|
||||||
}
|
|
||||||
|
|
||||||
const tName = "[]interface{}"
|
} else if reflect.TypeOf(expected) == reflect.TypeOf((*IsTypeArgument)(nil)) {
|
||||||
if name != reflect.TypeOf(actual).String() && len(expected.values) != 0 {
|
t := expected.(*IsTypeArgument).t
|
||||||
|
if reflect.TypeOf(t) != reflect.TypeOf(actual) {
|
||||||
differences++
|
differences++
|
||||||
output = fmt.Sprintf("%s\t%d: FAIL: type %s != type %s - %s\n", output, i, tName, reflect.TypeOf(actual).Name(), actualFmt)
|
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 {
|
|
||||||
if ef, af := assertOpts(expected.values, actual); ef == "" && af == "" {
|
|
||||||
// match
|
|
||||||
output = fmt.Sprintf("%s\t%d: PASS: %s == %s\n", output, i, tName, tName)
|
|
||||||
} else {
|
|
||||||
// not match
|
|
||||||
differences++
|
|
||||||
output = fmt.Sprintf("%s\t%d: FAIL: %s != %s\n", output, i, af, ef)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// normal checking
|
||||||
|
|
||||||
default:
|
|
||||||
if assert.ObjectsAreEqual(expected, Anything) || assert.ObjectsAreEqual(actual, Anything) || assert.ObjectsAreEqual(actual, expected) {
|
if assert.ObjectsAreEqual(expected, Anything) || assert.ObjectsAreEqual(actual, Anything) || assert.ObjectsAreEqual(actual, expected) {
|
||||||
// match
|
// match
|
||||||
output = fmt.Sprintf("%s\t%d: PASS: %s == %s\n", output, i, actualFmt, expectedFmt)
|
output = fmt.Sprintf("%s\t%d: PASS: %s == %s\n", output, i, actualFmt, expectedFmt)
|
||||||
|
@ -1045,7 +838,6 @@ func (args Arguments) Diff(objects []interface{}) (string, int) {
|
||||||
output = fmt.Sprintf("%s\t%d: FAIL: %s != %s\n", output, i, actualFmt, expectedFmt)
|
output = fmt.Sprintf("%s\t%d: FAIL: %s != %s\n", output, i, actualFmt, expectedFmt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1054,6 +846,7 @@ func (args Arguments) Diff(objects []interface{}) (string, int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return output, differences
|
return output, differences
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assert compares the arguments with the specified objects and fails if
|
// Assert compares the arguments with the specified objects and fails if
|
||||||
|
@ -1075,6 +868,7 @@ func (args Arguments) Assert(t TestingT, objects ...interface{}) bool {
|
||||||
t.Errorf("%sArguments do not match.", assert.CallerInfo())
|
t.Errorf("%sArguments do not match.", assert.CallerInfo())
|
||||||
|
|
||||||
return false
|
return false
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// String gets the argument at the specified index. Panics if there is no argument, or
|
// String gets the argument at the specified index. Panics if there is no argument, or
|
||||||
|
@ -1083,6 +877,7 @@ func (args Arguments) Assert(t TestingT, objects ...interface{}) bool {
|
||||||
// If no index is provided, String() returns a complete string representation
|
// If no index is provided, String() returns a complete string representation
|
||||||
// of the arguments.
|
// of the arguments.
|
||||||
func (args Arguments) String(indexOrNil ...int) string {
|
func (args Arguments) String(indexOrNil ...int) string {
|
||||||
|
|
||||||
if len(indexOrNil) == 0 {
|
if len(indexOrNil) == 0 {
|
||||||
// normal String() method - return a string representation of the args
|
// normal String() method - return a string representation of the args
|
||||||
var argsStr []string
|
var argsStr []string
|
||||||
|
@ -1092,7 +887,7 @@ func (args Arguments) String(indexOrNil ...int) string {
|
||||||
return strings.Join(argsStr, ",")
|
return strings.Join(argsStr, ",")
|
||||||
} else if len(indexOrNil) == 1 {
|
} else if len(indexOrNil) == 1 {
|
||||||
// Index has been specified - get the argument at that index
|
// Index has been specified - get the argument at that index
|
||||||
index := indexOrNil[0]
|
var index = indexOrNil[0]
|
||||||
var s string
|
var s string
|
||||||
var ok bool
|
var ok bool
|
||||||
if s, ok = args.Get(index).(string); !ok {
|
if s, ok = args.Get(index).(string); !ok {
|
||||||
|
@ -1102,6 +897,7 @@ func (args Arguments) String(indexOrNil ...int) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
panic(fmt.Sprintf("assert: arguments: Wrong number of arguments passed to String. Must be 0 or 1, not %d", len(indexOrNil)))
|
panic(fmt.Sprintf("assert: arguments: Wrong number of arguments passed to String. Must be 0 or 1, not %d", len(indexOrNil)))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Int gets the argument at the specified index. Panics if there is no argument, or
|
// Int gets the argument at the specified index. Panics if there is no argument, or
|
||||||
|
@ -1125,7 +921,7 @@ func (args Arguments) Error(index int) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if s, ok = obj.(error); !ok {
|
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
|
return s
|
||||||
}
|
}
|
||||||
|
@ -1210,89 +1006,3 @@ var spewConfig = spew.ConfigState{
|
||||||
type tHelper interface {
|
type tHelper interface {
|
||||||
Helper()
|
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
|
|
||||||
}
|
|
||||||
|
|
|
@ -32,40 +32,6 @@ func (i *TestExampleImplementation) TheExampleMethod(a, b, c int) (int, error) {
|
||||||
return args.Int(0), errors.New("Whoops")
|
return args.Int(0), errors.New("Whoops")
|
||||||
}
|
}
|
||||||
|
|
||||||
type options struct {
|
|
||||||
num int
|
|
||||||
str string
|
|
||||||
}
|
|
||||||
|
|
||||||
type OptionFn func(*options)
|
|
||||||
|
|
||||||
func OpNum(n int) OptionFn {
|
|
||||||
return func(o *options) {
|
|
||||||
o.num = n
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func OpStr(s string) OptionFn {
|
|
||||||
return func(o *options) {
|
|
||||||
o.str = s
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func OpBytes(b []byte) OptionFn {
|
|
||||||
return func(m *options) {
|
|
||||||
m.str = string(b)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *TestExampleImplementation) TheExampleMethodFunctionalOptions(x string, opts ...OptionFn) error {
|
|
||||||
args := i.Called(x, opts)
|
|
||||||
return args.Error(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TheExampleMethodFunctionalOptionsIndirect(i *TestExampleImplementation) {
|
|
||||||
i.TheExampleMethodFunctionalOptions("test", OpNum(1), OpStr("foo"))
|
|
||||||
}
|
|
||||||
|
|
||||||
//go:noinline
|
//go:noinline
|
||||||
func (i *TestExampleImplementation) TheExampleMethod2(yesorno bool) {
|
func (i *TestExampleImplementation) TheExampleMethod2(yesorno bool) {
|
||||||
i.Called(yesorno)
|
i.Called(yesorno)
|
||||||
|
@ -185,7 +151,7 @@ func Test_Mock_Chained_On(t *testing.T) {
|
||||||
var mockedService = new(TestExampleImplementation)
|
var mockedService = new(TestExampleImplementation)
|
||||||
|
|
||||||
// determine our current line number so we can assert the expected calls callerInfo properly
|
// determine our current line number so we can assert the expected calls callerInfo properly
|
||||||
_, filename, line, _ := runtime.Caller(0)
|
_, _, line, _ := runtime.Caller(0)
|
||||||
mockedService.
|
mockedService.
|
||||||
On("TheExampleMethod", 1, 2, 3).
|
On("TheExampleMethod", 1, 2, 3).
|
||||||
Return(0).
|
Return(0).
|
||||||
|
@ -198,14 +164,14 @@ func Test_Mock_Chained_On(t *testing.T) {
|
||||||
Method: "TheExampleMethod",
|
Method: "TheExampleMethod",
|
||||||
Arguments: []interface{}{1, 2, 3},
|
Arguments: []interface{}{1, 2, 3},
|
||||||
ReturnArguments: []interface{}{0},
|
ReturnArguments: []interface{}{0},
|
||||||
callerInfo: []string{fmt.Sprintf("%s:%d", filename, line+2)},
|
callerInfo: []string{fmt.Sprintf("mock_test.go:%d", line+2)},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Parent: &mockedService.Mock,
|
Parent: &mockedService.Mock,
|
||||||
Method: "TheExampleMethod3",
|
Method: "TheExampleMethod3",
|
||||||
Arguments: []interface{}{AnythingOfType("*mock.ExampleType")},
|
Arguments: []interface{}{AnythingOfType("*mock.ExampleType")},
|
||||||
ReturnArguments: []interface{}{nil},
|
ReturnArguments: []interface{}{nil},
|
||||||
callerInfo: []string{fmt.Sprintf("%s:%d", filename, line+4)},
|
callerInfo: []string{fmt.Sprintf("mock_test.go:%d", line+4)},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
assert.Equal(t, expectedCalls, mockedService.ExpectedCalls)
|
assert.Equal(t, expectedCalls, mockedService.ExpectedCalls)
|
||||||
|
@ -267,32 +233,6 @@ func Test_Mock_On_WithIntArgMatcher(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_Mock_On_WithArgMatcherThatPanics(t *testing.T) {
|
|
||||||
var mockedService TestExampleImplementation
|
|
||||||
|
|
||||||
mockedService.On("TheExampleMethod2", MatchedBy(func(_ interface{}) bool {
|
|
||||||
panic("try to lock mockedService")
|
|
||||||
})).Return()
|
|
||||||
|
|
||||||
defer func() {
|
|
||||||
assertedExpectations := make(chan struct{})
|
|
||||||
go func() {
|
|
||||||
tt := new(testing.T)
|
|
||||||
mockedService.AssertExpectations(tt)
|
|
||||||
close(assertedExpectations)
|
|
||||||
}()
|
|
||||||
select {
|
|
||||||
case <-assertedExpectations:
|
|
||||||
case <-time.After(time.Second):
|
|
||||||
t.Fatal("AssertExpectations() deadlocked, did the panic leave mockedService locked?")
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
assert.Panics(t, func() {
|
|
||||||
mockedService.TheExampleMethod2(false)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestMock_WithTest(t *testing.T) {
|
func TestMock_WithTest(t *testing.T) {
|
||||||
var (
|
var (
|
||||||
mockedService TestExampleImplementation
|
mockedService TestExampleImplementation
|
||||||
|
@ -522,161 +462,6 @@ func Test_Mock_On_WithFuncTypeArg(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_Mock_Unset(t *testing.T) {
|
|
||||||
// make a test impl object
|
|
||||||
var mockedService = new(TestExampleImplementation)
|
|
||||||
|
|
||||||
call := mockedService.
|
|
||||||
On("TheExampleMethodFuncType", "argA").
|
|
||||||
Return("blah")
|
|
||||||
|
|
||||||
found, foundCall := mockedService.findExpectedCall("TheExampleMethodFuncType", "argA")
|
|
||||||
require.NotEqual(t, -1, found)
|
|
||||||
require.Equal(t, foundCall, call)
|
|
||||||
|
|
||||||
call.Unset()
|
|
||||||
|
|
||||||
found, foundCall = mockedService.findExpectedCall("TheExampleMethodFuncType", "argA")
|
|
||||||
require.Equal(t, -1, found)
|
|
||||||
|
|
||||||
var expectedCall *Call
|
|
||||||
require.Equal(t, expectedCall, foundCall)
|
|
||||||
|
|
||||||
fn := func(string) error { return nil }
|
|
||||||
assert.Panics(t, func() {
|
|
||||||
mockedService.TheExampleMethodFuncType(fn)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Since every time you call On it creates a new object
|
|
||||||
// the last time you call Unset it will only unset the last call
|
|
||||||
func Test_Mock_Chained_UnsetOnlyUnsetsLastCall(t *testing.T) {
|
|
||||||
// make a test impl object
|
|
||||||
var mockedService = new(TestExampleImplementation)
|
|
||||||
|
|
||||||
// determine our current line number so we can assert the expected calls callerInfo properly
|
|
||||||
_, filename, line, _ := runtime.Caller(0)
|
|
||||||
mockedService.
|
|
||||||
On("TheExampleMethod1", 1, 1).
|
|
||||||
Return(0).
|
|
||||||
On("TheExampleMethod2", 2, 2).
|
|
||||||
On("TheExampleMethod3", 3, 3, 3).
|
|
||||||
Return(nil).
|
|
||||||
Unset()
|
|
||||||
|
|
||||||
expectedCalls := []*Call{
|
|
||||||
{
|
|
||||||
Parent: &mockedService.Mock,
|
|
||||||
Method: "TheExampleMethod1",
|
|
||||||
Arguments: []interface{}{1, 1},
|
|
||||||
ReturnArguments: []interface{}{0},
|
|
||||||
callerInfo: []string{fmt.Sprintf("%s:%d", filename, line+2)},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Parent: &mockedService.Mock,
|
|
||||||
Method: "TheExampleMethod2",
|
|
||||||
Arguments: []interface{}{2, 2},
|
|
||||||
ReturnArguments: []interface{}{},
|
|
||||||
callerInfo: []string{fmt.Sprintf("%s:%d", filename, line+4)},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
assert.Equal(t, 2, len(expectedCalls))
|
|
||||||
assert.Equal(t, expectedCalls, mockedService.ExpectedCalls)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_Mock_UnsetIfAlreadyUnsetFails(t *testing.T) {
|
|
||||||
// make a test impl object
|
|
||||||
var mockedService = new(TestExampleImplementation)
|
|
||||||
|
|
||||||
mock1 := mockedService.
|
|
||||||
On("TheExampleMethod1", 1, 1).
|
|
||||||
Return(1)
|
|
||||||
|
|
||||||
assert.Equal(t, 1, len(mockedService.ExpectedCalls))
|
|
||||||
mock1.Unset()
|
|
||||||
assert.Equal(t, 0, len(mockedService.ExpectedCalls))
|
|
||||||
|
|
||||||
assert.Panics(t, func() {
|
|
||||||
mock1.Unset()
|
|
||||||
})
|
|
||||||
|
|
||||||
assert.Equal(t, 0, len(mockedService.ExpectedCalls))
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_Mock_UnsetByOnMethodSpec(t *testing.T) {
|
|
||||||
// make a test impl object
|
|
||||||
var mockedService = new(TestExampleImplementation)
|
|
||||||
|
|
||||||
mock1 := mockedService.
|
|
||||||
On("TheExampleMethod", 1, 2, 3).
|
|
||||||
Return(0, nil)
|
|
||||||
|
|
||||||
assert.Equal(t, 1, len(mockedService.ExpectedCalls))
|
|
||||||
mock1.On("TheExampleMethod", 1, 2, 3).
|
|
||||||
Return(0, nil).Unset()
|
|
||||||
|
|
||||||
assert.Equal(t, 0, len(mockedService.ExpectedCalls))
|
|
||||||
|
|
||||||
assert.Panics(t, func() {
|
|
||||||
mock1.Unset()
|
|
||||||
})
|
|
||||||
|
|
||||||
assert.Equal(t, 0, len(mockedService.ExpectedCalls))
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_Mock_UnsetByOnMethodSpecAmongOthers(t *testing.T) {
|
|
||||||
// make a test impl object
|
|
||||||
var mockedService = new(TestExampleImplementation)
|
|
||||||
|
|
||||||
_, filename, line, _ := runtime.Caller(0)
|
|
||||||
mock1 := mockedService.
|
|
||||||
On("TheExampleMethod", 1, 2, 3).
|
|
||||||
Return(0, nil).
|
|
||||||
On("TheExampleMethodVariadic", 1, 2, 3, 4, 5).Once().
|
|
||||||
Return(nil)
|
|
||||||
mock1.
|
|
||||||
On("TheExampleMethodFuncType", Anything).
|
|
||||||
Return(nil)
|
|
||||||
|
|
||||||
assert.Equal(t, 3, len(mockedService.ExpectedCalls))
|
|
||||||
mock1.On("TheExampleMethod", 1, 2, 3).
|
|
||||||
Return(0, nil).Unset()
|
|
||||||
|
|
||||||
assert.Equal(t, 2, len(mockedService.ExpectedCalls))
|
|
||||||
|
|
||||||
expectedCalls := []*Call{
|
|
||||||
{
|
|
||||||
Parent: &mockedService.Mock,
|
|
||||||
Method: "TheExampleMethodVariadic",
|
|
||||||
Repeatability: 1,
|
|
||||||
Arguments: []interface{}{1, 2, 3, 4, 5},
|
|
||||||
ReturnArguments: []interface{}{nil},
|
|
||||||
callerInfo: []string{fmt.Sprintf("%s:%d", filename, line+4)},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Parent: &mockedService.Mock,
|
|
||||||
Method: "TheExampleMethodFuncType",
|
|
||||||
Arguments: []interface{}{Anything},
|
|
||||||
ReturnArguments: []interface{}{nil},
|
|
||||||
callerInfo: []string{fmt.Sprintf("%s:%d", filename, line+7)},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
assert.Equal(t, 2, len(mockedService.ExpectedCalls))
|
|
||||||
assert.Equal(t, expectedCalls, mockedService.ExpectedCalls)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_Mock_Unset_WithFuncPanics(t *testing.T) {
|
|
||||||
// make a test impl object
|
|
||||||
var mockedService = new(TestExampleImplementation)
|
|
||||||
mock1 := mockedService.On("TheExampleMethod", 1)
|
|
||||||
mock1.Arguments = append(mock1.Arguments, func(string) error { return nil })
|
|
||||||
|
|
||||||
assert.Panics(t, func() {
|
|
||||||
mock1.Unset()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_Mock_Return(t *testing.T) {
|
func Test_Mock_Return(t *testing.T) {
|
||||||
|
|
||||||
// make a test impl object
|
// make a test impl object
|
||||||
|
@ -928,245 +713,6 @@ func Test_Mock_Return_Nothing(t *testing.T) {
|
||||||
assert.Equal(t, 0, len(call.ReturnArguments))
|
assert.Equal(t, 0, len(call.ReturnArguments))
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_Mock_Return_NotBefore_In_Order(t *testing.T) {
|
|
||||||
var mockedService = new(TestExampleImplementation)
|
|
||||||
|
|
||||||
b := mockedService.
|
|
||||||
On("TheExampleMethod", 1, 2, 3).
|
|
||||||
Return(4, nil)
|
|
||||||
c := mockedService.
|
|
||||||
On("TheExampleMethod2", true).
|
|
||||||
Return().
|
|
||||||
NotBefore(b)
|
|
||||||
|
|
||||||
require.Equal(t, []*Call{b, c}, mockedService.ExpectedCalls)
|
|
||||||
require.NotPanics(t, func() {
|
|
||||||
mockedService.TheExampleMethod(1, 2, 3)
|
|
||||||
})
|
|
||||||
require.NotPanics(t, func() {
|
|
||||||
mockedService.TheExampleMethod2(true)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_Mock_Return_InOrder_Uses_NotBefore(t *testing.T) {
|
|
||||||
var mockedService = new(TestExampleImplementation)
|
|
||||||
|
|
||||||
InOrder(
|
|
||||||
mockedService.
|
|
||||||
On("TheExampleMethod", 1, 2, 3).
|
|
||||||
Return(4, nil),
|
|
||||||
mockedService.
|
|
||||||
On("TheExampleMethod2", true).
|
|
||||||
Return(),
|
|
||||||
)
|
|
||||||
|
|
||||||
require.NotPanics(t, func() {
|
|
||||||
mockedService.TheExampleMethod(1, 2, 3)
|
|
||||||
})
|
|
||||||
require.NotPanics(t, func() {
|
|
||||||
mockedService.TheExampleMethod2(true)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_Mock_Return_NotBefore_Out_Of_Order(t *testing.T) {
|
|
||||||
var mockedService = new(TestExampleImplementation)
|
|
||||||
|
|
||||||
b := mockedService.
|
|
||||||
On("TheExampleMethod", 1, 2, 3).
|
|
||||||
Return(4, nil).Twice()
|
|
||||||
c := mockedService.
|
|
||||||
On("TheExampleMethod2", true).
|
|
||||||
Return().
|
|
||||||
NotBefore(b)
|
|
||||||
|
|
||||||
require.Equal(t, []*Call{b, c}, mockedService.ExpectedCalls)
|
|
||||||
|
|
||||||
expectedPanicString := `mock: Unexpected Method Call
|
|
||||||
-----------------------------
|
|
||||||
|
|
||||||
TheExampleMethod2(bool)
|
|
||||||
0: true
|
|
||||||
|
|
||||||
Must not be called before:
|
|
||||||
|
|
||||||
TheExampleMethod(int,int,int)
|
|
||||||
0: 1
|
|
||||||
1: 2
|
|
||||||
2: 3`
|
|
||||||
require.PanicsWithValue(t, expectedPanicString, func() {
|
|
||||||
mockedService.TheExampleMethod2(true)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_Mock_Return_InOrder_Uses_NotBefore_Out_Of_Order(t *testing.T) {
|
|
||||||
var mockedService = new(TestExampleImplementation)
|
|
||||||
|
|
||||||
InOrder(
|
|
||||||
mockedService.
|
|
||||||
On("TheExampleMethod", 1, 2, 3).
|
|
||||||
Return(4, nil).Twice(),
|
|
||||||
mockedService.
|
|
||||||
On("TheExampleMethod2", true).
|
|
||||||
Return(),
|
|
||||||
)
|
|
||||||
|
|
||||||
expectedPanicString := `mock: Unexpected Method Call
|
|
||||||
-----------------------------
|
|
||||||
|
|
||||||
TheExampleMethod2(bool)
|
|
||||||
0: true
|
|
||||||
|
|
||||||
Must not be called before:
|
|
||||||
|
|
||||||
TheExampleMethod(int,int,int)
|
|
||||||
0: 1
|
|
||||||
1: 2
|
|
||||||
2: 3`
|
|
||||||
require.PanicsWithValue(t, expectedPanicString, func() {
|
|
||||||
mockedService.TheExampleMethod2(true)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_Mock_Return_NotBefore_Not_Enough_Times(t *testing.T) {
|
|
||||||
var mockedService = new(TestExampleImplementation)
|
|
||||||
|
|
||||||
b := mockedService.
|
|
||||||
On("TheExampleMethod", 1, 2, 3).
|
|
||||||
Return(4, nil).Twice()
|
|
||||||
c := mockedService.
|
|
||||||
On("TheExampleMethod2", true).
|
|
||||||
Return().
|
|
||||||
NotBefore(b)
|
|
||||||
|
|
||||||
require.Equal(t, []*Call{b, c}, mockedService.ExpectedCalls)
|
|
||||||
|
|
||||||
require.NotPanics(t, func() {
|
|
||||||
mockedService.TheExampleMethod(1, 2, 3)
|
|
||||||
})
|
|
||||||
expectedPanicString := `mock: Unexpected Method Call
|
|
||||||
-----------------------------
|
|
||||||
|
|
||||||
TheExampleMethod2(bool)
|
|
||||||
0: true
|
|
||||||
|
|
||||||
Must not be called before another call of:
|
|
||||||
|
|
||||||
TheExampleMethod(int,int,int)
|
|
||||||
0: 1
|
|
||||||
1: 2
|
|
||||||
2: 3`
|
|
||||||
require.PanicsWithValue(t, expectedPanicString, func() {
|
|
||||||
mockedService.TheExampleMethod2(true)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_Mock_Return_NotBefore_Different_Mock_In_Order(t *testing.T) {
|
|
||||||
var (
|
|
||||||
mockedService1 = new(TestExampleImplementation)
|
|
||||||
mockedService2 = new(TestExampleImplementation)
|
|
||||||
)
|
|
||||||
|
|
||||||
b := mockedService1.
|
|
||||||
On("TheExampleMethod", 1, 2, 3).
|
|
||||||
Return(4, nil)
|
|
||||||
c := mockedService2.
|
|
||||||
On("TheExampleMethod2", true).
|
|
||||||
Return().
|
|
||||||
NotBefore(b)
|
|
||||||
|
|
||||||
require.Equal(t, []*Call{c}, mockedService2.ExpectedCalls)
|
|
||||||
require.NotPanics(t, func() {
|
|
||||||
mockedService1.TheExampleMethod(1, 2, 3)
|
|
||||||
})
|
|
||||||
require.NotPanics(t, func() {
|
|
||||||
mockedService2.TheExampleMethod2(true)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_Mock_Return_NotBefore_Different_Mock_Out_Of_Order(t *testing.T) {
|
|
||||||
var (
|
|
||||||
mockedService1 = new(TestExampleImplementation)
|
|
||||||
mockedService2 = new(TestExampleImplementation)
|
|
||||||
)
|
|
||||||
|
|
||||||
b := mockedService1.
|
|
||||||
On("TheExampleMethod", 1, 2, 3).
|
|
||||||
Return(4, nil)
|
|
||||||
c := mockedService2.
|
|
||||||
On("TheExampleMethod2", true).
|
|
||||||
Return().
|
|
||||||
NotBefore(b)
|
|
||||||
|
|
||||||
require.Equal(t, []*Call{c}, mockedService2.ExpectedCalls)
|
|
||||||
|
|
||||||
expectedPanicString := `mock: Unexpected Method Call
|
|
||||||
-----------------------------
|
|
||||||
|
|
||||||
TheExampleMethod2(bool)
|
|
||||||
0: true
|
|
||||||
|
|
||||||
Must not be called before method from another mock instance:
|
|
||||||
|
|
||||||
TheExampleMethod(int,int,int)
|
|
||||||
0: 1
|
|
||||||
1: 2
|
|
||||||
2: 3`
|
|
||||||
require.PanicsWithValue(t, expectedPanicString, func() {
|
|
||||||
mockedService2.TheExampleMethod2(true)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_Mock_Return_NotBefore_In_Order_With_Non_Dependant(t *testing.T) {
|
|
||||||
var mockedService = new(TestExampleImplementation)
|
|
||||||
|
|
||||||
a := mockedService.
|
|
||||||
On("TheExampleMethod", 1, 2, 3).
|
|
||||||
Return(4, nil)
|
|
||||||
b := mockedService.
|
|
||||||
On("TheExampleMethod", 4, 5, 6).
|
|
||||||
Return(4, nil)
|
|
||||||
c := mockedService.
|
|
||||||
On("TheExampleMethod2", true).
|
|
||||||
Return().
|
|
||||||
NotBefore(a, b)
|
|
||||||
d := mockedService.
|
|
||||||
On("TheExampleMethod7", []bool{}).Return(nil)
|
|
||||||
|
|
||||||
require.Equal(t, []*Call{a, b, c, d}, mockedService.ExpectedCalls)
|
|
||||||
require.NotPanics(t, func() {
|
|
||||||
mockedService.TheExampleMethod7([]bool{})
|
|
||||||
})
|
|
||||||
require.NotPanics(t, func() {
|
|
||||||
mockedService.TheExampleMethod(1, 2, 3)
|
|
||||||
})
|
|
||||||
require.NotPanics(t, func() {
|
|
||||||
mockedService.TheExampleMethod7([]bool{})
|
|
||||||
})
|
|
||||||
require.NotPanics(t, func() {
|
|
||||||
mockedService.TheExampleMethod(4, 5, 6)
|
|
||||||
})
|
|
||||||
require.NotPanics(t, func() {
|
|
||||||
mockedService.TheExampleMethod7([]bool{})
|
|
||||||
})
|
|
||||||
require.NotPanics(t, func() {
|
|
||||||
mockedService.TheExampleMethod2(true)
|
|
||||||
})
|
|
||||||
require.NotPanics(t, func() {
|
|
||||||
mockedService.TheExampleMethod7([]bool{})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_Mock_Return_NotBefore_Orphan_Call(t *testing.T) {
|
|
||||||
var mockedService = new(TestExampleImplementation)
|
|
||||||
|
|
||||||
require.PanicsWithValue(t, "not before calls must be created with Mock.On()", func() {
|
|
||||||
mockedService.
|
|
||||||
On("TheExampleMethod2", true).
|
|
||||||
Return().
|
|
||||||
NotBefore(&Call{Method: "Not", Arguments: Arguments{"how", "it's"}, ReturnArguments: Arguments{"done"}})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_Mock_findExpectedCall(t *testing.T) {
|
func Test_Mock_findExpectedCall(t *testing.T) {
|
||||||
|
|
||||||
m := new(Mock)
|
m := new(Mock)
|
||||||
|
@ -1267,7 +813,7 @@ func Test_Mock_Called_blocks(t *testing.T) {
|
||||||
|
|
||||||
var mockedService = new(TestExampleImplementation)
|
var mockedService = new(TestExampleImplementation)
|
||||||
|
|
||||||
mockedService.Mock.On("asyncCall", 1, 2, 3).Return(5, "6", true).After(20 * time.Millisecond)
|
mockedService.Mock.On("asyncCall", 1, 2, 3).Return(5, "6", true).After(2 * time.Millisecond)
|
||||||
|
|
||||||
ch := make(chan Arguments)
|
ch := make(chan Arguments)
|
||||||
|
|
||||||
|
@ -1276,7 +822,7 @@ func Test_Mock_Called_blocks(t *testing.T) {
|
||||||
select {
|
select {
|
||||||
case <-ch:
|
case <-ch:
|
||||||
t.Fatal("should have waited")
|
t.Fatal("should have waited")
|
||||||
case <-time.After(10 * time.Millisecond):
|
case <-time.After(1 * time.Millisecond):
|
||||||
}
|
}
|
||||||
|
|
||||||
returnArguments := <-ch
|
returnArguments := <-ch
|
||||||
|
@ -1369,7 +915,6 @@ func Test_AssertExpectationsForObjects_Helper(t *testing.T) {
|
||||||
var mockedService1 = new(TestExampleImplementation)
|
var mockedService1 = new(TestExampleImplementation)
|
||||||
var mockedService2 = new(TestExampleImplementation)
|
var mockedService2 = new(TestExampleImplementation)
|
||||||
var mockedService3 = new(TestExampleImplementation)
|
var mockedService3 = new(TestExampleImplementation)
|
||||||
var mockedService4 = new(TestExampleImplementation) // No expectations does not cause a panic
|
|
||||||
|
|
||||||
mockedService1.On("Test_AssertExpectationsForObjects_Helper", 1).Return()
|
mockedService1.On("Test_AssertExpectationsForObjects_Helper", 1).Return()
|
||||||
mockedService2.On("Test_AssertExpectationsForObjects_Helper", 2).Return()
|
mockedService2.On("Test_AssertExpectationsForObjects_Helper", 2).Return()
|
||||||
|
@ -1379,8 +924,8 @@ func Test_AssertExpectationsForObjects_Helper(t *testing.T) {
|
||||||
mockedService2.Called(2)
|
mockedService2.Called(2)
|
||||||
mockedService3.Called(3)
|
mockedService3.Called(3)
|
||||||
|
|
||||||
assert.True(t, AssertExpectationsForObjects(t, &mockedService1.Mock, &mockedService2.Mock, &mockedService3.Mock, &mockedService4.Mock))
|
assert.True(t, AssertExpectationsForObjects(t, &mockedService1.Mock, &mockedService2.Mock, &mockedService3.Mock))
|
||||||
assert.True(t, AssertExpectationsForObjects(t, mockedService1, mockedService2, mockedService3, mockedService4))
|
assert.True(t, AssertExpectationsForObjects(t, mockedService1, mockedService2, mockedService3))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1499,85 +1044,6 @@ func Test_Mock_AssertExpectationsCustomType(t *testing.T) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_Mock_AssertExpectationsFunctionalOptionsType(t *testing.T) {
|
|
||||||
|
|
||||||
var mockedService = new(TestExampleImplementation)
|
|
||||||
|
|
||||||
mockedService.On("TheExampleMethodFunctionalOptions", "test", FunctionalOptions(OpNum(1), OpStr("foo"))).Return(nil).Once()
|
|
||||||
|
|
||||||
tt := new(testing.T)
|
|
||||||
assert.False(t, mockedService.AssertExpectations(tt))
|
|
||||||
|
|
||||||
// make the call now
|
|
||||||
mockedService.TheExampleMethodFunctionalOptions("test", OpNum(1), OpStr("foo"))
|
|
||||||
|
|
||||||
// now assert expectations
|
|
||||||
assert.True(t, mockedService.AssertExpectations(tt))
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_Mock_AssertExpectationsFunctionalOptionsType_Empty(t *testing.T) {
|
|
||||||
|
|
||||||
var mockedService = new(TestExampleImplementation)
|
|
||||||
|
|
||||||
mockedService.On("TheExampleMethodFunctionalOptions", "test", FunctionalOptions()).Return(nil).Once()
|
|
||||||
|
|
||||||
tt := new(testing.T)
|
|
||||||
assert.False(t, mockedService.AssertExpectations(tt))
|
|
||||||
|
|
||||||
// make the call now
|
|
||||||
mockedService.TheExampleMethodFunctionalOptions("test")
|
|
||||||
|
|
||||||
// now assert expectations
|
|
||||||
assert.True(t, mockedService.AssertExpectations(tt))
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_Mock_AssertExpectationsFunctionalOptionsType_Indirectly(t *testing.T) {
|
|
||||||
|
|
||||||
var mockedService = new(TestExampleImplementation)
|
|
||||||
|
|
||||||
mockedService.On("TheExampleMethodFunctionalOptions", "test", FunctionalOptions(OpNum(1), OpStr("foo"))).Return(nil).Once()
|
|
||||||
|
|
||||||
tt := new(testing.T)
|
|
||||||
assert.False(t, mockedService.AssertExpectations(tt))
|
|
||||||
|
|
||||||
// make the call now
|
|
||||||
TheExampleMethodFunctionalOptionsIndirect(mockedService)
|
|
||||||
|
|
||||||
// now assert expectations
|
|
||||||
assert.True(t, mockedService.AssertExpectations(tt))
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_Mock_AssertExpectationsFunctionalOptionsType_Diff_Func(t *testing.T) {
|
|
||||||
|
|
||||||
var mockedService = new(TestExampleImplementation)
|
|
||||||
|
|
||||||
mockedService.On("TheExampleMethodFunctionalOptions", "test", FunctionalOptions(OpStr("this"))).Return(nil).Once()
|
|
||||||
|
|
||||||
tt := new(testing.T)
|
|
||||||
assert.False(t, mockedService.AssertExpectations(tt))
|
|
||||||
|
|
||||||
assert.Panics(t, func() {
|
|
||||||
mockedService.TheExampleMethodFunctionalOptions("test", OpBytes([]byte("this")))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_Mock_AssertExpectationsFunctionalOptionsType_Diff_Arg(t *testing.T) {
|
|
||||||
|
|
||||||
var mockedService = new(TestExampleImplementation)
|
|
||||||
|
|
||||||
mockedService.On("TheExampleMethodFunctionalOptions", "test", FunctionalOptions(OpStr("this"))).Return(nil).Once()
|
|
||||||
|
|
||||||
tt := new(testing.T)
|
|
||||||
assert.False(t, mockedService.AssertExpectations(tt))
|
|
||||||
|
|
||||||
assert.Panics(t, func() {
|
|
||||||
mockedService.TheExampleMethodFunctionalOptions("test", OpStr("that"))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_Mock_AssertExpectations_With_Repeatability(t *testing.T) {
|
func Test_Mock_AssertExpectations_With_Repeatability(t *testing.T) {
|
||||||
|
|
||||||
var mockedService = new(TestExampleImplementation)
|
var mockedService = new(TestExampleImplementation)
|
||||||
|
@ -1599,16 +1065,6 @@ func Test_Mock_AssertExpectations_With_Repeatability(t *testing.T) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_Mock_AssertExpectations_Skipped_Test(t *testing.T) {
|
|
||||||
|
|
||||||
var mockedService = new(TestExampleImplementation)
|
|
||||||
|
|
||||||
mockedService.On("Test_Mock_AssertExpectations_Skipped_Test", 1, 2, 3).Return(5, 6, 7)
|
|
||||||
defer mockedService.AssertExpectations(t)
|
|
||||||
|
|
||||||
t.Skip("skipping test to ensure AssertExpectations does not fail")
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_Mock_TwoCallsWithDifferentArguments(t *testing.T) {
|
func Test_Mock_TwoCallsWithDifferentArguments(t *testing.T) {
|
||||||
|
|
||||||
var mockedService = new(TestExampleImplementation)
|
var mockedService = new(TestExampleImplementation)
|
||||||
|
@ -1732,14 +1188,17 @@ func Test_Mock_IsMethodCallable(t *testing.T) {
|
||||||
|
|
||||||
func TestIsArgsEqual(t *testing.T) {
|
func TestIsArgsEqual(t *testing.T) {
|
||||||
var expected = Arguments{5, 3, 4, 6, 7, 2}
|
var expected = Arguments{5, 3, 4, 6, 7, 2}
|
||||||
|
var args = make([]interface{}, 5)
|
||||||
// Copy elements 1 to 5
|
for i := 1; i < len(expected); i++ {
|
||||||
args := append(([]interface{})(nil), expected[1:]...)
|
args[i-1] = expected[i]
|
||||||
|
}
|
||||||
args[2] = expected[1]
|
args[2] = expected[1]
|
||||||
assert.False(t, isArgsEqual(expected, args))
|
assert.False(t, isArgsEqual(expected, args))
|
||||||
|
|
||||||
// Clone
|
var arr = make([]interface{}, 6)
|
||||||
arr := append(([]interface{})(nil), expected...)
|
for i := 0; i < len(expected); i++ {
|
||||||
|
arr[i] = expected[i]
|
||||||
|
}
|
||||||
assert.True(t, isArgsEqual(expected, arr))
|
assert.True(t, isArgsEqual(expected, arr))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1769,7 +1228,7 @@ func Test_Mock_AssertOptional(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Arguments helper methods
|
Arguments helper methods
|
||||||
*/
|
*/
|
||||||
func Test_Arguments_Get(t *testing.T) {
|
func Test_Arguments_Get(t *testing.T) {
|
||||||
|
|
||||||
|
@ -2023,10 +1482,6 @@ func (s *timer) GetTime(i int) string {
|
||||||
return s.Called(i).Get(0).(string)
|
return s.Called(i).Get(0).(string)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *timer) GetTimes(times []int) string {
|
|
||||||
return s.Called(times).Get(0).(string)
|
|
||||||
}
|
|
||||||
|
|
||||||
type tCustomLogger struct {
|
type tCustomLogger struct {
|
||||||
*testing.T
|
*testing.T
|
||||||
logs []string
|
logs []string
|
||||||
|
@ -2075,7 +1530,7 @@ func TestAfterTotalWaitTimeWhileExecution(t *testing.T) {
|
||||||
|
|
||||||
end := time.Now()
|
end := time.Now()
|
||||||
elapsedTime := end.Sub(start)
|
elapsedTime := end.Sub(start)
|
||||||
assert.True(t, elapsedTime > waitMs, fmt.Sprintf("Total elapsed time:%v should be at least greater than %v", elapsedTime, waitMs))
|
assert.True(t, elapsedTime > waitMs, fmt.Sprintf("Total elapsed time:%v should be atleast greater than %v", elapsedTime, waitMs))
|
||||||
assert.Equal(t, total, len(results))
|
assert.Equal(t, total, len(results))
|
||||||
for i := range results {
|
for i := range results {
|
||||||
assert.Equal(t, fmt.Sprintf("Time%d", i), results[i], "Return value of method should be same")
|
assert.Equal(t, fmt.Sprintf("Time%d", i), results[i], "Return value of method should be same")
|
||||||
|
@ -2086,7 +1541,7 @@ func TestArgumentMatcherToPrintMismatch(t *testing.T) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if r := recover(); r != nil {
|
if r := recover(); r != nil {
|
||||||
matchingExp := regexp.MustCompile(
|
matchingExp := regexp.MustCompile(
|
||||||
`\s+mock: Unexpected Method Call\s+-*\s+GetTime\(int\)\s+0: 1\s+The closest call I have is:\s+GetTime\(mock.argumentMatcher\)\s+0: mock.argumentMatcher\{.*?\}\s+Diff:.*\(int=1\) not matched by func\(int\) bool\nat: \[[^\]]+mock\/mock_test.go`)
|
`\s+mock: Unexpected Method Call\s+-*\s+GetTime\(int\)\s+0: 1\s+The closest call I have is:\s+GetTime\(mock.argumentMatcher\)\s+0: mock.argumentMatcher\{.*?\}\s+Diff:.*\(int=1\) not matched by func\(int\) bool`)
|
||||||
assert.Regexp(t, matchingExp, r)
|
assert.Regexp(t, matchingExp, r)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
@ -2099,23 +1554,6 @@ func TestArgumentMatcherToPrintMismatch(t *testing.T) {
|
||||||
m.AssertExpectations(t)
|
m.AssertExpectations(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestArgumentMatcherToPrintMismatchWithReferenceType(t *testing.T) {
|
|
||||||
defer func() {
|
|
||||||
if r := recover(); r != nil {
|
|
||||||
matchingExp := regexp.MustCompile(
|
|
||||||
`\s+mock: Unexpected Method Call\s+-*\s+GetTimes\(\[\]int\)\s+0: \[\]int\{1\}\s+The closest call I have is:\s+GetTimes\(mock.argumentMatcher\)\s+0: mock.argumentMatcher\{.*?\}\s+Diff:.*\(\[\]int=\[1\]\) not matched by func\(\[\]int\) bool\nat: \[[^\]]+mock\/mock_test.go`)
|
|
||||||
assert.Regexp(t, matchingExp, r)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
m := new(timer)
|
|
||||||
m.On("GetTimes", MatchedBy(func(_ []int) bool { return false })).Return("SomeTime").Once()
|
|
||||||
|
|
||||||
res := m.GetTimes([]int{1})
|
|
||||||
require.Equal(t, "SomeTime", res)
|
|
||||||
m.AssertExpectations(t)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestClosestCallMismatchedArgumentInformationShowsTheClosest(t *testing.T) {
|
func TestClosestCallMismatchedArgumentInformationShowsTheClosest(t *testing.T) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if r := recover(); r != nil {
|
if r := recover(); r != nil {
|
||||||
|
@ -2134,7 +1572,7 @@ func TestClosestCallMismatchedArgumentInformationShowsTheClosest(t *testing.T) {
|
||||||
func TestClosestCallFavorsFirstMock(t *testing.T) {
|
func TestClosestCallFavorsFirstMock(t *testing.T) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if r := recover(); r != nil {
|
if r := recover(); r != nil {
|
||||||
diffRegExp := `Difference found in argument 0:\s+--- Expected\s+\+\+\+ Actual\s+@@ -2,4 \+2,4 @@\s+\(bool\) true,\s+- \(bool\) true,\s+- \(bool\) true\s+\+ \(bool\) false,\s+\+ \(bool\) false\s+}\s+Diff: 0: FAIL: \(\[\]bool=\[(true\s?|false\s?){3}]\) != \(\[\]bool=\[(true\s?|false\s?){3}\]\)`
|
diffRegExp := `Difference found in argument 0:\s+--- Expected\s+\+\+\+ Actual\s+@@ -2,4 \+2,4 @@\s+\(bool\) true,\s+- \(bool\) true,\s+- \(bool\) true\s+\+ \(bool\) false,\s+\+ \(bool\) false\s+}\s+`
|
||||||
matchingExp := regexp.MustCompile(unexpectedCallRegex(`TheExampleMethod7([]bool)`, `0: \[\]bool{true, false, false}`, `0: \[\]bool{true, true, true}`, diffRegExp))
|
matchingExp := regexp.MustCompile(unexpectedCallRegex(`TheExampleMethod7([]bool)`, `0: \[\]bool{true, false, false}`, `0: \[\]bool{true, true, true}`, diffRegExp))
|
||||||
assert.Regexp(t, matchingExp, r)
|
assert.Regexp(t, matchingExp, r)
|
||||||
}
|
}
|
||||||
|
@ -2150,7 +1588,7 @@ func TestClosestCallFavorsFirstMock(t *testing.T) {
|
||||||
func TestClosestCallUsesRepeatabilityToFindClosest(t *testing.T) {
|
func TestClosestCallUsesRepeatabilityToFindClosest(t *testing.T) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if r := recover(); r != nil {
|
if r := recover(); r != nil {
|
||||||
diffRegExp := `Difference found in argument 0:\s+--- Expected\s+\+\+\+ Actual\s+@@ -1,4 \+1,4 @@\s+\(\[\]bool\) \(len=3\) {\s+- \(bool\) false,\s+- \(bool\) false,\s+\+ \(bool\) true,\s+\+ \(bool\) true,\s+\(bool\) false\s+Diff: 0: FAIL: \(\[\]bool=\[(true\s?|false\s?){3}]\) != \(\[\]bool=\[(true\s?|false\s?){3}\]\)`
|
diffRegExp := `Difference found in argument 0:\s+--- Expected\s+\+\+\+ Actual\s+@@ -1,4 \+1,4 @@\s+\(\[\]bool\) \(len=3\) {\s+- \(bool\) false,\s+- \(bool\) false,\s+\+ \(bool\) true,\s+\+ \(bool\) true,\s+\(bool\) false\s+`
|
||||||
matchingExp := regexp.MustCompile(unexpectedCallRegex(`TheExampleMethod7([]bool)`, `0: \[\]bool{true, true, false}`, `0: \[\]bool{false, false, false}`, diffRegExp))
|
matchingExp := regexp.MustCompile(unexpectedCallRegex(`TheExampleMethod7([]bool)`, `0: \[\]bool{true, true, false}`, `0: \[\]bool{false, false, false}`, diffRegExp))
|
||||||
assert.Regexp(t, matchingExp, r)
|
assert.Regexp(t, matchingExp, r)
|
||||||
}
|
}
|
||||||
|
@ -2207,7 +1645,7 @@ func Test_isBetterMatchThanReturnsFalseIfRepeatabilityIsLessThanOrEqualToOther(t
|
||||||
|
|
||||||
func unexpectedCallRegex(method, calledArg, expectedArg, diff string) string {
|
func unexpectedCallRegex(method, calledArg, expectedArg, diff string) string {
|
||||||
rMethod := regexp.QuoteMeta(method)
|
rMethod := regexp.QuoteMeta(method)
|
||||||
return fmt.Sprintf(`\s+mock: Unexpected Method Call\s+-*\s+%s\s+%s\s+The closest call I have is:\s+%s\s+%s\s+%s\nat: \[[^\]]+mock\/mock_test.go`,
|
return fmt.Sprintf(`\s+mock: Unexpected Method Call\s+-*\s+%s\s+%s\s+The closest call I have is:\s+%s\s+%s\s+%s`,
|
||||||
rMethod, calledArg, rMethod, expectedArg, diff)
|
rMethod, calledArg, rMethod, expectedArg, diff)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2215,40 +1653,3 @@ func unexpectedCallRegex(method, calledArg, expectedArg, diff string) string {
|
||||||
func ConcurrencyTestMethod(m *Mock) {
|
func ConcurrencyTestMethod(m *Mock) {
|
||||||
m.Called()
|
m.Called()
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestConcurrentArgumentRead(t *testing.T) {
|
|
||||||
methodUnderTest := func(c caller, u user) {
|
|
||||||
go u.Use(c)
|
|
||||||
c.Call()
|
|
||||||
}
|
|
||||||
|
|
||||||
c := &mockCaller{}
|
|
||||||
defer c.AssertExpectations(t)
|
|
||||||
|
|
||||||
u := &mockUser{}
|
|
||||||
defer u.AssertExpectations(t)
|
|
||||||
|
|
||||||
done := make(chan struct{})
|
|
||||||
|
|
||||||
c.On("Call").Return().Once()
|
|
||||||
u.On("Use", c).Return().Once().Run(func(args Arguments) { close(done) })
|
|
||||||
|
|
||||||
methodUnderTest(c, u)
|
|
||||||
<-done // wait until Use is called or assertions will fail
|
|
||||||
}
|
|
||||||
|
|
||||||
type caller interface {
|
|
||||||
Call()
|
|
||||||
}
|
|
||||||
|
|
||||||
type mockCaller struct{ Mock }
|
|
||||||
|
|
||||||
func (m *mockCaller) Call() { m.Called() }
|
|
||||||
|
|
||||||
type user interface {
|
|
||||||
Use(caller)
|
|
||||||
}
|
|
||||||
|
|
||||||
type mockUser struct{ Mock }
|
|
||||||
|
|
||||||
func (m *mockUser) Use(c caller) { m.Called(c) }
|
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
// Package require implements the same assertions as the `assert` package but
|
// Package require implements the same assertions as the `assert` package but
|
||||||
// stops test execution when a test fails.
|
// stops test execution when a test fails.
|
||||||
//
|
//
|
||||||
// # Example Usage
|
// Example Usage
|
||||||
//
|
//
|
||||||
// The following is a complete example using require in a standard test function:
|
// The following is a complete example using require in a standard test function:
|
||||||
//
|
|
||||||
// import (
|
// import (
|
||||||
// "testing"
|
// "testing"
|
||||||
// "github.com/stretchr/testify/require"
|
// "github.com/stretchr/testify/require"
|
||||||
|
@ -19,12 +18,10 @@
|
||||||
//
|
//
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// # Assertions
|
// Assertions
|
||||||
//
|
//
|
||||||
// The `require` package have same global functions as in the `assert` package,
|
// The `require` package have same global functions as in the `assert` package,
|
||||||
// but instead of returning a boolean result they call `t.FailNow()`.
|
// 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,
|
// 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.
|
// allowing custom error messages to be appended to the message the assertion method outputs.
|
||||||
|
|
|
@ -196,18 +196,6 @@ func TestErrorWrapper(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestErrorContainsWrapper(t *testing.T) {
|
|
||||||
require := New(t)
|
|
||||||
require.ErrorContains(errors.New("some error: another error"), "some error")
|
|
||||||
|
|
||||||
mockT := new(MockT)
|
|
||||||
mockRequire := New(mockT)
|
|
||||||
mockRequire.ErrorContains(errors.New("some error: another error"), "different error")
|
|
||||||
if !mockT.Failed {
|
|
||||||
t.Error("Check should fail")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestEqualErrorWrapper(t *testing.T) {
|
func TestEqualErrorWrapper(t *testing.T) {
|
||||||
require := New(t)
|
require := New(t)
|
||||||
require.EqualError(errors.New("some error"), "some error")
|
require.EqualError(errors.New("some error"), "some error")
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,4 +1,4 @@
|
||||||
{{ replace .Comment "assert." "require."}}
|
{{.Comment}}
|
||||||
func {{.DocInfo.Name}}(t TestingT, {{.Params}}) {
|
func {{.DocInfo.Name}}(t TestingT, {{.Params}}) {
|
||||||
if h, ok := t.(tHelper); ok { h.Helper() }
|
if h, ok := t.(tHelper); ok { h.Helper() }
|
||||||
if assert.{{.DocInfo.Name}}(t, {{.ForwardedParams}}) { return }
|
if assert.{{.DocInfo.Name}}(t, {{.ForwardedParams}}) { return }
|
||||||
|
|
|
@ -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 require
|
package require
|
||||||
|
|
||||||
|
@ -153,42 +156,8 @@ func (a *Assertions) EqualErrorf(theError error, errString string, msg string, a
|
||||||
EqualErrorf(a.t, theError, errString, msg, args...)
|
EqualErrorf(a.t, theError, errString, msg, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// EqualExportedValues asserts that the types of two objects are equal and their public
|
// EqualValues asserts that two objects are equal or convertable to the same types
|
||||||
// fields are also equal. This is useful for comparing structs that have private fields
|
// and equal.
|
||||||
// that could potentially differ.
|
|
||||||
//
|
|
||||||
// type S struct {
|
|
||||||
// Exported int
|
|
||||||
// notExported int
|
|
||||||
// }
|
|
||||||
// a.EqualExportedValues(S{1, 2}, S{1, 3}) => true
|
|
||||||
// a.EqualExportedValues(S{1, 2}, S{2, 3}) => false
|
|
||||||
func (a *Assertions) EqualExportedValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) {
|
|
||||||
if h, ok := a.t.(tHelper); ok {
|
|
||||||
h.Helper()
|
|
||||||
}
|
|
||||||
EqualExportedValues(a.t, expected, actual, msgAndArgs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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.
|
|
||||||
//
|
|
||||||
// type S struct {
|
|
||||||
// Exported int
|
|
||||||
// notExported int
|
|
||||||
// }
|
|
||||||
// a.EqualExportedValuesf(S{1, 2}, S{1, 3}, "error message %s", "formatted") => true
|
|
||||||
// a.EqualExportedValuesf(S{1, 2}, S{2, 3}, "error message %s", "formatted") => false
|
|
||||||
func (a *Assertions) EqualExportedValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) {
|
|
||||||
if h, ok := a.t.(tHelper); ok {
|
|
||||||
h.Helper()
|
|
||||||
}
|
|
||||||
EqualExportedValuesf(a.t, expected, actual, msg, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// EqualValues asserts that two objects are equal or convertible to the larger
|
|
||||||
// type and equal.
|
|
||||||
//
|
//
|
||||||
// a.EqualValues(uint32(123), int32(123))
|
// a.EqualValues(uint32(123), int32(123))
|
||||||
func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) {
|
func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) {
|
||||||
|
@ -198,8 +167,8 @@ func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAn
|
||||||
EqualValues(a.t, expected, actual, msgAndArgs...)
|
EqualValues(a.t, expected, actual, msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// EqualValuesf asserts that two objects are equal or convertible to the larger
|
// EqualValuesf asserts that two objects are equal or convertable to the same types
|
||||||
// type and equal.
|
// and equal.
|
||||||
//
|
//
|
||||||
// a.EqualValuesf(uint32(123), int32(123), "error message %s", "formatted")
|
// a.EqualValuesf(uint32(123), int32(123), "error message %s", "formatted")
|
||||||
func (a *Assertions) EqualValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) {
|
func (a *Assertions) EqualValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) {
|
||||||
|
@ -254,30 +223,6 @@ func (a *Assertions) ErrorAsf(err error, target interface{}, msg string, args ..
|
||||||
ErrorAsf(a.t, err, target, msg, args...)
|
ErrorAsf(a.t, err, target, msg, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ErrorContains asserts that a function returned an error (i.e. not `nil`)
|
|
||||||
// and that the error contains the specified substring.
|
|
||||||
//
|
|
||||||
// actualObj, err := SomeFunction()
|
|
||||||
// a.ErrorContains(err, expectedErrorSubString)
|
|
||||||
func (a *Assertions) ErrorContains(theError error, contains string, msgAndArgs ...interface{}) {
|
|
||||||
if h, ok := a.t.(tHelper); ok {
|
|
||||||
h.Helper()
|
|
||||||
}
|
|
||||||
ErrorContains(a.t, theError, contains, msgAndArgs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrorContainsf asserts that a function returned an error (i.e. not `nil`)
|
|
||||||
// and that the error contains the specified substring.
|
|
||||||
//
|
|
||||||
// actualObj, err := SomeFunction()
|
|
||||||
// a.ErrorContainsf(err, expectedErrorSubString, "error message %s", "formatted")
|
|
||||||
func (a *Assertions) ErrorContainsf(theError error, contains string, msg string, args ...interface{}) {
|
|
||||||
if h, ok := a.t.(tHelper); ok {
|
|
||||||
h.Helper()
|
|
||||||
}
|
|
||||||
ErrorContainsf(a.t, theError, contains, msg, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrorIs asserts that at least one of the errors in err's chain matches target.
|
// ErrorIs asserts that at least one of the errors in err's chain matches target.
|
||||||
// This is a wrapper for errors.Is.
|
// This is a wrapper for errors.Is.
|
||||||
func (a *Assertions) ErrorIs(err error, target error, msgAndArgs ...interface{}) {
|
func (a *Assertions) ErrorIs(err error, target error, msgAndArgs ...interface{}) {
|
||||||
|
@ -320,56 +265,6 @@ func (a *Assertions) Eventually(condition func() bool, waitFor time.Duration, ti
|
||||||
Eventually(a.t, condition, waitFor, tick, msgAndArgs...)
|
Eventually(a.t, condition, waitFor, tick, msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// EventuallyWithT 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
|
|
||||||
// }()
|
|
||||||
// a.EventuallyWithT(func(c *assert.CollectT) {
|
|
||||||
// // 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 (a *Assertions) EventuallyWithT(condition func(collect *assert.CollectT), waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) {
|
|
||||||
if h, ok := a.t.(tHelper); ok {
|
|
||||||
h.Helper()
|
|
||||||
}
|
|
||||||
EventuallyWithT(a.t, condition, waitFor, tick, msgAndArgs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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
|
|
||||||
// }()
|
|
||||||
// a.EventuallyWithTf(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 (a *Assertions) EventuallyWithTf(condition func(collect *assert.CollectT), waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) {
|
|
||||||
if h, ok := a.t.(tHelper); ok {
|
|
||||||
h.Helper()
|
|
||||||
}
|
|
||||||
EventuallyWithTf(a.t, condition, waitFor, tick, msg, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Eventuallyf asserts that given condition will be met in waitFor time,
|
// Eventuallyf asserts that given condition will be met in waitFor time,
|
||||||
// periodically checking target function each tick.
|
// periodically checking target function each tick.
|
||||||
//
|
//
|
||||||
|
@ -1129,40 +1024,6 @@ func (a *Assertions) NotContainsf(s interface{}, contains interface{}, msg strin
|
||||||
NotContainsf(a.t, s, contains, msg, args...)
|
NotContainsf(a.t, s, contains, msg, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NotElementsMatch 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.
|
|
||||||
//
|
|
||||||
// a.NotElementsMatch([1, 1, 2, 3], [1, 1, 2, 3]) -> false
|
|
||||||
//
|
|
||||||
// a.NotElementsMatch([1, 1, 2, 3], [1, 2, 3]) -> true
|
|
||||||
//
|
|
||||||
// a.NotElementsMatch([1, 2, 3], [1, 2, 4]) -> true
|
|
||||||
func (a *Assertions) NotElementsMatch(listA interface{}, listB interface{}, msgAndArgs ...interface{}) {
|
|
||||||
if h, ok := a.t.(tHelper); ok {
|
|
||||||
h.Helper()
|
|
||||||
}
|
|
||||||
NotElementsMatch(a.t, listA, listB, msgAndArgs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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.
|
|
||||||
//
|
|
||||||
// a.NotElementsMatchf([1, 1, 2, 3], [1, 1, 2, 3], "error message %s", "formatted") -> false
|
|
||||||
//
|
|
||||||
// a.NotElementsMatchf([1, 1, 2, 3], [1, 2, 3], "error message %s", "formatted") -> true
|
|
||||||
//
|
|
||||||
// a.NotElementsMatchf([1, 2, 3], [1, 2, 4], "error message %s", "formatted") -> true
|
|
||||||
func (a *Assertions) NotElementsMatchf(listA interface{}, listB interface{}, msg string, args ...interface{}) {
|
|
||||||
if h, ok := a.t.(tHelper); ok {
|
|
||||||
h.Helper()
|
|
||||||
}
|
|
||||||
NotElementsMatchf(a.t, listA, listB, msg, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either
|
// NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either
|
||||||
// a slice or a channel with len == 0.
|
// a slice or a channel with len == 0.
|
||||||
//
|
//
|
||||||
|
@ -1235,25 +1096,7 @@ func (a *Assertions) NotEqualf(expected interface{}, actual interface{}, msg str
|
||||||
NotEqualf(a.t, expected, actual, msg, args...)
|
NotEqualf(a.t, expected, actual, msg, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NotErrorAs asserts that none of the errors in err's chain matches target,
|
// NotErrorIs asserts that at none of the errors in err's chain matches target.
|
||||||
// but if so, sets target to that error value.
|
|
||||||
func (a *Assertions) NotErrorAs(err error, target interface{}, msgAndArgs ...interface{}) {
|
|
||||||
if h, ok := a.t.(tHelper); ok {
|
|
||||||
h.Helper()
|
|
||||||
}
|
|
||||||
NotErrorAs(a.t, err, target, msgAndArgs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NotErrorAsf asserts that none of the errors in err's chain matches target,
|
|
||||||
// but if so, sets target to that error value.
|
|
||||||
func (a *Assertions) NotErrorAsf(err error, target interface{}, msg string, args ...interface{}) {
|
|
||||||
if h, ok := a.t.(tHelper); ok {
|
|
||||||
h.Helper()
|
|
||||||
}
|
|
||||||
NotErrorAsf(a.t, err, target, msg, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NotErrorIs asserts that none of the errors in err's chain matches target.
|
|
||||||
// This is a wrapper for errors.Is.
|
// This is a wrapper for errors.Is.
|
||||||
func (a *Assertions) NotErrorIs(err error, target error, msgAndArgs ...interface{}) {
|
func (a *Assertions) NotErrorIs(err error, target error, msgAndArgs ...interface{}) {
|
||||||
if h, ok := a.t.(tHelper); ok {
|
if h, ok := a.t.(tHelper); ok {
|
||||||
|
@ -1262,7 +1105,7 @@ func (a *Assertions) NotErrorIs(err error, target error, msgAndArgs ...interface
|
||||||
NotErrorIs(a.t, err, target, msgAndArgs...)
|
NotErrorIs(a.t, err, target, msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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.
|
// This is a wrapper for errors.Is.
|
||||||
func (a *Assertions) NotErrorIsf(err error, target error, msg string, args ...interface{}) {
|
func (a *Assertions) NotErrorIsf(err error, target error, msg string, args ...interface{}) {
|
||||||
if h, ok := a.t.(tHelper); ok {
|
if h, ok := a.t.(tHelper); ok {
|
||||||
|
@ -1271,26 +1114,6 @@ func (a *Assertions) NotErrorIsf(err error, target error, msg string, args ...in
|
||||||
NotErrorIsf(a.t, err, target, msg, args...)
|
NotErrorIsf(a.t, err, target, msg, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NotImplements asserts that an object does not implement the specified interface.
|
|
||||||
//
|
|
||||||
// a.NotImplements((*MyInterface)(nil), new(MyObject))
|
|
||||||
func (a *Assertions) NotImplements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) {
|
|
||||||
if h, ok := a.t.(tHelper); ok {
|
|
||||||
h.Helper()
|
|
||||||
}
|
|
||||||
NotImplements(a.t, interfaceObject, object, msgAndArgs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NotImplementsf asserts that an object does not implement the specified interface.
|
|
||||||
//
|
|
||||||
// a.NotImplementsf((*MyInterface)(nil), new(MyObject), "error message %s", "formatted")
|
|
||||||
func (a *Assertions) NotImplementsf(interfaceObject interface{}, object interface{}, msg string, args ...interface{}) {
|
|
||||||
if h, ok := a.t.(tHelper); ok {
|
|
||||||
h.Helper()
|
|
||||||
}
|
|
||||||
NotImplementsf(a.t, interfaceObject, object, msg, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NotNil asserts that the specified object is not nil.
|
// NotNil asserts that the specified object is not nil.
|
||||||
//
|
//
|
||||||
// a.NotNil(err)
|
// a.NotNil(err)
|
||||||
|
@ -1379,12 +1202,10 @@ func (a *Assertions) NotSamef(expected interface{}, actual interface{}, msg stri
|
||||||
NotSamef(a.t, expected, actual, msg, args...)
|
NotSamef(a.t, expected, actual, msg, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NotSubset asserts that the specified list(array, slice...) or map does NOT
|
// NotSubset asserts that the specified list(array, slice...) contains not all
|
||||||
// contain all elements given in the specified subset list(array, slice...) or
|
// elements given in the specified subset(array, slice...).
|
||||||
// map.
|
|
||||||
//
|
//
|
||||||
// a.NotSubset([1, 3, 4], [1, 2])
|
// a.NotSubset([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]")
|
||||||
// a.NotSubset({"x": 1, "y": 2}, {"z": 3})
|
|
||||||
func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs ...interface{}) {
|
func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs ...interface{}) {
|
||||||
if h, ok := a.t.(tHelper); ok {
|
if h, ok := a.t.(tHelper); ok {
|
||||||
h.Helper()
|
h.Helper()
|
||||||
|
@ -1392,12 +1213,10 @@ func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs
|
||||||
NotSubset(a.t, list, subset, msgAndArgs...)
|
NotSubset(a.t, list, subset, msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NotSubsetf asserts that the specified list(array, slice...) or map does NOT
|
// NotSubsetf asserts that the specified list(array, slice...) contains not all
|
||||||
// contain all elements given in the specified subset list(array, slice...) or
|
// elements given in the specified subset(array, slice...).
|
||||||
// map.
|
|
||||||
//
|
//
|
||||||
// a.NotSubsetf([1, 3, 4], [1, 2], "error message %s", "formatted")
|
// a.NotSubsetf([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted")
|
||||||
// a.NotSubsetf({"x": 1, "y": 2}, {"z": 3}, "error message %s", "formatted")
|
|
||||||
func (a *Assertions) NotSubsetf(list interface{}, subset interface{}, msg string, args ...interface{}) {
|
func (a *Assertions) NotSubsetf(list interface{}, subset interface{}, msg string, args ...interface{}) {
|
||||||
if h, ok := a.t.(tHelper); ok {
|
if h, ok := a.t.(tHelper); ok {
|
||||||
h.Helper()
|
h.Helper()
|
||||||
|
@ -1557,11 +1376,10 @@ func (a *Assertions) Samef(expected interface{}, actual interface{}, msg string,
|
||||||
Samef(a.t, expected, actual, msg, args...)
|
Samef(a.t, expected, actual, msg, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Subset asserts that the specified list(array, slice...) or map contains all
|
// Subset asserts that the specified list(array, slice...) contains all
|
||||||
// elements given in the specified subset list(array, slice...) or map.
|
// elements given in the specified subset(array, slice...).
|
||||||
//
|
//
|
||||||
// a.Subset([1, 2, 3], [1, 2])
|
// a.Subset([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]")
|
||||||
// a.Subset({"x": 1, "y": 2}, {"x": 1})
|
|
||||||
func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ...interface{}) {
|
func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ...interface{}) {
|
||||||
if h, ok := a.t.(tHelper); ok {
|
if h, ok := a.t.(tHelper); ok {
|
||||||
h.Helper()
|
h.Helper()
|
||||||
|
@ -1569,11 +1387,10 @@ func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ...
|
||||||
Subset(a.t, list, subset, msgAndArgs...)
|
Subset(a.t, list, subset, msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Subsetf asserts that the specified list(array, slice...) or map contains all
|
// Subsetf asserts that the specified list(array, slice...) contains all
|
||||||
// elements given in the specified subset list(array, slice...) or map.
|
// elements given in the specified subset(array, slice...).
|
||||||
//
|
//
|
||||||
// a.Subsetf([1, 2, 3], [1, 2], "error message %s", "formatted")
|
// a.Subsetf([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted")
|
||||||
// a.Subsetf({"x": 1, "y": 2}, {"x": 1}, "error message %s", "formatted")
|
|
||||||
func (a *Assertions) Subsetf(list interface{}, subset interface{}, msg string, args ...interface{}) {
|
func (a *Assertions) Subsetf(list interface{}, subset interface{}, msg string, args ...interface{}) {
|
||||||
if h, ok := a.t.(tHelper); ok {
|
if h, ok := a.t.(tHelper); ok {
|
||||||
h.Helper()
|
h.Helper()
|
||||||
|
@ -1621,26 +1438,6 @@ func (a *Assertions) WithinDurationf(expected time.Time, actual time.Time, delta
|
||||||
WithinDurationf(a.t, expected, actual, delta, msg, args...)
|
WithinDurationf(a.t, expected, actual, delta, msg, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithinRange asserts that a time is within a time range (inclusive).
|
|
||||||
//
|
|
||||||
// a.WithinRange(time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second))
|
|
||||||
func (a *Assertions) WithinRange(actual time.Time, start time.Time, end time.Time, msgAndArgs ...interface{}) {
|
|
||||||
if h, ok := a.t.(tHelper); ok {
|
|
||||||
h.Helper()
|
|
||||||
}
|
|
||||||
WithinRange(a.t, actual, start, end, msgAndArgs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithinRangef asserts that a time is within a time range (inclusive).
|
|
||||||
//
|
|
||||||
// a.WithinRangef(time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second), "error message %s", "formatted")
|
|
||||||
func (a *Assertions) WithinRangef(actual time.Time, start time.Time, end time.Time, msg string, args ...interface{}) {
|
|
||||||
if h, ok := a.t.(tHelper); ok {
|
|
||||||
h.Helper()
|
|
||||||
}
|
|
||||||
WithinRangef(a.t, actual, start, end, msg, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// YAMLEq asserts that two YAML strings are equivalent.
|
// YAMLEq asserts that two YAML strings are equivalent.
|
||||||
func (a *Assertions) YAMLEq(expected string, actual string, msgAndArgs ...interface{}) {
|
func (a *Assertions) YAMLEq(expected string, actual string, msgAndArgs ...interface{}) {
|
||||||
if h, ok := a.t.(tHelper); ok {
|
if h, ok := a.t.(tHelper); ok {
|
||||||
|
|
|
@ -6,7 +6,7 @@ type TestingT interface {
|
||||||
FailNow()
|
FailNow()
|
||||||
}
|
}
|
||||||
|
|
||||||
type tHelper = interface {
|
type tHelper interface {
|
||||||
Helper()
|
Helper()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,8 +5,6 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// AssertionTesterInterface defines an interface to be used for testing assertion methods
|
// AssertionTesterInterface defines an interface to be used for testing assertion methods
|
||||||
|
@ -210,17 +208,6 @@ func TestError(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestErrorContains(t *testing.T) {
|
|
||||||
|
|
||||||
ErrorContains(t, errors.New("some error: another error"), "some error")
|
|
||||||
|
|
||||||
mockT := new(MockT)
|
|
||||||
ErrorContains(mockT, errors.New("some error"), "different error")
|
|
||||||
if !mockT.Failed {
|
|
||||||
t.Error("Check should fail")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestEqualError(t *testing.T) {
|
func TestEqualError(t *testing.T) {
|
||||||
|
|
||||||
EqualError(t, errors.New("some error"), "some error")
|
EqualError(t, errors.New("some error"), "some error")
|
||||||
|
@ -683,30 +670,3 @@ func TestErrorAssertionFunc(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestEventuallyWithTFalse(t *testing.T) {
|
|
||||||
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) {
|
|
||||||
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")
|
|
||||||
}
|
|
||||||
|
|
|
@ -5,8 +5,6 @@
|
||||||
// or individual tests (depending on which interface(s) you
|
// or individual tests (depending on which interface(s) you
|
||||||
// implement).
|
// implement).
|
||||||
//
|
//
|
||||||
// The suite package does not support parallel tests. See [issue 934].
|
|
||||||
//
|
|
||||||
// A testing suite is usually built by first extending the built-in
|
// A testing suite is usually built by first extending the built-in
|
||||||
// suite functionality from suite.Suite in testify. Alternatively,
|
// suite functionality from suite.Suite in testify. Alternatively,
|
||||||
// you could reproduce that logic on your own if you wanted (you
|
// you could reproduce that logic on your own if you wanted (you
|
||||||
|
@ -31,7 +29,6 @@
|
||||||
// Suite object has assertion methods.
|
// Suite object has assertion methods.
|
||||||
//
|
//
|
||||||
// A crude example:
|
// A crude example:
|
||||||
//
|
|
||||||
// // Basic imports
|
// // Basic imports
|
||||||
// import (
|
// import (
|
||||||
// "testing"
|
// "testing"
|
||||||
|
@ -65,6 +62,4 @@
|
||||||
// func TestExampleTestSuite(t *testing.T) {
|
// func TestExampleTestSuite(t *testing.T) {
|
||||||
// suite.Run(t, new(ExampleTestSuite))
|
// suite.Run(t, new(ExampleTestSuite))
|
||||||
// }
|
// }
|
||||||
//
|
|
||||||
// [issue 934]: https://github.com/stretchr/testify/issues/934
|
|
||||||
package suite
|
package suite
|
||||||
|
|
|
@ -7,7 +7,6 @@ import "testing"
|
||||||
type TestingSuite interface {
|
type TestingSuite interface {
|
||||||
T() *testing.T
|
T() *testing.T
|
||||||
SetT(*testing.T)
|
SetT(*testing.T)
|
||||||
SetS(suite TestingSuite)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetupAllSuite has a SetupSuite method, which will run before the
|
// SetupAllSuite has a SetupSuite method, which will run before the
|
||||||
|
@ -52,15 +51,3 @@ type AfterTest interface {
|
||||||
type WithStats interface {
|
type WithStats interface {
|
||||||
HandleStats(suiteName string, stats *SuiteInformation)
|
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()
|
|
||||||
}
|
|
||||||
|
|
|
@ -7,7 +7,6 @@ import (
|
||||||
"reflect"
|
"reflect"
|
||||||
"regexp"
|
"regexp"
|
||||||
"runtime/debug"
|
"runtime/debug"
|
||||||
"sync"
|
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -22,43 +21,26 @@ var matchMethod = flag.String("testify.m", "", "regular expression to select tes
|
||||||
// retrieving the current *testing.T context.
|
// retrieving the current *testing.T context.
|
||||||
type Suite struct {
|
type Suite struct {
|
||||||
*assert.Assertions
|
*assert.Assertions
|
||||||
|
|
||||||
mu sync.RWMutex
|
|
||||||
require *require.Assertions
|
require *require.Assertions
|
||||||
t *testing.T
|
t *testing.T
|
||||||
|
|
||||||
// Parent suite to have access to the implemented methods of parent struct
|
|
||||||
s TestingSuite
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// T retrieves the current *testing.T context.
|
// T retrieves the current *testing.T context.
|
||||||
func (suite *Suite) T() *testing.T {
|
func (suite *Suite) T() *testing.T {
|
||||||
suite.mu.RLock()
|
|
||||||
defer suite.mu.RUnlock()
|
|
||||||
return suite.t
|
return suite.t
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetT sets the current *testing.T context.
|
// SetT sets the current *testing.T context.
|
||||||
func (suite *Suite) SetT(t *testing.T) {
|
func (suite *Suite) SetT(t *testing.T) {
|
||||||
suite.mu.Lock()
|
|
||||||
defer suite.mu.Unlock()
|
|
||||||
suite.t = t
|
suite.t = t
|
||||||
suite.Assertions = assert.New(t)
|
suite.Assertions = assert.New(t)
|
||||||
suite.require = require.New(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.
|
// Require returns a require context for suite.
|
||||||
func (suite *Suite) Require() *require.Assertions {
|
func (suite *Suite) Require() *require.Assertions {
|
||||||
suite.mu.Lock()
|
|
||||||
defer suite.mu.Unlock()
|
|
||||||
if suite.require == nil {
|
if suite.require == nil {
|
||||||
panic("'Require' must not be called before 'Run' or 'SetT'")
|
suite.require = require.New(suite.T())
|
||||||
}
|
}
|
||||||
return suite.require
|
return suite.require
|
||||||
}
|
}
|
||||||
|
@ -69,22 +51,14 @@ func (suite *Suite) Require() *require.Assertions {
|
||||||
// assert.Assertions with require.Assertions), this method is provided so you
|
// assert.Assertions with require.Assertions), this method is provided so you
|
||||||
// can call `suite.Assert().NoError()`.
|
// can call `suite.Assert().NoError()`.
|
||||||
func (suite *Suite) Assert() *assert.Assertions {
|
func (suite *Suite) Assert() *assert.Assertions {
|
||||||
suite.mu.Lock()
|
|
||||||
defer suite.mu.Unlock()
|
|
||||||
if suite.Assertions == nil {
|
if suite.Assertions == nil {
|
||||||
panic("'Assert' must not be called before 'Run' or 'SetT'")
|
suite.Assertions = assert.New(suite.T())
|
||||||
}
|
}
|
||||||
return suite.Assertions
|
return suite.Assertions
|
||||||
}
|
}
|
||||||
|
|
||||||
func recoverAndFailOnPanic(t *testing.T) {
|
func failOnPanic(t *testing.T) {
|
||||||
t.Helper()
|
|
||||||
r := recover()
|
r := recover()
|
||||||
failOnPanic(t, r)
|
|
||||||
}
|
|
||||||
|
|
||||||
func failOnPanic(t *testing.T, r interface{}) {
|
|
||||||
t.Helper()
|
|
||||||
if r != nil {
|
if r != nil {
|
||||||
t.Errorf("test panicked: %v\n%s", r, debug.Stack())
|
t.Errorf("test panicked: %v\n%s", r, debug.Stack())
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
|
@ -97,21 +71,9 @@ func failOnPanic(t *testing.T, r interface{}) {
|
||||||
// Provides compatibility with go test pkg -run TestSuite/TestName/SubTestName.
|
// Provides compatibility with go test pkg -run TestSuite/TestName/SubTestName.
|
||||||
func (suite *Suite) Run(name string, subtest func()) bool {
|
func (suite *Suite) Run(name string, subtest func()) bool {
|
||||||
oldT := suite.T()
|
oldT := suite.T()
|
||||||
|
defer suite.SetT(oldT)
|
||||||
return oldT.Run(name, func(t *testing.T) {
|
return oldT.Run(name, func(t *testing.T) {
|
||||||
suite.SetT(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()
|
subtest()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -119,10 +81,9 @@ func (suite *Suite) Run(name string, subtest func()) bool {
|
||||||
// Run takes a testing suite and runs all of the tests attached
|
// Run takes a testing suite and runs all of the tests attached
|
||||||
// to it.
|
// to it.
|
||||||
func Run(t *testing.T, suite TestingSuite) {
|
func Run(t *testing.T, suite TestingSuite) {
|
||||||
defer recoverAndFailOnPanic(t)
|
defer failOnPanic(t)
|
||||||
|
|
||||||
suite.SetT(t)
|
suite.SetT(t)
|
||||||
suite.SetS(suite)
|
|
||||||
|
|
||||||
var suiteSetupDone bool
|
var suiteSetupDone bool
|
||||||
|
|
||||||
|
@ -165,14 +126,10 @@ func Run(t *testing.T, suite TestingSuite) {
|
||||||
F: func(t *testing.T) {
|
F: func(t *testing.T) {
|
||||||
parentT := suite.T()
|
parentT := suite.T()
|
||||||
suite.SetT(t)
|
suite.SetT(t)
|
||||||
defer recoverAndFailOnPanic(t)
|
defer failOnPanic(t)
|
||||||
defer func() {
|
defer func() {
|
||||||
t.Helper()
|
|
||||||
|
|
||||||
r := recover()
|
|
||||||
|
|
||||||
if stats != nil {
|
if stats != nil {
|
||||||
passed := !t.Failed() && r == nil
|
passed := !t.Failed()
|
||||||
stats.end(method.Name, passed)
|
stats.end(method.Name, passed)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,7 +142,6 @@ func Run(t *testing.T, suite TestingSuite) {
|
||||||
}
|
}
|
||||||
|
|
||||||
suite.SetT(parentT)
|
suite.SetT(parentT)
|
||||||
failOnPanic(t, r)
|
|
||||||
}()
|
}()
|
||||||
|
|
||||||
if setupTestSuite, ok := suite.(SetupTestSuite); ok {
|
if setupTestSuite, ok := suite.(SetupTestSuite); ok {
|
||||||
|
|
|
@ -4,7 +4,7 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"flag"
|
"flag"
|
||||||
"io"
|
"io/ioutil"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
@ -21,20 +21,20 @@ import (
|
||||||
type SuiteRequireTwice struct{ Suite }
|
type SuiteRequireTwice struct{ Suite }
|
||||||
|
|
||||||
// TestSuiteRequireTwice checks for regressions of issue #149 where
|
// 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.
|
// A regression would result on these tests panicking rather than failing.
|
||||||
func TestSuiteRequireTwice(t *testing.T) {
|
func TestSuiteRequireTwice(t *testing.T) {
|
||||||
ok := testing.RunTests(
|
ok := testing.RunTests(
|
||||||
allTestsFilter,
|
allTestsFilter,
|
||||||
[]testing.InternalTest{{
|
[]testing.InternalTest{{
|
||||||
Name: t.Name() + "/SuiteRequireTwice",
|
Name: "TestSuiteRequireTwice",
|
||||||
F: func(t *testing.T) {
|
F: func(t *testing.T) {
|
||||||
suite := new(SuiteRequireTwice)
|
suite := new(SuiteRequireTwice)
|
||||||
Run(t, suite)
|
Run(t, suite)
|
||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
)
|
)
|
||||||
assert.False(t, ok)
|
assert.Equal(t, false, ok)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SuiteRequireTwice) TestRequireOne() {
|
func (s *SuiteRequireTwice) TestRequireOne() {
|
||||||
|
@ -104,31 +104,31 @@ func TestSuiteRecoverPanic(t *testing.T) {
|
||||||
ok := true
|
ok := true
|
||||||
panickingTests := []testing.InternalTest{
|
panickingTests := []testing.InternalTest{
|
||||||
{
|
{
|
||||||
Name: t.Name() + "/InSetupSuite",
|
Name: "TestPanicInSetupSuite",
|
||||||
F: func(t *testing.T) { Run(t, &panickingSuite{panicInSetupSuite: true}) },
|
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}) },
|
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}) },
|
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}) },
|
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}) },
|
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}) },
|
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}) },
|
F: func(t *testing.T) { Run(t, &panickingSuite{panicInTearDownSuite: true}) },
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -159,11 +159,6 @@ type SuiteTester struct {
|
||||||
TestTwoRunCount int
|
TestTwoRunCount int
|
||||||
TestSubtestRunCount int
|
TestSubtestRunCount int
|
||||||
NonTestMethodRunCount int
|
NonTestMethodRunCount int
|
||||||
SetupSubTestRunCount int
|
|
||||||
TearDownSubTestRunCount int
|
|
||||||
|
|
||||||
SetupSubTestNames []string
|
|
||||||
TearDownSubTestNames []string
|
|
||||||
|
|
||||||
SuiteNameBefore []string
|
SuiteNameBefore []string
|
||||||
TestNameBefore []string
|
TestNameBefore []string
|
||||||
|
@ -260,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 {
|
type SuiteSkipTester struct {
|
||||||
// Include our basic suite logic.
|
// Include our basic suite logic.
|
||||||
Suite
|
Suite
|
||||||
|
@ -306,13 +291,13 @@ func TestRunSuite(t *testing.T) {
|
||||||
|
|
||||||
// The suite was only run once, so the SetupSuite and TearDownSuite
|
// The suite was only run once, so the SetupSuite and TearDownSuite
|
||||||
// methods should have each been run only once.
|
// methods should have each been run only once.
|
||||||
assert.Equal(t, 1, suiteTester.SetupSuiteRunCount)
|
assert.Equal(t, suiteTester.SetupSuiteRunCount, 1)
|
||||||
assert.Equal(t, 1, suiteTester.TearDownSuiteRunCount)
|
assert.Equal(t, suiteTester.TearDownSuiteRunCount, 1)
|
||||||
|
|
||||||
assert.Len(t, suiteTester.SuiteNameAfter, 4)
|
assert.Equal(t, len(suiteTester.SuiteNameAfter), 4)
|
||||||
assert.Len(t, suiteTester.SuiteNameBefore, 4)
|
assert.Equal(t, len(suiteTester.SuiteNameBefore), 4)
|
||||||
assert.Len(t, suiteTester.TestNameAfter, 4)
|
assert.Equal(t, len(suiteTester.TestNameAfter), 4)
|
||||||
assert.Len(t, suiteTester.TestNameBefore, 4)
|
assert.Equal(t, len(suiteTester.TestNameBefore), 4)
|
||||||
|
|
||||||
assert.Contains(t, suiteTester.TestNameAfter, "TestOne")
|
assert.Contains(t, suiteTester.TestNameAfter, "TestOne")
|
||||||
assert.Contains(t, suiteTester.TestNameAfter, "TestTwo")
|
assert.Contains(t, suiteTester.TestNameAfter, "TestTwo")
|
||||||
|
@ -324,12 +309,6 @@ func TestRunSuite(t *testing.T) {
|
||||||
assert.Contains(t, suiteTester.TestNameBefore, "TestSkip")
|
assert.Contains(t, suiteTester.TestNameBefore, "TestSkip")
|
||||||
assert.Contains(t, suiteTester.TestNameBefore, "TestSubtest")
|
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 {
|
for _, suiteName := range suiteTester.SuiteNameAfter {
|
||||||
assert.Equal(t, "SuiteTester", suiteName)
|
assert.Equal(t, "SuiteTester", suiteName)
|
||||||
}
|
}
|
||||||
|
@ -349,20 +328,17 @@ func TestRunSuite(t *testing.T) {
|
||||||
// There are four test methods (TestOne, TestTwo, TestSkip, and TestSubtest), so
|
// There are four test methods (TestOne, TestTwo, TestSkip, and TestSubtest), so
|
||||||
// the SetupTest and TearDownTest methods (which should be run once for
|
// the SetupTest and TearDownTest methods (which should be run once for
|
||||||
// each test) should have been run four times.
|
// each test) should have been run four times.
|
||||||
assert.Equal(t, 4, suiteTester.SetupTestRunCount)
|
assert.Equal(t, suiteTester.SetupTestRunCount, 4)
|
||||||
assert.Equal(t, 4, suiteTester.TearDownTestRunCount)
|
assert.Equal(t, suiteTester.TearDownTestRunCount, 4)
|
||||||
|
|
||||||
// Each test should have been run once.
|
// Each test should have been run once.
|
||||||
assert.Equal(t, 1, suiteTester.TestOneRunCount)
|
assert.Equal(t, suiteTester.TestOneRunCount, 1)
|
||||||
assert.Equal(t, 1, suiteTester.TestTwoRunCount)
|
assert.Equal(t, suiteTester.TestTwoRunCount, 1)
|
||||||
assert.Equal(t, 1, suiteTester.TestSubtestRunCount)
|
assert.Equal(t, suiteTester.TestSubtestRunCount, 1)
|
||||||
|
|
||||||
assert.Equal(t, 2, suiteTester.TearDownSubTestRunCount)
|
|
||||||
assert.Equal(t, 2, suiteTester.SetupSubTestRunCount)
|
|
||||||
|
|
||||||
// Methods that don't match the test method identifier shouldn't
|
// Methods that don't match the test method identifier shouldn't
|
||||||
// have been run at all.
|
// have been run at all.
|
||||||
assert.Equal(t, 0, suiteTester.NonTestMethodRunCount)
|
assert.Equal(t, suiteTester.NonTestMethodRunCount, 0)
|
||||||
|
|
||||||
suiteSkipTester := new(SuiteSkipTester)
|
suiteSkipTester := new(SuiteSkipTester)
|
||||||
Run(t, suiteSkipTester)
|
Run(t, suiteSkipTester)
|
||||||
|
@ -370,8 +346,8 @@ func TestRunSuite(t *testing.T) {
|
||||||
// The suite was only run once, so the SetupSuite and TearDownSuite
|
// The suite was only run once, so the SetupSuite and TearDownSuite
|
||||||
// methods should have each been run only once, even though SetupSuite
|
// methods should have each been run only once, even though SetupSuite
|
||||||
// called Skip()
|
// called Skip()
|
||||||
assert.Equal(t, 1, suiteSkipTester.SetupSuiteRunCount)
|
assert.Equal(t, suiteSkipTester.SetupSuiteRunCount, 1)
|
||||||
assert.Equal(t, 1, suiteSkipTester.TearDownSuiteRunCount)
|
assert.Equal(t, suiteSkipTester.TearDownSuiteRunCount, 1)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -440,7 +416,7 @@ func (sc *StdoutCapture) StopCapture() (string, error) {
|
||||||
}
|
}
|
||||||
os.Stdout.Close()
|
os.Stdout.Close()
|
||||||
os.Stdout = sc.oldStdout
|
os.Stdout = sc.oldStdout
|
||||||
bytes, err := io.ReadAll(sc.readPipe)
|
bytes, err := ioutil.ReadAll(sc.readPipe)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
@ -451,7 +427,7 @@ func TestSuiteLogging(t *testing.T) {
|
||||||
suiteLoggingTester := new(SuiteLoggingTester)
|
suiteLoggingTester := new(SuiteLoggingTester)
|
||||||
capture := StdoutCapture{}
|
capture := StdoutCapture{}
|
||||||
internalTest := testing.InternalTest{
|
internalTest := testing.InternalTest{
|
||||||
Name: t.Name() + "/SuiteLoggingTester",
|
Name: "SomeTest",
|
||||||
F: func(subT *testing.T) {
|
F: func(subT *testing.T) {
|
||||||
Run(subT, suiteLoggingTester)
|
Run(subT, suiteLoggingTester)
|
||||||
},
|
},
|
||||||
|
@ -492,7 +468,7 @@ func (s *CallOrderSuite) SetupSuite() {
|
||||||
|
|
||||||
func (s *CallOrderSuite) TearDownSuite() {
|
func (s *CallOrderSuite) TearDownSuite() {
|
||||||
s.call("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() {
|
func (s *CallOrderSuite) SetupTest() {
|
||||||
s.call("SetupTest")
|
s.call("SetupTest")
|
||||||
|
@ -502,32 +478,12 @@ func (s *CallOrderSuite) TearDownTest() {
|
||||||
s.call("TearDownTest")
|
s.call("TearDownTest")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *CallOrderSuite) SetupSubTest() {
|
|
||||||
s.call("SetupSubTest")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *CallOrderSuite) TearDownSubTest() {
|
|
||||||
s.call("TearDownSubTest")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *CallOrderSuite) Test_A() {
|
func (s *CallOrderSuite) Test_A() {
|
||||||
s.call("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() {
|
func (s *CallOrderSuite) Test_B() {
|
||||||
s.call("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 {
|
type suiteWithStats struct {
|
||||||
|
@ -545,37 +501,19 @@ func (s *suiteWithStats) TestSomething() {
|
||||||
s.Equal(1, 1)
|
s.Equal(1, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *suiteWithStats) TestPanic() {
|
|
||||||
panic("oops")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSuiteWithStats(t *testing.T) {
|
func TestSuiteWithStats(t *testing.T) {
|
||||||
suiteWithStats := new(suiteWithStats)
|
suiteWithStats := new(suiteWithStats)
|
||||||
|
|
||||||
suiteSuccess := testing.RunTests(allTestsFilter, []testing.InternalTest{
|
|
||||||
{
|
|
||||||
Name: t.Name() + "/suiteWithStats",
|
|
||||||
F: func(t *testing.T) {
|
|
||||||
Run(t, suiteWithStats)
|
Run(t, suiteWithStats)
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
require.False(t, suiteSuccess, "suiteWithStats should report test failure because of panic in TestPanic")
|
|
||||||
|
|
||||||
assert.True(t, suiteWithStats.wasCalled)
|
assert.True(t, suiteWithStats.wasCalled)
|
||||||
assert.NotZero(t, suiteWithStats.stats.Start)
|
assert.NotZero(t, suiteWithStats.stats.Start)
|
||||||
assert.NotZero(t, suiteWithStats.stats.End)
|
assert.NotZero(t, suiteWithStats.stats.End)
|
||||||
assert.False(t, suiteWithStats.stats.Passed())
|
assert.True(t, suiteWithStats.stats.Passed())
|
||||||
|
|
||||||
testStats := suiteWithStats.stats.TestStats
|
testStats := suiteWithStats.stats.TestStats["TestSomething"]
|
||||||
|
assert.NotZero(t, testStats.Start)
|
||||||
assert.NotZero(t, testStats["TestSomething"].Start)
|
assert.NotZero(t, testStats.End)
|
||||||
assert.NotZero(t, testStats["TestSomething"].End)
|
assert.True(t, testStats.Passed)
|
||||||
assert.True(t, testStats["TestSomething"].Passed)
|
|
||||||
|
|
||||||
assert.NotZero(t, testStats["TestPanic"].Start)
|
|
||||||
assert.NotZero(t, testStats["TestPanic"].End)
|
|
||||||
assert.False(t, testStats["TestPanic"].Passed)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// FailfastSuite will test the behavior when running with the failfast flag
|
// FailfastSuite will test the behavior when running with the failfast flag
|
||||||
|
@ -597,51 +535,21 @@ func TestFailfastSuite(t *testing.T) {
|
||||||
ok := testing.RunTests(
|
ok := testing.RunTests(
|
||||||
allTestsFilter,
|
allTestsFilter,
|
||||||
[]testing.InternalTest{{
|
[]testing.InternalTest{{
|
||||||
Name: t.Name() + "/FailfastSuite",
|
Name: "TestFailfastSuite",
|
||||||
F: func(t *testing.T) {
|
F: func(t *testing.T) {
|
||||||
Run(t, s)
|
Run(t, s)
|
||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
)
|
)
|
||||||
assert.False(t, ok)
|
assert.Equal(t, false, ok)
|
||||||
var expect []string
|
|
||||||
if failFast {
|
if failFast {
|
||||||
// Test A Fails and because we are running with failfast Test B never runs and we proceed straight to TearDownSuite
|
// 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 {
|
} else {
|
||||||
// Test A Fails and because we are running without failfast we continue and run Test B and then proceed to TearDownSuite
|
// 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) {
|
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
|
// 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")
|
cmd := exec.Command("go", "test", "-v", "-race", "-run", "TestFailfastSuite", "-failfast")
|
||||||
|
@ -679,70 +587,3 @@ func (s *FailfastSuite) Test_B_Passes() {
|
||||||
s.call("Test B Passes")
|
s.call("Test B Passes")
|
||||||
s.Require().True(true)
|
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)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue