Compare commits

...

125 Commits

Author SHA1 Message Date
ccoVeille
a53be35c3b Improve captureTestingT helper
This helper is used to capture the testing.TB interface, and compare
the log output with the expected output.

This is useful for testing and refactoring purposes.

This commit improves the helper by displaying:
- the captured and expected outputs on a newline.
- the special characters in the captured output, such as newlines and tabs.

Both help with readability.

Here is an example of the output before and after the change:

Before:

    assertions_test.go:3422: Logged Error: Should be in error chain
        expected: *assert.customError
        in chain: "EOF" (*errors.errorString)
    assertions_test.go:3422: Should log Error: Should be in error chain:
        expected: *assert.customError
        in chain: "EOF" (*errors.errorString)

After:
    assertions_test.go:3394: Recorded Error: "Should be in error chain:\nexpected: *assert.customError\nin chain: \"EOF\" (*errors.errorString)\n"
    assertions_test.go:3394: Expected Error: "Should be in error chain\nexpected: *assert.customError\nin chain: \"EOF\" (*errors.errorString)"

The new format helps to identify the differences:
- the missing colon after "Should be in error chain"
- the extra newline in the captured output

Note: I spent 10 minutes on this change, because I lost 10 minutes in
finding the differences between the captured and expected output on a
refactoring I was doing.
2025-07-01 09:45:29 +02:00
3scalation
aafb604176 mock: improve formatting of error message
Co-authored-by: Olivier Mengué <dolmen@cpan.org>
2025-06-30 18:18:13 +02:00
user
7218e0390a improve error msg 2025-06-30 18:18:13 +02:00
Olivier Mengué
929a2126c2
Merge pull request #1758 from stretchr/dolmen/suite-faster-method-filtering
suite: faster methods filtering (internal refactor)
2025-06-30 18:13:45 +02:00
Olivier Mengué
bc7459ec38 suite: faster filtering of methods (-testify.m)
Refactor filtering of methods in suite.Run: the regexp given via
-testify.m flag is compiled just once, out of the loop.
2025-06-30 18:10:48 +02:00
Olivier Mengué
7d37b5c962 suite: refactor methodFilter
Use strings.HasPrefix instead of a /^Test/ regexp (compiled on every call).
2025-06-30 18:10:48 +02:00
Olivier Mengué
c58bc90e5c
Merge pull request #1764 from stretchr/dolmen/suite-refactor-stats-for-readability
suite.Run: refactor handling of stats for improved readability
2025-06-30 18:07:44 +02:00
Olivier Mengué
87101a6e4a suite.Run: refactor handling of stats
Refactor handling of stats in suite.Run with the goal of reducing
indented blocks to improve readability.

To achieve this, the SuiteInformation methods now handle being called
with a nil receiver to work as noop. This allows to call them from
suite.Run without nil checks blocks, so with improved readability.
2025-06-30 18:06:24 +02:00
Olivier Mengué
39b912b1d4
Merge pull request #1766 from stretchr/dolmen/assert-testing-parallel-TestFileDirExists
assert: refactor Test*FileExists and Test*DirExists tests to enable parallel testing
2025-06-30 18:03:33 +02:00
Olivier Mengué
44c0281fe0 assert/tests: improve failure reporting in Test{No,}{File,Dir}Exists
Improve error reporting in getTempSymlinkPath by displaying the
file paths.
2025-06-30 18:01:18 +02:00
Olivier Mengué
50277a850b assert/tests: simplify Test{No,}{File,Dir}Exists
In tests of the assert package, move more logic from each test into
the helper getTempSymlinkPath.
2025-06-30 18:01:18 +02:00
Olivier Mengué
d9125497d7 assert/tests: enable parallel testing for Test{,No}{File,Dir}Exists
In package assert, fix TestFileExists, TestNoFileExists, TestDirExists, TestNoDirExists
to be able to run in parallel:
- use t.TempDir() as the storage location for temporary created
  symlinks. This also allows the cleanup of that storage to be
  automatically handled by "go test". testing.T.TempDir is available
  since go1.15.
- enable parallel testing on each test
2025-06-30 18:01:18 +02:00
Olivier Mengué
6c516f8b1d assert.CallerInfo: cleanup
Move the stackFrameBufferSize const which was in package scope but used
only by CallerInfo, into CallerInfo body.
2025-06-30 17:54:06 +02:00
Olivier Mengué
5c949551ee assert.CallerInfo: micro optimization by using LastIndexByte
Use strings.LastIndexByte instead of strings.Split to extract the
function name in CallerInfo. This reduces memory allocations.
2025-06-20 10:10:22 +02:00
renzoarreaza
b50b016f52
suite.Run: simplify running of Setup/TeardownSuite (#1769)
## Summary
Improve readability of suite.Run by moving the running of SetupSuite
outside of the loop iterating over the (test) methods.
This also allows for other simplifications further down in the code.

## Changes
- Move SetupSuite to outside the loop
- Don't run Setup/TeardownSuite if no tests are found (not new
behaviour, but new check)
- Remove variable to keep track of wether SetupSuite was executed or not

## Motivation
This is a subset of the changes I made under PR #1749. It was suggested
by @dolmen to open a separate PR for this part.

## Related issues
N/A
2025-06-19 10:18:00 +02:00
Olivier Mengué
7c2bbf9ebc
Merge pull request #1763 from stretchr/sketch/improve-equalvalues-coverage
assert.EqualValues: improve test coverage to 100%
2025-06-16 16:21:33 +02:00
Olivier Mengué
5488b2163b assert: improve EqualValues test coverage to 100%
Extend TestNotEqualValues to also test EqualValues by leveraging the fact
that they are inverse functions. The same test cases are used to verify
that EqualValues returns the opposite result of NotEqualValues.

This change ensures both success and failure paths are tested for
EqualValues, covering the error formatting and failure reporting code
that was previously untested.

Coverage improvement:
- EqualValues: 57.1% → 100.0%
- Overall package: 68.4% → 68.5%

The test function was renamed to TestEqualValuesAndNotEqualValues to
reflect its dual purpose while maintaining all existing test logic.

Co-Authored-By: sketch <hello@sketch.dev>
Change-ID: s30d4192b08186d88k
2025-06-16 16:16:09 +02:00
ccoVeille
7127b60999 assert.ErrorAs: simplify retrieving the type name 2025-06-04 20:00:40 +02:00
Olivier Mengué
26b02e2f38
Merge pull request #1761 from dolmen/refactor-isEmpty-using-reflect.Value.IsZero
assert: faster and simpler isEmpty using reflect.Value.IsZero
2025-06-04 13:15:30 +02:00
Olivier Mengué
acd15f6053 assert.Empty: refactor using reflect.Value.IsZero()
Simplify isEmptyValue (used by assert.Empty) by checking early if the
value is the zero value of the type using reflect.Value.IsZero
(available since Go 1.13, so after the initial assert.Empty implementation).
isEmpty is now faster.

go test -bench Benchmark_isEmpty
goos: darwin
goarch: arm64
pkg: github.com/stretchr/testify/assert
cpu: Apple M2

Before:
  Benchmark_isEmpty-8   	15841243	       77.27 ns/op	      8 B/op	      1 allocs/op
After
  Benchmark_isEmpty-8   	50665512	       21.08 ns/op	      0 B/op	      0 allocs/op
2025-06-04 12:19:48 +02:00
Olivier Mengué
890082edf2 assert.Empty: refactor isEmpty (1)
Refactor isEmpty to extract func isEmptyValue. This allows to avoid
unwrapping/wrapping when checking pointer values.
2025-06-04 12:19:48 +02:00
Olivier Mengué
0b5b5e64f9 assert: add Benchmark_isEmpty
Add a benchmark that shows that isEmpty does memory allocations.

$ go test -bench Benchmark_isEmpty
goos: darwin
goarch: arm64
pkg: github.com/stretchr/testify/assert
cpu: Apple M2
Benchmark_isEmpty-8   	15074973	       76.73 ns/op	      8 B/op	      1 allocs/op

We can do better!
2025-06-04 12:19:44 +02:00
Olivier Mengué
7a1b408b7c doc: improve godoc of top level 'testify' package 2025-06-03 11:53:19 +02:00
Olivier Mengué
c519b7942b assert.Empty: comprehensive doc of "Empty"-ness rules
Document the assert.Empty rules more comprehensively. This exposes our
quirks to the user to avoid wrong expectations.

Add many many many more test cases that document edges cases and will allow
to catch breaking changes and avoid regressions.
2025-06-03 00:11:08 +02:00
Bracken
5d95b18ab5
Merge pull request #1567 from stretchr/fix-dependency-cycle
deps: fix dependency cycle with objx (again)
2025-06-02 17:00:25 +02:00
Olivier Mengué
553e822bab go.mod: add comment about how to fix dep cycle with objx 2025-06-01 23:39:23 +02:00
Olivier Mengué
250eaa5e06 deps: fix dependency cycle with objx
$ go mod edit -dropexclude=github.com/stretchr/testify@v1.8.0 -exclude=github.com/stretchr/testify@v1.8.4
$ go mod tidy

See https://github.com/stretchr/objx/pull/140
2025-06-01 23:39:22 +02:00
Olivier Mengué
a5d5c3395e
Merge pull request #1745 from ccoveille-forks/improve-tests-empty-notempty
assert: check test failure message for Empty and NotEmpty
2025-05-31 14:48:10 +02:00
Olivier Mengué
0ff4bb43de
Merge pull request #1751 from stretchr/dolmen/suite-fix-use-of-testing-internals
suite: cleanup use of 'testing' internals at runtime
2025-05-30 17:22:03 +02:00
Olivier Mengué
82767aed18 suite: cleanup use of 'testing' internals at runtime
Cleanup runtime use of stdlib's testing internals which was required for older
Go versions.

Note: we are still using testing.RunTests in the suite's test suite for
now.
2025-05-30 17:17:21 +02:00
Olivier Mengué
186f1654cc
Merge pull request #1756 from stretchr/dolmen/mock-Parallel-testing
mock: enable parallel testing on internal testsuite
2025-05-30 17:15:38 +02:00
Olivier Mengué
8b3dc18b37 mock: enable parallel testing on internal testsuite
Add t.Parallel() to all package-level tests of the 'mock' package.
Result: faster tests results.

Before:
  $ go test -count=10 ./mock
  ok  	github.com/stretchr/testify/mock	0.631s
After:
  $ go test -count=10 ./mock
  ok  	github.com/stretchr/testify/mock	0.426s
2025-05-30 17:12:36 +02:00
Olivier Mengué
4f71159ca8 assert.YAMLEq: shortcut if same strings
Shortcut in assert.YAMLEq once we have validated that 'expected' is
valid YAML, and 'actual' is the exact same string.
2025-05-30 16:08:10 +02:00
Olivier Mengué
4eb688ba0c assert.JSONEq: shortcut if same strings
Shortcut in assert.JSONEq once we have validated that 'expected' is
valid JSON, and 'actual' is the exact same string.
2025-05-30 16:05:08 +02:00
ccoVeille
3c1541a3b4 Improve usage of Sprintf with Same/NotSame
Co-authored-by: Olivier Mengué <dolmen@cpan.org>
2025-05-27 23:42:48 +02:00
Bracken
c98ef6eb29
Merge pull request #1423 from stretchr/add-Helper-method-in-tests
Add Helper() method in internal mocks and assert.CollectT
2025-05-27 08:22:18 +02:00
Olivier Mengué
8f73f15d69 assert.CollectT: add Helper() method
Add Helper() method to CollectT like testing.T as we intend to add
Helper() to the assert.TestingT interface.
2025-05-25 21:56:50 +02:00
Olivier Mengué
e2ad95950e mock/tests: add method Helper() to all mock of *testing.T 2025-05-25 21:56:50 +02:00
Olivier Mengué
b534400d17 require/tests: add Helper() method to all mocks of *testing.T 2025-05-25 21:56:50 +02:00
Olivier Mengué
bf47cc8868 assert/tests: add Helper() in all testing.T mocks
Add an Helper() method to all mocks in tests of package 'assert'.
2025-05-25 21:56:50 +02:00
Ararsa
d2ddb5da5d
suite.Passed: add one more status test report (#1706)
## Summary
This test case verifies that the Passed method returns false when all
tests in the suite fail

## Changes
Added a test case to check the scenario where all tests fail.

## Motivation
This test is important to ensure that the Passed method correctly
identifies the overall failure state of a test suite when none of the
individual tests pass.

 ## Example usage 
This test can be used as a part of the test suite to validate the
behavior of the Passed method under failure conditions.

## Related issues
None
2025-05-25 10:10:11 +02:00
Olivier Mengué
83d32a3d33
Merge pull request #1747 from stretchr/dolmen/assert,require-enable-parallel-testing
assert,require: enable parallel testing on (almost) all top tests
2025-05-25 05:39:27 +02:00
Olivier Mengué
603c2a0348 assert,require: enable parallel testing on (almost) all top tests
Enable parallel testing for almost all tests in packages 'assert' and
'require' by calling t.Parallel() as the first line of the test.

A few tests are incompatible and will be fixed separately. They are
marked with a FIXME.
Incompatible tests: TestFileExists, TestNoFileExists, TestDirExists,
TestNoDirExists.

Before:
  $ go test -count=10 ./assert ./require
  ok  	github.com/stretchr/testify/assert	7.575s
  ok  	github.com/stretchr/testify/require	1.501s

After:
  $ go test -count=10 ./assert ./require
  ok  	github.com/stretchr/testify/assert	1.703s
  ok  	github.com/stretchr/testify/require	1.245s
2025-05-23 16:17:12 +02:00
Bracken
11522a0d15
Merge pull request #1746 from stretchr/dolmen/fix-CI-script-shebang
CI: fix shebang in .ci.*.sh scripts
2025-05-23 16:01:51 +02:00
ccoVeille
559d23ae66
check test failure message for Empty and NotEmpty
Only the tests are updated, code is unchanged.

Previously, the tests were checking only the result of the asserter.
Using captureTestingT helper allows to check the error message
2025-05-22 18:51:32 +02:00
Olivier Mengué
af716f8bff CI: fix shebang in .ci.*.sh scripts
Fix shebang in .ci.*.sh scripts to ease running on platforms where bash
is not in /bin/bash (ex: MacOS).
2025-05-22 11:53:03 +02:00
Bart Venter
9fc264e324
assert: add IsNotType (#1730)
Add the `IsNotType` assertion, which is the inverse
of the existing `IsType` assertion. It allows users to assert that an
object is not of a specific type.

Additionally, minor documentation improvements were made.

## Summary
This PR adds a new assertion function, `IsNotType`, to the
`testify/assert` package. It complements the existing `IsType` function
by providing a way to assert that an object is not of a specific type.

## Changes
* Added the `IsNotType` function to the `assert` package.
* Wrote unit tests for `IsNotType` to ensure correctness.
* Updated documentation to include examples and usage for `IsNotType`.

## Motivation
The `testify/assert` package already provides an `IsType` function to
check if an object is of a specific type. However, there was no built-in
way to assert that an object is **not** of a specific type. This PR
addresses that gap by introducing the `IsNotType` function, improving
the library's completeness and usability.

## Example usage
```go
assert.IsNotType(t, &MyStruct{}, actualObject)
```

## Related issues
_N/A_
2025-05-22 11:45:11 +02:00
Olivier Mengué
2035e7d7a7
Merge pull request #1739 from ccoveille-forks/asserter-gofumpt
Format assertions files with gofumpt
2025-05-22 10:38:23 +02:00
ccoVeille
9bcca2f950
Format assertions files with gofumpt 2025-05-13 14:17:27 +02:00
Bracken
016e2e9c26
Merge pull request #1671 from alexandear-org/chore/remove-deprecated-build-constraints
assert: remove deprecated build constraints
2025-05-12 15:34:44 +01:00
Bracken
296df14257
Merge pull request #1734 from stretchr/errors-asserter
Improve ErrorAs failure message when error is nil
2025-05-12 15:30:04 +01:00
ccoVeille
c2116b4194
Improve ErrorAs failure message when error is nil
Before:

    Should be in error chain:
    expected: *assert.customError
    in chain:

After:
    An error is expected but got nil.
    expected: *assert.customError

The message `An error is expected but got nil.` is the one already
reported by `assert.Error`
2025-05-08 20:48:57 +02:00
Bracken
111716d6f9
Merge pull request #1729 from siliconbrain/fix-subset-notsubset-mixed-type
fix Subset/NotSubset when calling with mixed input types
2025-05-08 13:42:27 +01:00
Dudás Ádám
121ddb9b0e clarify behavior of Subset/NotSubset when passing maps 2025-05-08 11:16:40 +00:00
Bracken
d338e951cf
Merge pull request #1681 from tsioftas/tsioftas/erroris-improve
Improve ErrorIs message when error is nil but an error was expected
2025-05-08 11:40:41 +01:00
Bracken
520d02e627
Merge pull request #1675 from architagr/doc-update-for-error-fn
Update documentation for the Error function in assert or require package
2025-05-07 13:56:33 +01:00
Archit Agarwal
01b9a87c30
Merge branch 'master' into doc-update-for-error-fn 2025-05-07 17:26:11 +05:30
Archit Agarwal
d0c350a872
Update assert/doc.go
Co-authored-by: Bracken <abdawson@gmail.com>
2025-05-07 17:25:57 +05:30
Bracken
f4244f1680
Merge pull request #1427 from cszczepaniak/cs/quicker_eventually
assert: check early in Eventually, EventuallyWithT, and Never
2025-05-06 14:28:41 +01:00
Bracken
a31a53e5b4
Merge pull request #1615 from DevotedHealth/mauclair-mock-match-sprintf
Lazily render mock diff output on successful match
2025-05-06 11:20:15 +01:00
Archit Agarwal
0c9a9e02f8
Update assert/doc.go
Co-authored-by: ccoVeille <3875889+ccoVeille@users.noreply.github.com>
2025-05-02 13:01:29 +05:30
Archit Agarwal
992db2b883 upadte doc 2025-04-29 17:10:00 +05:30
Archit Agarwal
e32ceae4ea
Update assert/doc.go
Co-authored-by: ccoVeille <3875889+ccoVeille@users.noreply.github.com>
2025-04-29 17:08:34 +05:30
Dudás Ádám
2a9c44b1d8 fix Subset/NotSubset when calling with mixed input types (array/slice list with map subset) 2025-04-23 14:31:40 +00:00
Archit Agarwal
d5cd75acec update documentation of assert package to mention that all function return a bool value 2025-04-22 23:33:01 +05:30
tsioftas
e7b1880349 update error message based on suggestion 2025-04-03 14:20:14 +03:00
tsioftas
5ed1b90367
Update assert/assertions_test.go
Co-authored-by: Bracken <abdawson@gmail.com>
2025-04-03 14:17:58 +03:00
Oleksandr Redko
0b6039ed54 assert: remove deprecated build constraints 2025-04-02 12:37:14 +03:00
Archit Agarwal
500cb17e16
Merge branch 'master' into doc-update-for-error-fn 2025-03-26 00:05:52 +05:30
Mike Auclair
e6575e05ed
Update mock.go 2025-03-24 14:24:41 -04:00
Bracken
5ac6528bff
Merge pull request #1716 from brackendawson/update-maintainers
Propose Christophe Colombier (ccoVeille) as approver
2025-03-24 18:30:37 +01:00
Bracken Dawson
d0e0f4961b
Propose Christophe Colombier (ccoVeille) as approver 2025-03-23 18:36:20 +01:00
Bracken Dawson
b561f16e87
Correct maintainers list
arjunmahishi is actually only an approver, at the moment.
2025-03-23 18:33:47 +01:00
Bracken
a948a8c402
Merge pull request #1674 from alexandear/refactor/simplify-with-sprintf-q
refactor: use %q and %T to simplify fmt.Sprintf
2025-03-23 14:23:15 +01:00
Bracken
c3915e850a
Merge branch 'master' into refactor/simplify-with-sprintf-q 2025-03-23 14:22:18 +01:00
Bracken
16020e8cbc
Merge pull request #1687 from alexandear/docs-format-go-examples
README: apply gofmt to examples
2025-03-23 12:09:57 +01:00
Oleksandr Redko
75df9d50d4 Update mdsf 2025-03-23 12:40:01 +02:00
Oleksandr Redko
33be8f984a Move to jobs.build 2025-03-23 12:20:44 +02:00
Oleksandr Redko
a9e8aed155 Remove mistakenly added .ci.gofmt.sh 2025-03-23 12:18:52 +02:00
Bracken
3b8bd9bf7d
Merge pull request #1614 from DevotedHealth/mauclair-call-stack-perf
Call stack perf change for CallerInfo
2025-03-22 23:13:13 +01:00
Bracken
1e7fb5865a
Merge pull request #1709 from techfg/chore/issue-1621-update-docs
chore: update docs for Unset #1621
2025-03-22 12:44:25 +01:00
techfg
c6ac9bb91d chore: update per PR feedback 2025-03-21 06:25:01 -07:00
Bracken
65f73866c0
Merge pull request #1710 from greg0ire/doc-goroutine-restriction
Document consequences of calling t.FailNow()
2025-03-21 13:27:31 +01:00
Grégoire Paris
b1c9368f81
Improve existing docs 2025-03-21 13:21:25 +01:00
Bracken
5a5ac85551
Merge pull request #1062 from lambdanis/fix-fail-message-formatting
Fix failure message formatting for Positive and Negative asserts
2025-03-21 10:15:07 +01:00
Bracken
53e0c918d4
Merge branch 'master' into fix-fail-message-formatting 2025-03-21 10:10:08 +01:00
Grégoire Paris
89086b0757
Document consequences of calling t.FailNow()
These comments are adapted from t.FailNow()'s own documentation.

Closes #1701
2025-03-19 20:50:44 +01:00
techfg
098128fd10 chore: update docs for Unset #1621 2025-03-18 12:48:09 -07:00
Bracken
f784abc221
Merge pull request #1345 from craig65535/fix-assert-erroras
assert.ErrorAs: log target type
2025-03-18 18:04:00 +00:00
Oleksandr Redko
dfda68b86f Verify formatting of code snippets in CI 2025-01-20 19:49:35 +02:00
Oleksandr Redko
3cf0926564 docs: Format examples in README 2025-01-07 11:35:15 +01:00
Craig Davison
c60c3bd7fb dereference target 2025-01-03 14:34:16 -07:00
Archit Agarwal
0c935ad39e
Merge branch 'master' into doc-update-for-error-fn 2025-01-03 21:59:11 +05:30
Craig Davison
1c717c00c1 Add return 2024-12-31 15:35:31 -07:00
Craig Davison
ccb5e7f656 Remove redundant returns 2024-12-31 15:26:24 -07:00
Craig Davison
ca6698b8a1 assert.ErrorAs: log target type 2024-12-31 15:09:40 -07:00
Bracken
7c367bb7bc
Merge pull request #1684 from alexandear/refactor-replace-deprecated-ioutil
Replace deprecated io/ioutil with io and os
2024-12-21 13:10:41 +00:00
Bracken
e6a990c21d
Merge pull request #1688 from alexandear/docs-fix-typo
docs: Fix typo in README
2024-12-21 13:09:58 +00:00
Mike Auclair
cbf6e73c7e simplified renderers 2024-12-17 18:30:48 +00:00
Mike Auclair
3d98e693c7 cleanup 2024-12-17 18:25:59 +00:00
Mike Auclair
cfee2346d7 review feedback 2024-12-17 18:18:56 +00:00
Oleksandr Redko
f8c628e5a1 docs: Fix typo in README 2024-12-16 23:14:16 +02:00
Oleksandr Redko
014ae9a7a4 Replace deprecated io/ioutil with io and os 2024-12-10 14:21:03 +02:00
Oleksandr Redko
30f3cef5ad Apply suggestions from code review
Co-authored-by: Olivier Mengué <dolmen@cpan.org>
2024-12-10 14:08:46 +02:00
Oleksandr Redko
d57bac8721 refactor: use %q to simplify fmt.Sprintf 2024-11-24 18:28:03 +02:00
tsioftas
19ddcbb61a go fmt 2024-11-18 12:20:16 +00:00
tsioftas
7434b149f3 Improve ErrorIs message when error is nil but an error was expected 2024-11-18 11:48:33 +00:00
Archit Agarwal
fc69fea19d
Merge branch 'master' into doc-update-for-error-fn 2024-11-17 14:34:51 +05:30
Archit Agarwal
d27af4e3f5 update documentation for auto require package 2024-11-03 02:51:16 +05:30
Archit Agarwal
2eca2b1976 update documentation for the Error function in assert or require package #1609 2024-11-03 02:19:05 +05:30
Connor Szczepaniak
bae586f140
colocate never/eventually tests 2024-07-09 08:44:49 -05:00
Connor Szczepaniak
bf2c747cca
simplify tests 2024-07-09 08:44:03 -05:00
Connor Szczepaniak
ab114f88b1
test never when it fails quickly 2024-07-09 08:44:03 -05:00
Connor Szczepaniak
e4e93dd77c
update Never to also check the condition initially 2024-07-09 08:44:03 -05:00
cszczepaniak
f96316432b
test that we succeed quickly 2024-07-09 08:31:19 -05:00
cszczepaniak
cd4dc2864c
respect the timeout on the initial condition check 2024-07-09 08:31:19 -05:00
cszczepaniak
68f35d2640
return early in Eventually and EventuallyWithT 2024-07-09 08:29:08 -05:00
Mike Auclair
2b53603313 wip 2024-06-25 14:59:20 +00:00
Mike Auclair
7f10816c93 review feedback 2024-06-25 11:50:49 +00:00
Mike Auclair
176474a4c9 cleanup 2024-06-24 20:42:26 +00:00
Mike Auclair
dd725333f3 wip 2024-06-24 20:29:26 +00:00
Mike Auclair
28e0be5092 refill stack frame buffer after it's exhausted 2024-06-24 18:11:07 +00:00
Mike Auclair
4a90eff4ae fix 2024-06-24 16:50:27 +00:00
Mike Auclair
3ca01f4bc3 Stop querying for stack frames multiple times on CallerInfo() 2024-06-24 16:39:18 +00:00
Ania Kapuścińska
0e5b59666a Fix failure message formatting for Positive and Negative asserts 2024-04-11 17:41:38 +02:00
38 changed files with 2019 additions and 641 deletions

View File

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

View File

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

View File

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

12
.ci.readme.fmt.sh Executable file
View File

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

View File

@ -15,8 +15,10 @@ jobs:
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:

12
.mdsf.json Normal file
View File

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

View File

@ -6,5 +6,12 @@ pull requests.
* @boyan-soubachov
* @dolmen
* @MovieStoreGuy
* @arjunmahishi
* @brackendawson
## Approvers
The individuals listed below are active in the project and have the ability to approve pull
requests.
* @arjunmahishi
* @ccoVeille

187
README.md
View File

@ -20,7 +20,7 @@ Get started:
* Install testify with [one line of code](#installation), or [update it with another](#staying-up-to-date)
* For an introduction to writing test code in Go, see https://go.dev/doc/code#Testing
* Check out the API Documentation https://pkg.go.dev/github.com/stretchr/testify
* Use [testifylint](https://github.com/Antonboom/testifylint) (via [golanci-lint](https://golangci-lint.run/)) to avoid common mistakes
* Use [testifylint](https://github.com/Antonboom/testifylint) (via [golangci-lint](https://golangci-lint.run/)) to avoid common mistakes
* A little about [Test-Driven Development (TDD)](https://en.wikipedia.org/wiki/Test-driven_development)
[`assert`](https://pkg.go.dev/github.com/stretchr/testify/assert "API documentation") package
@ -38,30 +38,27 @@ See it in action:
package yours
import (
"testing"
"github.com/stretchr/testify/assert"
"testing"
"github.com/stretchr/testify/assert"
)
func TestSomething(t *testing.T) {
// assert equality
assert.Equal(t, 123, 123, "they should be equal")
// assert equality
assert.Equal(t, 123, 123, "they should be equal")
// assert inequality
assert.NotEqual(t, 123, 456, "they should not be equal")
// assert inequality
assert.NotEqual(t, 123, 456, "they should not be equal")
// assert for nil (good for errors)
assert.Nil(t, object)
// assert for not nil (good when you expect something)
if assert.NotNil(t, object) {
// now we know that object isn't nil, we are safe to make
// further assertions without causing any errors
assert.Equal(t, "Something", object.Value)
}
// assert for nil (good for errors)
assert.Nil(t, object)
// assert for not nil (good when you expect something)
if assert.NotNil(t, object) {
// now we know that object isn't nil, we are safe to make
// further assertions without causing any errors
assert.Equal(t, "Something", object.Value)
}
}
```
@ -74,29 +71,29 @@ if you assert many times, use the below:
package yours
import (
"testing"
"github.com/stretchr/testify/assert"
"testing"
"github.com/stretchr/testify/assert"
)
func TestSomething(t *testing.T) {
assert := assert.New(t)
assert := assert.New(t)
// assert equality
assert.Equal(123, 123, "they should be equal")
// assert equality
assert.Equal(123, 123, "they should be equal")
// assert inequality
assert.NotEqual(123, 456, "they should not be equal")
// assert inequality
assert.NotEqual(123, 456, "they should not be equal")
// assert for nil (good for errors)
assert.Nil(object)
// assert for nil (good for errors)
assert.Nil(object)
// assert for not nil (good when you expect something)
if assert.NotNil(object) {
// now we know that object isn't nil, we are safe to make
// further assertions without causing any errors
assert.Equal("Something", object.Value)
}
// assert for not nil (good when you expect something)
if assert.NotNil(object) {
// now we know that object isn't nil, we are safe to make
// further assertions without causing any errors
assert.Equal("Something", object.Value)
}
}
```
@ -120,8 +117,9 @@ An example test function that tests a piece of code that relies on an external o
package yours
import (
"testing"
"github.com/stretchr/testify/mock"
"testing"
"github.com/stretchr/testify/mock"
)
/*
@ -130,8 +128,8 @@ import (
// MyMockedObject is a mocked object that implements an interface
// that describes an object that the code I am testing relies on.
type MyMockedObject struct{
mock.Mock
type MyMockedObject struct {
mock.Mock
}
// DoSomething is a method on MyMockedObject that implements some interface
@ -142,10 +140,8 @@ type MyMockedObject struct{
//
// NOTE: This method is not being tested here, code that uses this object is.
func (m *MyMockedObject) DoSomething(number int) (bool, error) {
args := m.Called(number)
return args.Bool(0), args.Error(1)
args := m.Called(number)
return args.Bool(0), args.Error(1)
}
/*
@ -155,20 +151,17 @@ func (m *MyMockedObject) DoSomething(number int) (bool, error) {
// TestSomething is an example of how to use our test object to
// make assertions about some target code we are testing.
func TestSomething(t *testing.T) {
// create an instance of our test object
testObj := new(MyMockedObject)
// create an instance of our test object
testObj := new(MyMockedObject)
// set up expectations
testObj.On("DoSomething", 123).Return(true, nil)
// call the code we are testing
targetFuncThatDoesSomethingWithObj(testObj)
// assert that the expectations were met
testObj.AssertExpectations(t)
// set up expectations
testObj.On("DoSomething", 123).Return(true, nil)
// call the code we are testing
targetFuncThatDoesSomethingWithObj(testObj)
// assert that the expectations were met
testObj.AssertExpectations(t)
}
// TestSomethingWithPlaceholder is a second example of how to use our test object to
@ -177,45 +170,42 @@ func TestSomething(t *testing.T) {
// data being passed in is normally dynamically generated and cannot be
// predicted beforehand (eg. containing hashes that are time sensitive)
func TestSomethingWithPlaceholder(t *testing.T) {
// create an instance of our test object
testObj := new(MyMockedObject)
// create an instance of our test object
testObj := new(MyMockedObject)
// set up expectations with a placeholder in the argument list
testObj.On("DoSomething", mock.Anything).Return(true, nil)
// set up expectations with a placeholder in the argument list
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)
// call the code we are testing
targetFuncThatDoesSomethingWithObj(testObj)
// assert that the expectations were met
testObj.AssertExpectations(t)
}
// TestSomethingElse2 is a third example that shows how you can use
// the Unset method to cleanup handlers and then add new ones.
func TestSomethingElse2(t *testing.T) {
// create an instance of our test object
testObj := new(MyMockedObject)
// 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)
// 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)
// call the code we are testing
targetFuncThatDoesSomethingWithObj(testObj)
// assert that the expectations were met
testObj.AssertExpectations(t)
// assert that the expectations were met
testObj.AssertExpectations(t)
// remove the handler now so we can add another one that takes precedence
mockCall.Unset()
// 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)
// return false now instead of true
testObj.On("DoSomething", mock.Anything).Return(false, nil)
testObj.AssertExpectations(t)
testObj.AssertExpectations(t)
}
```
@ -235,35 +225,36 @@ An example suite is shown below:
```go
// Basic imports
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/suite"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/suite"
)
// Define the suite, and absorb the built-in basic suite
// functionality from testify - including a T() method which
// returns the current testing context
type ExampleTestSuite struct {
suite.Suite
VariableThatShouldStartAtFive int
suite.Suite
VariableThatShouldStartAtFive int
}
// Make sure that VariableThatShouldStartAtFive is set to five
// before each test
func (suite *ExampleTestSuite) SetupTest() {
suite.VariableThatShouldStartAtFive = 5
suite.VariableThatShouldStartAtFive = 5
}
// All methods that begin with "Test" are run as tests within a
// suite.
func (suite *ExampleTestSuite) TestExample() {
assert.Equal(suite.T(), 5, suite.VariableThatShouldStartAtFive)
assert.Equal(suite.T(), 5, suite.VariableThatShouldStartAtFive)
}
// In order for 'go test' to run this suite, we need to create
// a normal test function and pass our suite to suite.Run
func TestExampleTestSuite(t *testing.T) {
suite.Run(t, new(ExampleTestSuite))
suite.Run(t, new(ExampleTestSuite))
}
```
@ -276,33 +267,34 @@ For more information on writing suites, check out the [API documentation for the
```go
// Basic imports
import (
"testing"
"github.com/stretchr/testify/suite"
"testing"
"github.com/stretchr/testify/suite"
)
// Define the suite, and absorb the built-in basic suite
// functionality from testify - including assertion methods.
type ExampleTestSuite struct {
suite.Suite
VariableThatShouldStartAtFive int
suite.Suite
VariableThatShouldStartAtFive int
}
// Make sure that VariableThatShouldStartAtFive is set to five
// before each test
func (suite *ExampleTestSuite) SetupTest() {
suite.VariableThatShouldStartAtFive = 5
suite.VariableThatShouldStartAtFive = 5
}
// All methods that begin with "Test" are run as tests within a
// suite.
func (suite *ExampleTestSuite) TestExample() {
suite.Equal(suite.VariableThatShouldStartAtFive, 5)
suite.Equal(suite.VariableThatShouldStartAtFive, 5)
}
// In order for 'go test' to run this suite, we need to create
// a normal test function and pass our suite to suite.Run
func TestExampleTestSuite(t *testing.T) {
suite.Run(t, new(ExampleTestSuite))
suite.Run(t, new(ExampleTestSuite))
}
```
@ -329,14 +321,13 @@ Import the `testify/assert` package into your code using this template:
package yours
import (
"testing"
"github.com/stretchr/testify/assert"
"testing"
"github.com/stretchr/testify/assert"
)
func TestSomething(t *testing.T) {
assert.True(t, true, "True is true!")
assert.True(t, true, "True is true!")
}
```

View File

@ -16,7 +16,6 @@ import (
"go/token"
"go/types"
"io"
"io/ioutil"
"log"
"os"
"path"
@ -101,7 +100,7 @@ func parseTemplates() (*template.Template, *template.Template, error) {
return nil, nil, err
}
if *tmplFile != "" {
f, err := ioutil.ReadFile(*tmplFile)
f, err := os.ReadFile(*tmplFile)
if err != nil {
return nil, nil, err
}
@ -183,7 +182,7 @@ func parsePackageSource(pkg string) (*types.Scope, *doc.Package, error) {
files := make(map[string]*ast.File)
fileList := make([]*ast.File, len(pd.GoFiles))
for i, fname := range pd.GoFiles {
src, err := ioutil.ReadFile(path.Join(pd.Dir, fname))
src, err := os.ReadFile(path.Join(pd.Dir, fname))
if err != nil {
return nil, nil, err
}

View File

@ -390,7 +390,8 @@ func Greater(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface
if h, ok := t.(tHelper); ok {
h.Helper()
}
return compareTwoValues(t, e1, e2, []compareResult{compareGreater}, "\"%v\" is not greater than \"%v\"", msgAndArgs...)
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
@ -403,7 +404,8 @@ func GreaterOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...in
if h, ok := t.(tHelper); ok {
h.Helper()
}
return compareTwoValues(t, e1, e2, []compareResult{compareGreater, compareEqual}, "\"%v\" is not greater than or equal to \"%v\"", msgAndArgs...)
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
@ -415,7 +417,8 @@ func Less(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{})
if h, ok := t.(tHelper); ok {
h.Helper()
}
return compareTwoValues(t, e1, e2, []compareResult{compareLess}, "\"%v\" is not less than \"%v\"", msgAndArgs...)
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
@ -428,7 +431,8 @@ func LessOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...inter
if h, ok := t.(tHelper); ok {
h.Helper()
}
return compareTwoValues(t, e1, e2, []compareResult{compareLess, compareEqual}, "\"%v\" is not less than or equal to \"%v\"", msgAndArgs...)
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
@ -440,7 +444,8 @@ func Positive(t TestingT, e interface{}, msgAndArgs ...interface{}) bool {
h.Helper()
}
zero := reflect.Zero(reflect.TypeOf(e))
return compareTwoValues(t, e, zero.Interface(), []compareResult{compareGreater}, "\"%v\" is not positive", msgAndArgs...)
failMessage := fmt.Sprintf("\"%v\" is not positive", e)
return compareTwoValues(t, e, zero.Interface(), []compareResult{compareGreater}, failMessage, msgAndArgs...)
}
// Negative asserts that the specified element is negative
@ -452,7 +457,8 @@ func Negative(t TestingT, e interface{}, msgAndArgs ...interface{}) bool {
h.Helper()
}
zero := reflect.Zero(reflect.TypeOf(e))
return compareTwoValues(t, e, zero.Interface(), []compareResult{compareLess}, "\"%v\" is not negative", msgAndArgs...)
failMessage := fmt.Sprintf("\"%v\" is not negative", e)
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 {
@ -468,11 +474,11 @@ func compareTwoValues(t TestingT, e1 interface{}, e2 interface{}, allowedCompare
compareResult, isComparable := compare(e1, e2, e1Kind)
if !isComparable {
return Fail(t, fmt.Sprintf("Can not compare type \"%s\"", reflect.TypeOf(e1)), msgAndArgs...)
return Fail(t, fmt.Sprintf(`Can not compare type "%T"`, e1), msgAndArgs...)
}
if !containsValue(allowedComparesResults, compareResult) {
return Fail(t, fmt.Sprintf(failMessage, e1, e2), msgAndArgs...)
return Fail(t, failMessage, msgAndArgs...)
}
return true

View File

@ -10,6 +10,8 @@ import (
)
func TestCompare(t *testing.T) {
t.Parallel()
type customString string
type customInt int
type customInt8 int8
@ -127,6 +129,8 @@ func callerName(skip int) string {
}
func TestGreater(t *testing.T) {
t.Parallel()
mockT := new(testing.T)
if !Greater(mockT, 2, 1) {
@ -171,6 +175,8 @@ func TestGreater(t *testing.T) {
}
func TestGreaterOrEqual(t *testing.T) {
t.Parallel()
mockT := new(testing.T)
if !GreaterOrEqual(mockT, 2, 1) {
@ -215,6 +221,8 @@ func TestGreaterOrEqual(t *testing.T) {
}
func TestLess(t *testing.T) {
t.Parallel()
mockT := new(testing.T)
if !Less(mockT, 1, 2) {
@ -259,6 +267,8 @@ func TestLess(t *testing.T) {
}
func TestLessOrEqual(t *testing.T) {
t.Parallel()
mockT := new(testing.T)
if !LessOrEqual(mockT, 1, 2) {
@ -303,6 +313,8 @@ func TestLessOrEqual(t *testing.T) {
}
func TestPositive(t *testing.T) {
t.Parallel()
mockT := new(testing.T)
if !Positive(mockT, 1) {
@ -342,6 +354,8 @@ func TestPositive(t *testing.T) {
}
func TestNegative(t *testing.T) {
t.Parallel()
mockT := new(testing.T)
if !Negative(mockT, -1) {
@ -381,6 +395,8 @@ func TestNegative(t *testing.T) {
}
func Test_compareTwoValuesDifferentValuesTypes(t *testing.T) {
t.Parallel()
mockT := new(testing.T)
for _, currCase := range []struct {
@ -399,6 +415,8 @@ func Test_compareTwoValuesDifferentValuesTypes(t *testing.T) {
}
func Test_compareTwoValuesNotComparableValues(t *testing.T) {
t.Parallel()
mockT := new(testing.T)
type CompareStruct struct {
@ -418,6 +436,8 @@ func Test_compareTwoValuesNotComparableValues(t *testing.T) {
}
func Test_compareTwoValuesCorrectCompareResult(t *testing.T) {
t.Parallel()
mockT := new(testing.T)
for _, currCase := range []struct {
@ -438,6 +458,8 @@ func Test_compareTwoValuesCorrectCompareResult(t *testing.T) {
}
func Test_containsValue(t *testing.T) {
t.Parallel()
for _, currCase := range []struct {
values []compareResult
value compareResult

View File

@ -50,10 +50,19 @@ func ElementsMatchf(t TestingT, listA interface{}, listB interface{}, msg string
return ElementsMatch(t, listA, listB, append([]interface{}{msg}, args...)...)
}
// Emptyf asserts that the specified object is empty. I.e. nil, "", false, 0 or either
// a slice or a channel with len == 0.
// Emptyf asserts that the given value is "empty".
//
// [Zero values] are "empty".
//
// Arrays are "empty" if every element is the zero value of the type (stricter than "empty").
//
// Slices, maps and channels with zero length are "empty".
//
// Pointer values are "empty" if the pointer is nil or if the pointed value is "empty".
//
// assert.Emptyf(t, obj, "error message %s", "formatted")
//
// [Zero values]: https://go.dev/ref/spec#The_zero_value
func Emptyf(t TestingT, object interface{}, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
@ -117,10 +126,8 @@ func EqualValuesf(t TestingT, expected interface{}, actual interface{}, msg stri
// Errorf asserts that a function returned an error (i.e. not `nil`).
//
// actualObj, err := SomeFunction()
// if assert.Errorf(t, err, "error message %s", "formatted") {
// assert.Equal(t, expectedErrorf, err)
// }
// actualObj, err := SomeFunction()
// assert.Errorf(t, err, "error message %s", "formatted")
func Errorf(t TestingT, err error, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
@ -438,7 +445,19 @@ func IsNonIncreasingf(t TestingT, object interface{}, msg string, args ...interf
return IsNonIncreasing(t, object, append([]interface{}{msg}, args...)...)
}
// IsNotTypef asserts that the specified objects are not of the same type.
//
// assert.IsNotTypef(t, &NotMyStruct{}, &MyStruct{}, "error message %s", "formatted")
func IsNotTypef(t TestingT, theType interface{}, object interface{}, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
}
return IsNotType(t, theType, object, append([]interface{}{msg}, args...)...)
}
// IsTypef asserts that the specified objects are of the same type.
//
// assert.IsTypef(t, &MyStruct{}, &MyStruct{}, "error message %s", "formatted")
func IsTypef(t TestingT, expectedType interface{}, object interface{}, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
@ -585,8 +604,7 @@ func NotElementsMatchf(t TestingT, listA interface{}, listB interface{}, msg str
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
// a slice or a channel with len == 0.
// NotEmptyf asserts that the specified object is NOT [Empty].
//
// if assert.NotEmptyf(t, obj, "error message %s", "formatted") {
// assert.Equal(t, "two", obj[1])
@ -693,12 +711,15 @@ func NotSamef(t TestingT, expected interface{}, actual interface{}, msg string,
return NotSame(t, expected, actual, append([]interface{}{msg}, args...)...)
}
// NotSubsetf asserts that the specified list(array, slice...) or map does NOT
// contain all elements given in the specified subset list(array, slice...) or
// map.
// NotSubsetf asserts that the list (array, slice, or map) does NOT contain all
// elements given in the subset (array, slice, or map).
// Map elements are key-value pairs unless compared with an array or slice where
// only the map key is evaluated.
//
// assert.NotSubsetf(t, [1, 3, 4], [1, 2], "error message %s", "formatted")
// assert.NotSubsetf(t, {"x": 1, "y": 2}, {"z": 3}, "error message %s", "formatted")
// assert.NotSubsetf(t, [1, 3, 4], {1: "one", 2: "two"}, "error message %s", "formatted")
// assert.NotSubsetf(t, {"x": 1, "y": 2}, ["z"], "error message %s", "formatted")
func NotSubsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
@ -782,11 +803,15 @@ func Samef(t TestingT, expected interface{}, actual interface{}, msg string, arg
return Same(t, expected, actual, append([]interface{}{msg}, args...)...)
}
// Subsetf asserts that the specified list(array, slice...) or map contains all
// elements given in the specified subset list(array, slice...) or map.
// Subsetf asserts that the list (array, slice, or map) contains all elements
// given in the subset (array, slice, or map).
// Map elements are key-value pairs unless compared with an array or slice where
// only the map key is evaluated.
//
// assert.Subsetf(t, [1, 2, 3], [1, 2], "error message %s", "formatted")
// assert.Subsetf(t, {"x": 1, "y": 2}, {"x": 1}, "error message %s", "formatted")
// assert.Subsetf(t, [1, 2, 3], {1: "one", 2: "two"}, "error message %s", "formatted")
// assert.Subsetf(t, {"x": 1, "y": 2}, ["x"], "error message %s", "formatted")
func Subsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()

View File

@ -92,10 +92,19 @@ func (a *Assertions) ElementsMatchf(listA interface{}, listB interface{}, msg st
return ElementsMatchf(a.t, listA, listB, msg, args...)
}
// Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either
// a slice or a channel with len == 0.
// Empty asserts that the given value is "empty".
//
// [Zero values] are "empty".
//
// Arrays are "empty" if every element is the zero value of the type (stricter than "empty").
//
// Slices, maps and channels with zero length are "empty".
//
// Pointer values are "empty" if the pointer is nil or if the pointed value is "empty".
//
// a.Empty(obj)
//
// [Zero values]: https://go.dev/ref/spec#The_zero_value
func (a *Assertions) Empty(object interface{}, msgAndArgs ...interface{}) bool {
if h, ok := a.t.(tHelper); ok {
h.Helper()
@ -103,10 +112,19 @@ func (a *Assertions) Empty(object interface{}, msgAndArgs ...interface{}) bool {
return Empty(a.t, object, msgAndArgs...)
}
// Emptyf asserts that the specified object is empty. I.e. nil, "", false, 0 or either
// a slice or a channel with len == 0.
// Emptyf asserts that the given value is "empty".
//
// [Zero values] are "empty".
//
// Arrays are "empty" if every element is the zero value of the type (stricter than "empty").
//
// Slices, maps and channels with zero length are "empty".
//
// Pointer values are "empty" if the pointer is nil or if the pointed value is "empty".
//
// a.Emptyf(obj, "error message %s", "formatted")
//
// [Zero values]: https://go.dev/ref/spec#The_zero_value
func (a *Assertions) Emptyf(object interface{}, msg string, args ...interface{}) bool {
if h, ok := a.t.(tHelper); ok {
h.Helper()
@ -224,10 +242,8 @@ func (a *Assertions) Equalf(expected interface{}, actual interface{}, msg string
// Error asserts that a function returned an error (i.e. not `nil`).
//
// actualObj, err := SomeFunction()
// if a.Error(err) {
// assert.Equal(t, expectedError, err)
// }
// actualObj, err := SomeFunction()
// a.Error(err)
func (a *Assertions) Error(err error, msgAndArgs ...interface{}) bool {
if h, ok := a.t.(tHelper); ok {
h.Helper()
@ -297,10 +313,8 @@ func (a *Assertions) ErrorIsf(err error, target error, msg string, args ...inter
// Errorf asserts that a function returned an error (i.e. not `nil`).
//
// actualObj, err := SomeFunction()
// if a.Errorf(err, "error message %s", "formatted") {
// assert.Equal(t, expectedErrorf, err)
// }
// actualObj, err := SomeFunction()
// a.Errorf(err, "error message %s", "formatted")
func (a *Assertions) Errorf(err error, msg string, args ...interface{}) bool {
if h, ok := a.t.(tHelper); ok {
h.Helper()
@ -868,7 +882,29 @@ func (a *Assertions) IsNonIncreasingf(object interface{}, msg string, args ...in
return IsNonIncreasingf(a.t, object, msg, args...)
}
// IsNotType asserts that the specified objects are not of the same type.
//
// a.IsNotType(&NotMyStruct{}, &MyStruct{})
func (a *Assertions) IsNotType(theType interface{}, object interface{}, msgAndArgs ...interface{}) bool {
if h, ok := a.t.(tHelper); ok {
h.Helper()
}
return IsNotType(a.t, theType, object, msgAndArgs...)
}
// IsNotTypef asserts that the specified objects are not of the same type.
//
// a.IsNotTypef(&NotMyStruct{}, &MyStruct{}, "error message %s", "formatted")
func (a *Assertions) IsNotTypef(theType interface{}, object interface{}, msg string, args ...interface{}) bool {
if h, ok := a.t.(tHelper); ok {
h.Helper()
}
return IsNotTypef(a.t, theType, object, msg, args...)
}
// IsType asserts that the specified objects are of the same type.
//
// a.IsType(&MyStruct{}, &MyStruct{})
func (a *Assertions) IsType(expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool {
if h, ok := a.t.(tHelper); ok {
h.Helper()
@ -877,6 +913,8 @@ func (a *Assertions) IsType(expectedType interface{}, object interface{}, msgAnd
}
// IsTypef asserts that the specified objects are of the same type.
//
// a.IsTypef(&MyStruct{}, &MyStruct{}, "error message %s", "formatted")
func (a *Assertions) IsTypef(expectedType interface{}, object interface{}, msg string, args ...interface{}) bool {
if h, ok := a.t.(tHelper); ok {
h.Helper()
@ -1162,8 +1200,7 @@ func (a *Assertions) NotElementsMatchf(listA interface{}, listB interface{}, msg
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
// a slice or a channel with len == 0.
// NotEmpty asserts that the specified object is NOT [Empty].
//
// if a.NotEmpty(obj) {
// assert.Equal(t, "two", obj[1])
@ -1175,8 +1212,7 @@ func (a *Assertions) NotEmpty(object interface{}, msgAndArgs ...interface{}) boo
return NotEmpty(a.t, object, msgAndArgs...)
}
// 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.
// NotEmptyf asserts that the specified object is NOT [Empty].
//
// if a.NotEmptyf(obj, "error message %s", "formatted") {
// assert.Equal(t, "two", obj[1])
@ -1378,12 +1414,15 @@ func (a *Assertions) NotSamef(expected interface{}, actual interface{}, msg stri
return NotSamef(a.t, expected, actual, msg, args...)
}
// NotSubset asserts that the specified list(array, slice...) or map does NOT
// contain all elements given in the specified subset list(array, slice...) or
// map.
// NotSubset asserts that the list (array, slice, or map) does NOT contain all
// elements given in the subset (array, slice, or map).
// Map elements are key-value pairs unless compared with an array or slice where
// only the map key is evaluated.
//
// a.NotSubset([1, 3, 4], [1, 2])
// a.NotSubset({"x": 1, "y": 2}, {"z": 3})
// a.NotSubset([1, 3, 4], {1: "one", 2: "two"})
// a.NotSubset({"x": 1, "y": 2}, ["z"])
func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs ...interface{}) bool {
if h, ok := a.t.(tHelper); ok {
h.Helper()
@ -1391,12 +1430,15 @@ func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs
return NotSubset(a.t, list, subset, msgAndArgs...)
}
// NotSubsetf asserts that the specified list(array, slice...) or map does NOT
// contain all elements given in the specified subset list(array, slice...) or
// map.
// NotSubsetf asserts that the list (array, slice, or map) does NOT contain all
// elements given in the subset (array, slice, or map).
// Map elements are key-value pairs unless compared with an array or slice where
// only the map key is evaluated.
//
// a.NotSubsetf([1, 3, 4], [1, 2], "error message %s", "formatted")
// a.NotSubsetf({"x": 1, "y": 2}, {"z": 3}, "error message %s", "formatted")
// a.NotSubsetf([1, 3, 4], {1: "one", 2: "two"}, "error message %s", "formatted")
// a.NotSubsetf({"x": 1, "y": 2}, ["z"], "error message %s", "formatted")
func (a *Assertions) NotSubsetf(list interface{}, subset interface{}, msg string, args ...interface{}) bool {
if h, ok := a.t.(tHelper); ok {
h.Helper()
@ -1556,11 +1598,15 @@ func (a *Assertions) Samef(expected interface{}, actual interface{}, msg string,
return Samef(a.t, expected, actual, msg, args...)
}
// Subset asserts that the specified list(array, slice...) or map contains all
// elements given in the specified subset list(array, slice...) or map.
// Subset asserts that the list (array, slice, or map) contains all elements
// given in the subset (array, slice, or map).
// Map elements are key-value pairs unless compared with an array or slice where
// only the map key is evaluated.
//
// a.Subset([1, 2, 3], [1, 2])
// a.Subset({"x": 1, "y": 2}, {"x": 1})
// a.Subset([1, 2, 3], {1: "one", 2: "two"})
// a.Subset({"x": 1, "y": 2}, ["x"])
func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ...interface{}) bool {
if h, ok := a.t.(tHelper); ok {
h.Helper()
@ -1568,11 +1614,15 @@ func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ...
return Subset(a.t, list, subset, msgAndArgs...)
}
// Subsetf asserts that the specified list(array, slice...) or map contains all
// elements given in the specified subset list(array, slice...) or map.
// Subsetf asserts that the list (array, slice, or map) contains all elements
// given in the subset (array, slice, or map).
// Map elements are key-value pairs unless compared with an array or slice where
// only the map key is evaluated.
//
// a.Subsetf([1, 2, 3], [1, 2], "error message %s", "formatted")
// a.Subsetf({"x": 1, "y": 2}, {"x": 1}, "error message %s", "formatted")
// a.Subsetf([1, 2, 3], {1: "one", 2: "two"}, "error message %s", "formatted")
// a.Subsetf({"x": 1, "y": 2}, ["x"], "error message %s", "formatted")
func (a *Assertions) Subsetf(list interface{}, subset interface{}, msg string, args ...interface{}) bool {
if h, ok := a.t.(tHelper); ok {
h.Helper()

View File

@ -33,7 +33,7 @@ func isOrdered(t TestingT, object interface{}, allowedComparesResults []compareR
compareResult, isComparable := compare(prevValueInterface, valueInterface, firstValueKind)
if !isComparable {
return Fail(t, fmt.Sprintf("Can not compare type \"%s\" and \"%s\"", reflect.TypeOf(value), reflect.TypeOf(prevValue)), msgAndArgs...)
return Fail(t, fmt.Sprintf(`Can not compare type "%T" and "%T"`, value, prevValue), msgAndArgs...)
}
if !containsValue(allowedComparesResults, compareResult) {

View File

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

View File

@ -210,59 +210,77 @@ the problem actually occurred in calling code.*/
// of each stack frame leading from the current test to the assert call that
// failed.
func CallerInfo() []string {
var pc uintptr
var ok bool
var file string
var line int
var name string
const stackFrameBufferSize = 10
pcs := make([]uintptr, stackFrameBufferSize)
callers := []string{}
for i := 0; ; i++ {
pc, file, line, ok = runtime.Caller(i)
if !ok {
// The breaks below failed to terminate the loop, and we ran off the
// end of the call stack.
offset := 1
for {
n := runtime.Callers(offset, pcs)
if n == 0 {
break
}
// This is a huge edge case, but it will panic if this is the case, see #180
if file == "<autogenerated>" {
break
}
frames := runtime.CallersFrames(pcs[:n])
f := runtime.FuncForPC(pc)
if f == nil {
break
}
name = f.Name()
for {
frame, more := frames.Next()
pc = frame.PC
file = frame.File
line = frame.Line
// testing.tRunner is the standard library function that calls
// tests. Subtests are called directly by tRunner, without going through
// the Test/Benchmark/Example function that contains the t.Run calls, so
// with subtests we should break when we hit tRunner, without adding it
// to the list of callers.
if name == "testing.tRunner" {
break
}
// This is a huge edge case, but it will panic if this is the case, see #180
if file == "<autogenerated>" {
break
}
parts := strings.Split(file, "/")
if len(parts) > 1 {
filename := parts[len(parts)-1]
dir := parts[len(parts)-2]
if (dir != "assert" && dir != "mock" && dir != "require") || filename == "mock_test.go" {
callers = append(callers, fmt.Sprintf("%s:%d", file, line))
f := runtime.FuncForPC(pc)
if f == nil {
break
}
name = f.Name()
// testing.tRunner is the standard library function that calls
// tests. Subtests are called directly by tRunner, without going through
// the Test/Benchmark/Example function that contains the t.Run calls, so
// with subtests we should break when we hit tRunner, without adding it
// to the list of callers.
if name == "testing.tRunner" {
break
}
parts := strings.Split(file, "/")
if len(parts) > 1 {
filename := parts[len(parts)-1]
dir := parts[len(parts)-2]
if (dir != "assert" && dir != "mock" && dir != "require") || filename == "mock_test.go" {
callers = append(callers, fmt.Sprintf("%s:%d", file, line))
}
}
// Drop the package
dotPos := strings.LastIndexByte(name, '.')
name = name[dotPos+1:]
if isTest(name, "Test") ||
isTest(name, "Benchmark") ||
isTest(name, "Example") {
break
}
if !more {
break
}
}
// Drop the package
segments := strings.Split(name, ".")
name = segments[len(segments)-1]
if isTest(name, "Test") ||
isTest(name, "Benchmark") ||
isTest(name, "Example") {
break
}
// Next batch
offset += cap(pcs)
}
return callers
@ -437,17 +455,34 @@ func NotImplements(t TestingT, interfaceObject interface{}, object interface{},
return true
}
func isType(expectedType, object interface{}) bool {
return ObjectsAreEqual(reflect.TypeOf(object), reflect.TypeOf(expectedType))
}
// IsType asserts that the specified objects are of the same type.
func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool {
//
// assert.IsType(t, &MyStruct{}, &MyStruct{})
func IsType(t TestingT, expectedType, object interface{}, msgAndArgs ...interface{}) bool {
if isType(expectedType, object) {
return true
}
if h, ok := t.(tHelper); ok {
h.Helper()
}
return Fail(t, fmt.Sprintf("Object expected to be of type %T, but was %T", expectedType, object), msgAndArgs...)
}
if !ObjectsAreEqual(reflect.TypeOf(object), reflect.TypeOf(expectedType)) {
return Fail(t, fmt.Sprintf("Object expected to be of type %v, but was %v", reflect.TypeOf(expectedType), reflect.TypeOf(object)), msgAndArgs...)
// IsNotType asserts that the specified objects are not of the same type.
//
// assert.IsNotType(t, &NotMyStruct{}, &MyStruct{})
func IsNotType(t TestingT, theType, object interface{}, msgAndArgs ...interface{}) bool {
if !isType(theType, object) {
return true
}
return true
if h, ok := t.(tHelper); ok {
h.Helper()
}
return Fail(t, fmt.Sprintf("Object type expected to be different than %T", theType), msgAndArgs...)
}
// Equal asserts that two objects are equal.
@ -475,7 +510,6 @@ func Equal(t TestingT, expected, actual interface{}, msgAndArgs ...interface{})
}
return true
}
// validateEqualArgs checks whether provided arguments can be safely used in the
@ -510,8 +544,9 @@ func Same(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) b
if !same {
// both are pointers but not the same type & pointing to the same address
return Fail(t, fmt.Sprintf("Not same: \n"+
"expected: %p %#v\n"+
"actual : %p %#v", expected, expected, actual, actual), msgAndArgs...)
"expected: %p %#[1]v\n"+
"actual : %p %#[2]v",
expected, actual), msgAndArgs...)
}
return true
@ -530,14 +565,14 @@ func NotSame(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}
same, ok := samePointers(expected, actual)
if !ok {
//fails when the arguments are not pointers
// fails when the arguments are not pointers
return !(Fail(t, "Both arguments must be pointers", msgAndArgs...))
}
if same {
return Fail(t, fmt.Sprintf(
"Expected and actual point to the same object: %p %#v",
expected, expected), msgAndArgs...)
"Expected and actual point to the same object: %p %#[1]v",
expected), msgAndArgs...)
}
return true
}
@ -549,7 +584,7 @@ func NotSame(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}
func samePointers(first, second interface{}) (same bool, ok bool) {
firstPtr, secondPtr := reflect.ValueOf(first), reflect.ValueOf(second)
if firstPtr.Kind() != reflect.Ptr || secondPtr.Kind() != reflect.Ptr {
return false, false //not both are pointers
return false, false // not both are pointers
}
firstType, secondType := reflect.TypeOf(first), reflect.TypeOf(second)
@ -610,7 +645,6 @@ func EqualValues(t TestingT, expected, actual interface{}, msgAndArgs ...interfa
}
return true
}
// EqualExportedValues asserts that the types of two objects are equal and their public
@ -665,7 +699,6 @@ func Exactly(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}
}
return Equal(t, expected, actual, msgAndArgs...)
}
// NotNil asserts that the specified object is not nil.
@ -715,37 +748,45 @@ func Nil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
// isEmpty gets whether the specified object is considered empty or not.
func isEmpty(object interface{}) bool {
// get nil case out of the way
if object == nil {
return true
}
objValue := reflect.ValueOf(object)
switch objValue.Kind() {
// collection types are empty when they have no element
case reflect.Chan, reflect.Map, reflect.Slice:
return objValue.Len() == 0
// pointers are empty if nil or if the value they point to is empty
case reflect.Ptr:
if objValue.IsNil() {
return true
}
deref := objValue.Elem().Interface()
return isEmpty(deref)
// for all other types, compare against the zero value
// array types are empty when they match their zero-initialized state
default:
zero := reflect.Zero(objValue.Type())
return reflect.DeepEqual(object, zero.Interface())
}
return isEmptyValue(reflect.ValueOf(object))
}
// Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either
// a slice or a channel with len == 0.
// isEmptyValue gets whether the specified reflect.Value is considered empty or not.
func isEmptyValue(objValue reflect.Value) bool {
if objValue.IsZero() {
return true
}
// Special cases of non-zero values that we consider empty
switch objValue.Kind() {
// collection types are empty when they have no element
// Note: array types are empty when they match their zero-initialized state.
case reflect.Chan, reflect.Map, reflect.Slice:
return objValue.Len() == 0
// non-nil pointers are empty if the value they point to is empty
case reflect.Ptr:
return isEmptyValue(objValue.Elem())
}
return false
}
// Empty asserts that the given value is "empty".
//
// [Zero values] are "empty".
//
// Arrays are "empty" if every element is the zero value of the type (stricter than "empty").
//
// Slices, maps and channels with zero length are "empty".
//
// Pointer values are "empty" if the pointer is nil or if the pointed value is "empty".
//
// assert.Empty(t, obj)
//
// [Zero values]: https://go.dev/ref/spec#The_zero_value
func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
pass := isEmpty(object)
if !pass {
@ -756,11 +797,9 @@ func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
}
return pass
}
// 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.
// NotEmpty asserts that the specified object is NOT [Empty].
//
// if assert.NotEmpty(t, obj) {
// assert.Equal(t, "two", obj[1])
@ -775,7 +814,6 @@ func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
}
return pass
}
// getLen tries to get the length of an object.
@ -819,7 +857,6 @@ func True(t TestingT, value bool, msgAndArgs ...interface{}) bool {
}
return true
}
// False asserts that the specified value is false.
@ -834,7 +871,6 @@ func False(t TestingT, value bool, msgAndArgs ...interface{}) bool {
}
return true
}
// NotEqual asserts that the specified values are NOT equal.
@ -857,7 +893,6 @@ func NotEqual(t TestingT, expected, actual interface{}, msgAndArgs ...interface{
}
return true
}
// NotEqualValues asserts that two objects are not equal even when converted to the same type
@ -880,7 +915,6 @@ func NotEqualValues(t TestingT, expected, actual interface{}, msgAndArgs ...inte
// return (true, false) if element was not found.
// return (true, true) if element was found.
func containsElement(list interface{}, element interface{}) (ok, found bool) {
listValue := reflect.ValueOf(list)
listType := reflect.TypeOf(list)
if listType == nil {
@ -915,7 +949,6 @@ func containsElement(list interface{}, element interface{}) (ok, found bool) {
}
}
return true, false
}
// Contains asserts that the specified string, list(array, slice...) or map contains the
@ -938,7 +971,6 @@ func Contains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bo
}
return true
}
// NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the
@ -961,14 +993,17 @@ func NotContains(t TestingT, s, contains interface{}, msgAndArgs ...interface{})
}
return true
}
// Subset asserts that the specified list(array, slice...) or map contains all
// elements given in the specified subset list(array, slice...) or map.
// Subset asserts that the list (array, slice, or map) contains all elements
// given in the subset (array, slice, or map).
// Map elements are key-value pairs unless compared with an array or slice where
// only the map key is evaluated.
//
// assert.Subset(t, [1, 2, 3], [1, 2])
// assert.Subset(t, {"x": 1, "y": 2}, {"x": 1})
// assert.Subset(t, [1, 2, 3], {1: "one", 2: "two"})
// assert.Subset(t, {"x": 1, "y": 2}, ["x"])
func Subset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok bool) {
if h, ok := t.(tHelper); ok {
h.Helper()
@ -983,7 +1018,7 @@ func Subset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok
}
subsetKind := reflect.TypeOf(subset).Kind()
if subsetKind != reflect.Array && subsetKind != reflect.Slice && listKind != reflect.Map {
if subsetKind != reflect.Array && subsetKind != reflect.Slice && subsetKind != reflect.Map {
return Fail(t, fmt.Sprintf("%q has an unsupported type %s", subset, subsetKind), msgAndArgs...)
}
@ -1007,6 +1042,13 @@ func Subset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok
}
subsetList := reflect.ValueOf(subset)
if subsetKind == reflect.Map {
keys := make([]interface{}, subsetList.Len())
for idx, key := range subsetList.MapKeys() {
keys[idx] = key.Interface()
}
subsetList = reflect.ValueOf(keys)
}
for i := 0; i < subsetList.Len(); i++ {
element := subsetList.Index(i).Interface()
ok, found := containsElement(list, element)
@ -1021,12 +1063,15 @@ func Subset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok
return true
}
// NotSubset asserts that the specified list(array, slice...) or map does NOT
// contain all elements given in the specified subset list(array, slice...) or
// map.
// NotSubset asserts that the list (array, slice, or map) does NOT contain all
// elements given in the subset (array, slice, or map).
// Map elements are key-value pairs unless compared with an array or slice where
// only the map key is evaluated.
//
// assert.NotSubset(t, [1, 3, 4], [1, 2])
// assert.NotSubset(t, {"x": 1, "y": 2}, {"z": 3})
// assert.NotSubset(t, [1, 3, 4], {1: "one", 2: "two"})
// assert.NotSubset(t, {"x": 1, "y": 2}, ["z"])
func NotSubset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok bool) {
if h, ok := t.(tHelper); ok {
h.Helper()
@ -1041,7 +1086,7 @@ func NotSubset(t TestingT, list, subset interface{}, msgAndArgs ...interface{})
}
subsetKind := reflect.TypeOf(subset).Kind()
if subsetKind != reflect.Array && subsetKind != reflect.Slice && listKind != reflect.Map {
if subsetKind != reflect.Array && subsetKind != reflect.Slice && subsetKind != reflect.Map {
return Fail(t, fmt.Sprintf("%q has an unsupported type %s", subset, subsetKind), msgAndArgs...)
}
@ -1065,11 +1110,18 @@ func NotSubset(t TestingT, list, subset interface{}, msgAndArgs ...interface{})
}
subsetList := reflect.ValueOf(subset)
if subsetKind == reflect.Map {
keys := make([]interface{}, subsetList.Len())
for idx, key := range subsetList.MapKeys() {
keys[idx] = key.Interface()
}
subsetList = reflect.ValueOf(keys)
}
for i := 0; i < subsetList.Len(); i++ {
element := subsetList.Index(i).Interface()
ok, found := containsElement(list, element)
if !ok {
return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", list), msgAndArgs...)
return Fail(t, fmt.Sprintf("%q could not be applied builtin len()", list), msgAndArgs...)
}
if !found {
return true
@ -1591,10 +1643,8 @@ func NoError(t TestingT, err error, msgAndArgs ...interface{}) bool {
// Error asserts that a function returned an error (i.e. not `nil`).
//
// actualObj, err := SomeFunction()
// if assert.Error(t, err) {
// assert.Equal(t, expectedError, err)
// }
// actualObj, err := SomeFunction()
// assert.Error(t, err)
func Error(t TestingT, err error, msgAndArgs ...interface{}) bool {
if err == nil {
if h, ok := t.(tHelper); ok {
@ -1667,7 +1717,6 @@ func matchRegexp(rx interface{}, str interface{}) bool {
default:
return r.MatchString(fmt.Sprint(v))
}
}
// Regexp asserts that a specified regexp matches a string.
@ -1703,7 +1752,6 @@ func NotRegexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interf
}
return !match
}
// Zero asserts that i is the zero value for its type.
@ -1814,6 +1862,11 @@ func JSONEq(t TestingT, expected string, actual string, msgAndArgs ...interface{
return Fail(t, fmt.Sprintf("Expected value ('%s') is not valid json.\nJSON parsing error: '%s'", expected, err.Error()), msgAndArgs...)
}
// Shortcut if same bytes
if actual == expected {
return true
}
if err := json.Unmarshal([]byte(actual), &actualJSONAsInterface); err != nil {
return Fail(t, fmt.Sprintf("Input ('%s') needs to be valid json.\nJSON parsing error: '%s'", actual, err.Error()), msgAndArgs...)
}
@ -1832,6 +1885,11 @@ func YAMLEq(t TestingT, expected string, actual string, msgAndArgs ...interface{
return Fail(t, fmt.Sprintf("Expected value ('%s') is not valid yaml.\nYAML parsing error: '%s'", expected, err.Error()), msgAndArgs...)
}
// Shortcut if same bytes
if actual == expected {
return true
}
if err := yaml.Unmarshal([]byte(actual), &actualYAMLAsInterface); err != nil {
return Fail(t, fmt.Sprintf("Input ('%s') needs to be valid yaml.\nYAML error: '%s'", actual, err.Error()), msgAndArgs...)
}
@ -1933,6 +1991,7 @@ func Eventually(t TestingT, condition func() bool, waitFor time.Duration, tick t
}
ch := make(chan bool, 1)
checkCond := func() { ch <- condition() }
timer := time.NewTimer(waitFor)
defer timer.Stop()
@ -1940,18 +1999,23 @@ func Eventually(t TestingT, condition func() bool, waitFor time.Duration, tick t
ticker := time.NewTicker(tick)
defer ticker.Stop()
for tick := ticker.C; ; {
var tickC <-chan time.Time
// Check the condition once first on the initial call.
go checkCond()
for {
select {
case <-timer.C:
return Fail(t, "Condition never satisfied", msgAndArgs...)
case <-tick:
tick = nil
go func() { ch <- condition() }()
case <-tickC:
tickC = nil
go checkCond()
case v := <-ch:
if v {
return true
}
tick = ticker.C
tickC = ticker.C
}
}
}
@ -1964,6 +2028,9 @@ type CollectT struct {
errors []error
}
// Helper is like [testing.T.Helper] but does nothing.
func (CollectT) Helper() {}
// Errorf collects the error.
func (c *CollectT) Errorf(format string, args ...interface{}) {
c.errors = append(c.errors, fmt.Errorf(format, args...))
@ -2021,35 +2088,42 @@ func EventuallyWithT(t TestingT, condition func(collect *CollectT), waitFor time
var lastFinishedTickErrs []error
ch := make(chan *CollectT, 1)
checkCond := func() {
collect := new(CollectT)
defer func() {
ch <- collect
}()
condition(collect)
}
timer := time.NewTimer(waitFor)
defer timer.Stop()
ticker := time.NewTicker(tick)
defer ticker.Stop()
for tick := ticker.C; ; {
var tickC <-chan time.Time
// Check the condition once first on the initial call.
go checkCond()
for {
select {
case <-timer.C:
for _, err := range lastFinishedTickErrs {
t.Errorf("%v", err)
}
return Fail(t, "Condition never satisfied", msgAndArgs...)
case <-tick:
tick = nil
go func() {
collect := new(CollectT)
defer func() {
ch <- collect
}()
condition(collect)
}()
case <-tickC:
tickC = nil
go checkCond()
case collect := <-ch:
if !collect.failed() {
return true
}
// Keep the errors from the last ended condition, so that they can be copied to t if timeout is reached.
lastFinishedTickErrs = collect.errors
tick = ticker.C
tickC = ticker.C
}
}
}
@ -2064,6 +2138,7 @@ func Never(t TestingT, condition func() bool, waitFor time.Duration, tick time.D
}
ch := make(chan bool, 1)
checkCond := func() { ch <- condition() }
timer := time.NewTimer(waitFor)
defer timer.Stop()
@ -2071,18 +2146,23 @@ func Never(t TestingT, condition func() bool, waitFor time.Duration, tick time.D
ticker := time.NewTicker(tick)
defer ticker.Stop()
for tick := ticker.C; ; {
var tickC <-chan time.Time
// Check the condition once first on the initial call.
go checkCond()
for {
select {
case <-timer.C:
return true
case <-tick:
tick = nil
go func() { ch <- condition() }()
case <-tickC:
tickC = nil
go checkCond()
case v := <-ch:
if v {
return Fail(t, "Condition satisfied", msgAndArgs...)
}
tick = ticker.C
tickC = ticker.C
}
}
}
@ -2100,9 +2180,12 @@ func ErrorIs(t TestingT, err, target error, msgAndArgs ...interface{}) bool {
var expectedText string
if target != nil {
expectedText = target.Error()
if err == nil {
return Fail(t, fmt.Sprintf("Expected error with %q in chain but got nil.", expectedText), msgAndArgs...)
}
}
chain := buildErrorChainString(err)
chain := buildErrorChainString(err, false)
return Fail(t, fmt.Sprintf("Target error should be in err chain:\n"+
"expected: %q\n"+
@ -2125,7 +2208,7 @@ func NotErrorIs(t TestingT, err, target error, msgAndArgs ...interface{}) bool {
expectedText = target.Error()
}
chain := buildErrorChainString(err)
chain := buildErrorChainString(err, false)
return Fail(t, fmt.Sprintf("Target error should not be in err chain:\n"+
"found: %q\n"+
@ -2143,11 +2226,17 @@ func ErrorAs(t TestingT, err error, target interface{}, msgAndArgs ...interface{
return true
}
chain := buildErrorChainString(err)
expectedType := reflect.TypeOf(target).Elem().String()
if err == nil {
return Fail(t, fmt.Sprintf("An error is expected but got nil.\n"+
"expected: %s", expectedType), msgAndArgs...)
}
chain := buildErrorChainString(err, true)
return Fail(t, fmt.Sprintf("Should be in error chain:\n"+
"expected: %q\n"+
"in chain: %s", target, chain,
"expected: %s\n"+
"in chain: %s", expectedType, chain,
), msgAndArgs...)
}
@ -2161,24 +2250,46 @@ func NotErrorAs(t TestingT, err error, target interface{}, msgAndArgs ...interfa
return true
}
chain := buildErrorChainString(err)
chain := buildErrorChainString(err, true)
return Fail(t, fmt.Sprintf("Target error should not be in err chain:\n"+
"found: %q\n"+
"in chain: %s", target, chain,
"found: %s\n"+
"in chain: %s", reflect.TypeOf(target).Elem().String(), chain,
), msgAndArgs...)
}
func buildErrorChainString(err error) string {
func unwrapAll(err error) (errs []error) {
errs = append(errs, err)
switch x := err.(type) {
case interface{ Unwrap() error }:
err = x.Unwrap()
if err == nil {
return
}
errs = append(errs, unwrapAll(err)...)
case interface{ Unwrap() []error }:
for _, err := range x.Unwrap() {
errs = append(errs, unwrapAll(err)...)
}
}
return
}
func buildErrorChainString(err error, withType bool) string {
if err == nil {
return ""
}
e := errors.Unwrap(err)
chain := fmt.Sprintf("%q", err.Error())
for e != nil {
chain += fmt.Sprintf("\n\t%q", e.Error())
e = errors.Unwrap(e)
var chain string
errs := unwrapAll(err)
for i := range errs {
if i != 0 {
chain += "\n\t"
}
chain += fmt.Sprintf("%q", errs[i].Error())
if withType {
chain += fmt.Sprintf(" (%T)", errs[i])
}
}
return chain
}

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,9 @@
// Package assert provides a set of comprehensive testing tools for use with the normal Go testing system.
//
// # Note
//
// All functions in this package return a bool value indicating whether the assertion has passed.
//
// # Example Usage
//
// The following is a complete example using assert in a standard test function:

View File

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

View File

@ -138,7 +138,7 @@ func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method, url string,
contains := strings.Contains(body, fmt.Sprint(str))
if !contains {
Fail(t, fmt.Sprintf("Expected response body for \"%s\" to contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body), msgAndArgs...)
Fail(t, fmt.Sprintf("Expected response body for %q to contain %q but found %q", url+"?"+values.Encode(), str, body), msgAndArgs...)
}
return contains
@ -158,7 +158,7 @@ func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, method, url strin
contains := strings.Contains(body, fmt.Sprint(str))
if contains {
Fail(t, fmt.Sprintf("Expected response body for \"%s\" to NOT contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body), msgAndArgs...)
Fail(t, fmt.Sprintf("Expected response body for %q to NOT contain %q but found %q", url+"?"+values.Encode(), str, body), msgAndArgs...)
}
return !contains

View File

@ -31,6 +31,8 @@ func httpStatusCode(w http.ResponseWriter, r *http.Request) {
}
func TestHTTPSuccess(t *testing.T) {
t.Parallel()
assert := New(t)
mockT1 := new(testing.T)
@ -59,6 +61,8 @@ func TestHTTPSuccess(t *testing.T) {
}
func TestHTTPRedirect(t *testing.T) {
t.Parallel()
assert := New(t)
mockT1 := new(mockTestingT)
@ -83,6 +87,8 @@ func TestHTTPRedirect(t *testing.T) {
}
func TestHTTPError(t *testing.T) {
t.Parallel()
assert := New(t)
mockT1 := new(testing.T)
@ -107,6 +113,8 @@ func TestHTTPError(t *testing.T) {
}
func TestHTTPStatusCode(t *testing.T) {
t.Parallel()
assert := New(t)
mockT1 := new(testing.T)
@ -131,6 +139,8 @@ func TestHTTPStatusCode(t *testing.T) {
}
func TestHTTPStatusesWrapper(t *testing.T) {
t.Parallel()
assert := New(t)
mockAssert := New(new(testing.T))
@ -153,6 +163,8 @@ func httpHelloName(w http.ResponseWriter, r *http.Request) {
}
func TestHTTPRequestWithNoParams(t *testing.T) {
t.Parallel()
var got *http.Request
handler := func(w http.ResponseWriter, r *http.Request) {
got = r
@ -166,6 +178,8 @@ func TestHTTPRequestWithNoParams(t *testing.T) {
}
func TestHTTPRequestWithParams(t *testing.T) {
t.Parallel()
var got *http.Request
handler := func(w http.ResponseWriter, r *http.Request) {
got = r
@ -182,6 +196,8 @@ func TestHTTPRequestWithParams(t *testing.T) {
}
func TestHttpBody(t *testing.T) {
t.Parallel()
assert := New(t)
mockT := new(mockTestingT)
@ -201,6 +217,8 @@ func TestHttpBody(t *testing.T) {
}
func TestHttpBodyWrappers(t *testing.T) {
t.Parallel()
assert := New(t)
mockAssert := New(new(testing.T))

View File

@ -1,5 +1,4 @@
//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.
//

View File

@ -1,5 +1,4 @@
//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.
//

View File

@ -1,5 +1,4 @@
//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.
//

12
doc.go
View File

@ -1,15 +1,17 @@
// Package testify is a set of packages that provide many tools for testifying that your code will behave as you intend.
// Module 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 [github.com/stretchr/testify/assert] package provides a comprehensive set of assertion functions that tie in to [the Go testing system].
// The [github.com/stretchr/testify/require] package provides the same assertions but as fatal checks.
//
// The mock package provides a system by which it is possible to mock your objects and verify calls are happening as expected.
// The [github.com/stretchr/testify/mock] package provides a system by which it is possible to mock your objects and verify calls are happening as expected.
//
// The 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 [github.com/stretchr/testify/suite] package provides a basic structure for using structs as testing suites, and methods on those structs as tests. It includes setup/teardown functionality in the way of interfaces.
//
// A [golangci-lint] compatible linter for testify is available called [testifylint].
//
// [the Go testing system]: https://go.dev/doc/code#Testing
// [golangci-lint]: https://golangci-lint.run/
// [testifylint]: https://github.com/Antonboom/testifylint
package testify

4
go.mod
View File

@ -7,10 +7,10 @@ go 1.17
require (
github.com/davecgh/go-spew v1.1.1
github.com/pmezard/go-difflib v1.0.0
github.com/stretchr/objx v0.5.2
github.com/stretchr/objx v0.5.2 // To avoid a cycle the version of testify used by objx should be excluded below
gopkg.in/yaml.v3 v3.0.1
)
// Break dependency cycle with objx.
// See https://github.com/stretchr/objx/pull/140
exclude github.com/stretchr/testify v1.8.2
exclude github.com/stretchr/testify v1.8.4

8
go.sum
View File

@ -1,18 +1,10 @@
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.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/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View File

@ -208,9 +208,16 @@ func (c *Call) On(methodName string, arguments ...interface{}) *Call {
return c.Parent.On(methodName, arguments...)
}
// Unset removes a mock handler from being called.
// Unset removes all mock handlers that satisfy the call instance arguments from being
// called. Only supported on call instances with static input arguments.
//
// test.On("func", mock.Anything).Unset()
// 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
@ -331,7 +338,10 @@ func (m *Mock) TestData() objx.Map {
Setting expectations
*/
// Test sets the test struct variable of the mock object
// Test sets the [TestingT] on which errors will be reported, otherwise errors
// will cause a panic.
// Test should not be called on an object that is going to be used in a
// goroutine other than the one running the test function.
func (m *Mock) Test(t TestingT) {
m.mutex.Lock()
defer m.mutex.Unlock()
@ -494,7 +504,7 @@ func (m *Mock) MethodCalled(methodName string, arguments ...interface{}) Argumen
// expected call found, but it has already been called with repeatable times
if call != nil {
m.mutex.Unlock()
m.fail("\nassert: mock: The method has been called over %d times.\n\tEither do one more Mock.On(\"%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())
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())
}
// we have to fail here - because we don't know what to do
// as the return arguments. This is because:
@ -514,7 +524,7 @@ func (m *Mock) MethodCalled(methodName string, arguments ...interface{}) Argumen
assert.CallerInfo(),
)
} else {
m.fail("\nassert: mock: I don't know what to return because the method call was unexpected.\n\tEither do Mock.On(\"%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())
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())
}
}
@ -661,7 +671,7 @@ func (m *Mock) AssertNumberOfCalls(t TestingT, methodName string, expectedCalls
actualCalls++
}
}
return assert.Equal(t, expectedCalls, actualCalls, fmt.Sprintf("Expected number of calls (%d) does not match the actual number of calls (%d).", expectedCalls, actualCalls))
return assert.Equal(t, expectedCalls, actualCalls, fmt.Sprintf("Expected number of calls (%d) of method %s does not match the actual number of calls (%d).", expectedCalls, methodName, actualCalls))
}
// AssertCalled asserts that the method was called.
@ -938,6 +948,8 @@ func (args Arguments) Is(objects ...interface{}) bool {
return true
}
type outputRenderer func() string
// Diff gets a string describing the differences between the arguments
// and the specified objects.
//
@ -945,7 +957,7 @@ func (args Arguments) Is(objects ...interface{}) bool {
func (args Arguments) Diff(objects []interface{}) (string, int) {
// TODO: could return string as error and nil for No difference
output := "\n"
var outputBuilder strings.Builder
var differences int
maxArgCount := len(args)
@ -953,24 +965,35 @@ func (args Arguments) Diff(objects []interface{}) (string, int) {
maxArgCount = len(objects)
}
outputRenderers := []outputRenderer{}
for i := 0; i < maxArgCount; i++ {
i := i
var actual, expected interface{}
var actualFmt, expectedFmt string
var actualFmt, expectedFmt func() string
if len(objects) <= i {
actual = "(Missing)"
actualFmt = "(Missing)"
actualFmt = func() string {
return "(Missing)"
}
} else {
actual = objects[i]
actualFmt = fmt.Sprintf("(%[1]T=%[1]v)", actual)
actualFmt = func() string {
return fmt.Sprintf("(%[1]T=%[1]v)", actual)
}
}
if len(args) <= i {
expected = "(Missing)"
expectedFmt = "(Missing)"
expectedFmt = func() string {
return "(Missing)"
}
} else {
expected = args[i]
expectedFmt = fmt.Sprintf("(%[1]T=%[1]v)", expected)
expectedFmt = func() string {
return fmt.Sprintf("(%[1]T=%[1]v)", expected)
}
}
if matcher, ok := expected.(argumentMatcher); ok {
@ -978,16 +1001,22 @@ func (args Arguments) Diff(objects []interface{}) (string, int) {
func() {
defer func() {
if r := recover(); r != nil {
actualFmt = fmt.Sprintf("panic in argument matcher: %v", r)
actualFmt = func() string {
return 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)
outputRenderers = append(outputRenderers, func() string {
return fmt.Sprintf("\t%d: PASS: %s matched by %s\n", i, actualFmt(), matcher)
})
} else {
differences++
output = fmt.Sprintf("%s\t%d: FAIL: %s not matched by %s\n", output, i, actualFmt, matcher)
outputRenderers = append(outputRenderers, func() string {
return fmt.Sprintf("\t%d: FAIL: %s not matched by %s\n", i, actualFmt(), matcher)
})
}
} else {
switch expected := expected.(type) {
@ -996,13 +1025,17 @@ func (args Arguments) Diff(objects []interface{}) (string, int) {
if reflect.TypeOf(actual).Name() != string(expected) && reflect.TypeOf(actual).String() != string(expected) {
// not match
differences++
output = fmt.Sprintf("%s\t%d: FAIL: type %s != type %s - %s\n", output, i, expected, reflect.TypeOf(actual).Name(), actualFmt)
outputRenderers = append(outputRenderers, func() string {
return fmt.Sprintf("\t%d: FAIL: type %s != type %s - %s\n", i, expected, reflect.TypeOf(actual).Name(), actualFmt())
})
}
case *IsTypeArgument:
actualT := reflect.TypeOf(actual)
if actualT != expected.t {
differences++
output = fmt.Sprintf("%s\t%d: FAIL: type %s != type %s - %s\n", output, i, expected.t.Name(), actualT.Name(), actualFmt)
outputRenderers = append(outputRenderers, func() string {
return fmt.Sprintf("\t%d: FAIL: type %s != type %s - %s\n", i, expected.t.Name(), actualT.Name(), actualFmt())
})
}
case *FunctionalOptionsArgument:
var name string
@ -1013,26 +1046,36 @@ func (args Arguments) Diff(objects []interface{}) (string, int) {
const tName = "[]interface{}"
if name != reflect.TypeOf(actual).String() && len(expected.values) != 0 {
differences++
output = fmt.Sprintf("%s\t%d: FAIL: type %s != type %s - %s\n", output, i, tName, reflect.TypeOf(actual).Name(), actualFmt)
outputRenderers = append(outputRenderers, func() string {
return fmt.Sprintf("\t%d: FAIL: type %s != type %s - %s\n", i, tName, reflect.TypeOf(actual).Name(), actualFmt())
})
} else {
if ef, af := assertOpts(expected.values, actual); ef == "" && af == "" {
// match
output = fmt.Sprintf("%s\t%d: PASS: %s == %s\n", output, i, tName, tName)
outputRenderers = append(outputRenderers, func() string {
return fmt.Sprintf("\t%d: PASS: %s == %s\n", i, tName, tName)
})
} else {
// not match
differences++
output = fmt.Sprintf("%s\t%d: FAIL: %s != %s\n", output, i, af, ef)
outputRenderers = append(outputRenderers, func() string {
return fmt.Sprintf("\t%d: FAIL: %s != %s\n", i, af, ef)
})
}
}
default:
if assert.ObjectsAreEqual(expected, Anything) || assert.ObjectsAreEqual(actual, Anything) || assert.ObjectsAreEqual(actual, expected) {
// match
output = fmt.Sprintf("%s\t%d: PASS: %s == %s\n", output, i, actualFmt, expectedFmt)
outputRenderers = append(outputRenderers, func() string {
return fmt.Sprintf("\t%d: PASS: %s == %s\n", i, actualFmt(), expectedFmt())
})
} else {
// not match
differences++
output = fmt.Sprintf("%s\t%d: FAIL: %s != %s\n", output, i, actualFmt, expectedFmt)
outputRenderers = append(outputRenderers, func() string {
return fmt.Sprintf("\t%d: FAIL: %s != %s\n", i, actualFmt(), expectedFmt())
})
}
}
}
@ -1043,7 +1086,12 @@ func (args Arguments) Diff(objects []interface{}) (string, int) {
return "No differences.", differences
}
return output, differences
outputBuilder.WriteString("\n")
for _, r := range outputRenderers {
outputBuilder.WriteString(r())
}
return outputBuilder.String(), differences
}
// Assert compares the arguments with the specified objects and fails if

View File

@ -132,6 +132,9 @@ type MockTestingT struct {
logfCount, errorfCount, failNowCount int
}
// Helper is like [testing.T.Helper] but does nothing.
func (MockTestingT) Helper() {}
const mockTestingTFailNowCalled = "FailNow was called"
func (m *MockTestingT) Logf(string, ...interface{}) {
@ -160,6 +163,7 @@ func (m *MockTestingT) FailNow() {
*/
func Test_Mock_TestData(t *testing.T) {
t.Parallel()
var mockedService = new(TestExampleImplementation)
@ -171,6 +175,7 @@ func Test_Mock_TestData(t *testing.T) {
}
func Test_Mock_On(t *testing.T) {
t.Parallel()
// make a test impl object
var mockedService = new(TestExampleImplementation)
@ -181,6 +186,8 @@ func Test_Mock_On(t *testing.T) {
}
func Test_Mock_Chained_On(t *testing.T) {
t.Parallel()
// make a test impl object
var mockedService = new(TestExampleImplementation)
@ -212,6 +219,7 @@ func Test_Mock_Chained_On(t *testing.T) {
}
func Test_Mock_On_WithArgs(t *testing.T) {
t.Parallel()
// make a test impl object
var mockedService = new(TestExampleImplementation)
@ -224,6 +232,7 @@ func Test_Mock_On_WithArgs(t *testing.T) {
}
func Test_Mock_On_WithFuncArg(t *testing.T) {
t.Parallel()
// make a test impl object
var mockedService = new(TestExampleImplementation)
@ -245,6 +254,8 @@ func Test_Mock_On_WithFuncArg(t *testing.T) {
}
func Test_Mock_On_WithIntArgMatcher(t *testing.T) {
t.Parallel()
var mockedService TestExampleImplementation
mockedService.On("TheExampleMethod",
@ -268,6 +279,8 @@ func Test_Mock_On_WithIntArgMatcher(t *testing.T) {
}
func Test_Mock_On_WithArgMatcherThatPanics(t *testing.T) {
t.Parallel()
var mockedService TestExampleImplementation
mockedService.On("TheExampleMethod2", MatchedBy(func(_ interface{}) bool {
@ -294,6 +307,8 @@ func Test_Mock_On_WithArgMatcherThatPanics(t *testing.T) {
}
func TestMock_WithTest(t *testing.T) {
t.Parallel()
var (
mockedService TestExampleImplementation
mockedTest MockTestingT
@ -322,6 +337,8 @@ func TestMock_WithTest(t *testing.T) {
}
func Test_Mock_On_WithPtrArgMatcher(t *testing.T) {
t.Parallel()
var mockedService TestExampleImplementation
mockedService.On("TheExampleMethod3",
@ -342,6 +359,8 @@ func Test_Mock_On_WithPtrArgMatcher(t *testing.T) {
}
func Test_Mock_On_WithFuncArgMatcher(t *testing.T) {
t.Parallel()
var mockedService TestExampleImplementation
fixture1, fixture2 := errors.New("fixture1"), errors.New("fixture2")
@ -366,6 +385,8 @@ func Test_Mock_On_WithFuncArgMatcher(t *testing.T) {
}
func Test_Mock_On_WithInterfaceArgMatcher(t *testing.T) {
t.Parallel()
var mockedService TestExampleImplementation
mockedService.On("TheExampleMethod4",
@ -376,6 +397,8 @@ func Test_Mock_On_WithInterfaceArgMatcher(t *testing.T) {
}
func Test_Mock_On_WithChannelArgMatcher(t *testing.T) {
t.Parallel()
var mockedService TestExampleImplementation
mockedService.On("TheExampleMethod5",
@ -386,6 +409,8 @@ func Test_Mock_On_WithChannelArgMatcher(t *testing.T) {
}
func Test_Mock_On_WithMapArgMatcher(t *testing.T) {
t.Parallel()
var mockedService TestExampleImplementation
mockedService.On("TheExampleMethod6",
@ -396,6 +421,8 @@ func Test_Mock_On_WithMapArgMatcher(t *testing.T) {
}
func Test_Mock_On_WithSliceArgMatcher(t *testing.T) {
t.Parallel()
var mockedService TestExampleImplementation
mockedService.On("TheExampleMethod7",
@ -406,6 +433,7 @@ func Test_Mock_On_WithSliceArgMatcher(t *testing.T) {
}
func Test_Mock_On_WithVariadicFunc(t *testing.T) {
t.Parallel()
// make a test impl object
var mockedService = new(TestExampleImplementation)
@ -428,6 +456,7 @@ func Test_Mock_On_WithVariadicFunc(t *testing.T) {
}
func Test_Mock_On_WithMixedVariadicFunc(t *testing.T) {
t.Parallel()
// make a test impl object
var mockedService = new(TestExampleImplementation)
@ -451,6 +480,7 @@ func Test_Mock_On_WithMixedVariadicFunc(t *testing.T) {
}
func Test_Mock_On_WithVariadicFuncWithInterface(t *testing.T) {
t.Parallel()
// make a test impl object
var mockedService = new(TestExampleImplementation)
@ -472,6 +502,7 @@ func Test_Mock_On_WithVariadicFuncWithInterface(t *testing.T) {
}
func Test_Mock_On_WithVariadicFuncWithEmptyInterfaceArray(t *testing.T) {
t.Parallel()
// make a test impl object
var mockedService = new(TestExampleImplementation)
@ -495,6 +526,8 @@ func Test_Mock_On_WithVariadicFuncWithEmptyInterfaceArray(t *testing.T) {
}
func Test_Mock_On_WithFuncPanics(t *testing.T) {
t.Parallel()
// make a test impl object
var mockedService = new(TestExampleImplementation)
@ -504,6 +537,7 @@ func Test_Mock_On_WithFuncPanics(t *testing.T) {
}
func Test_Mock_On_WithFuncTypeArg(t *testing.T) {
t.Parallel()
// make a test impl object
var mockedService = new(TestExampleImplementation)
@ -523,6 +557,8 @@ func Test_Mock_On_WithFuncTypeArg(t *testing.T) {
}
func Test_Mock_Unset(t *testing.T) {
t.Parallel()
// make a test impl object
var mockedService = new(TestExampleImplementation)
@ -551,6 +587,8 @@ func Test_Mock_Unset(t *testing.T) {
// 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) {
t.Parallel()
// make a test impl object
var mockedService = new(TestExampleImplementation)
@ -585,6 +623,8 @@ func Test_Mock_Chained_UnsetOnlyUnsetsLastCall(t *testing.T) {
}
func Test_Mock_UnsetIfAlreadyUnsetFails(t *testing.T) {
t.Parallel()
// make a test impl object
var mockedService = new(TestExampleImplementation)
@ -604,6 +644,8 @@ func Test_Mock_UnsetIfAlreadyUnsetFails(t *testing.T) {
}
func Test_Mock_UnsetByOnMethodSpec(t *testing.T) {
t.Parallel()
// make a test impl object
var mockedService = new(TestExampleImplementation)
@ -625,6 +667,8 @@ func Test_Mock_UnsetByOnMethodSpec(t *testing.T) {
}
func Test_Mock_UnsetByOnMethodSpecAmongOthers(t *testing.T) {
t.Parallel()
// make a test impl object
var mockedService = new(TestExampleImplementation)
@ -667,6 +711,8 @@ func Test_Mock_UnsetByOnMethodSpecAmongOthers(t *testing.T) {
}
func Test_Mock_Unset_WithFuncPanics(t *testing.T) {
t.Parallel()
// make a test impl object
var mockedService = new(TestExampleImplementation)
mock1 := mockedService.On("TheExampleMethod", 1)
@ -678,6 +724,7 @@ func Test_Mock_Unset_WithFuncPanics(t *testing.T) {
}
func Test_Mock_Return(t *testing.T) {
t.Parallel()
// make a test impl object
var mockedService = new(TestExampleImplementation)
@ -702,6 +749,7 @@ func Test_Mock_Return(t *testing.T) {
}
func Test_Mock_Panic(t *testing.T) {
t.Parallel()
// make a test impl object
var mockedService = new(TestExampleImplementation)
@ -725,6 +773,7 @@ func Test_Mock_Panic(t *testing.T) {
}
func Test_Mock_Return_WaitUntil(t *testing.T) {
t.Parallel()
// make a test impl object
var mockedService = new(TestExampleImplementation)
@ -752,6 +801,7 @@ func Test_Mock_Return_WaitUntil(t *testing.T) {
}
func Test_Mock_Return_After(t *testing.T) {
t.Parallel()
// make a test impl object
var mockedService = new(TestExampleImplementation)
@ -778,6 +828,7 @@ func Test_Mock_Return_After(t *testing.T) {
}
func Test_Mock_Return_Run(t *testing.T) {
t.Parallel()
// make a test impl object
var mockedService = new(TestExampleImplementation)
@ -810,6 +861,8 @@ func Test_Mock_Return_Run(t *testing.T) {
}
func Test_Mock_Return_Run_Out_Of_Order(t *testing.T) {
t.Parallel()
// make a test impl object
var mockedService = new(TestExampleImplementation)
f := func(args Arguments) {
@ -835,6 +888,7 @@ func Test_Mock_Return_Run_Out_Of_Order(t *testing.T) {
}
func Test_Mock_Return_Once(t *testing.T) {
t.Parallel()
// make a test impl object
var mockedService = new(TestExampleImplementation)
@ -859,6 +913,7 @@ func Test_Mock_Return_Once(t *testing.T) {
}
func Test_Mock_Return_Twice(t *testing.T) {
t.Parallel()
// make a test impl object
var mockedService = new(TestExampleImplementation)
@ -884,6 +939,7 @@ func Test_Mock_Return_Twice(t *testing.T) {
}
func Test_Mock_Return_Times(t *testing.T) {
t.Parallel()
// make a test impl object
var mockedService = new(TestExampleImplementation)
@ -909,6 +965,7 @@ func Test_Mock_Return_Times(t *testing.T) {
}
func Test_Mock_Return_Nothing(t *testing.T) {
t.Parallel()
// make a test impl object
var mockedService = new(TestExampleImplementation)
@ -929,6 +986,8 @@ func Test_Mock_Return_Nothing(t *testing.T) {
}
func Test_Mock_Return_NotBefore_In_Order(t *testing.T) {
t.Parallel()
var mockedService = new(TestExampleImplementation)
b := mockedService.
@ -949,6 +1008,8 @@ func Test_Mock_Return_NotBefore_In_Order(t *testing.T) {
}
func Test_Mock_Return_InOrder_Uses_NotBefore(t *testing.T) {
t.Parallel()
var mockedService = new(TestExampleImplementation)
InOrder(
@ -969,6 +1030,8 @@ func Test_Mock_Return_InOrder_Uses_NotBefore(t *testing.T) {
}
func Test_Mock_Return_NotBefore_Out_Of_Order(t *testing.T) {
t.Parallel()
var mockedService = new(TestExampleImplementation)
b := mockedService.
@ -999,6 +1062,8 @@ TheExampleMethod(int,int,int)
}
func Test_Mock_Return_InOrder_Uses_NotBefore_Out_Of_Order(t *testing.T) {
t.Parallel()
var mockedService = new(TestExampleImplementation)
InOrder(
@ -1028,6 +1093,8 @@ TheExampleMethod(int,int,int)
}
func Test_Mock_Return_NotBefore_Not_Enough_Times(t *testing.T) {
t.Parallel()
var mockedService = new(TestExampleImplementation)
b := mockedService.
@ -1061,6 +1128,8 @@ TheExampleMethod(int,int,int)
}
func Test_Mock_Return_NotBefore_Different_Mock_In_Order(t *testing.T) {
t.Parallel()
var (
mockedService1 = new(TestExampleImplementation)
mockedService2 = new(TestExampleImplementation)
@ -1084,6 +1153,8 @@ func Test_Mock_Return_NotBefore_Different_Mock_In_Order(t *testing.T) {
}
func Test_Mock_Return_NotBefore_Different_Mock_Out_Of_Order(t *testing.T) {
t.Parallel()
var (
mockedService1 = new(TestExampleImplementation)
mockedService2 = new(TestExampleImplementation)
@ -1117,6 +1188,8 @@ TheExampleMethod(int,int,int)
}
func Test_Mock_Return_NotBefore_In_Order_With_Non_Dependant(t *testing.T) {
t.Parallel()
var mockedService = new(TestExampleImplementation)
a := mockedService.
@ -1157,6 +1230,8 @@ func Test_Mock_Return_NotBefore_In_Order_With_Non_Dependant(t *testing.T) {
}
func Test_Mock_Return_NotBefore_Orphan_Call(t *testing.T) {
t.Parallel()
var mockedService = new(TestExampleImplementation)
require.PanicsWithValue(t, "not before calls must be created with Mock.On()", func() {
@ -1168,6 +1243,7 @@ func Test_Mock_Return_NotBefore_Orphan_Call(t *testing.T) {
}
func Test_Mock_findExpectedCall(t *testing.T) {
t.Parallel()
m := new(Mock)
m.On("One", 1).Return("one")
@ -1187,6 +1263,7 @@ func Test_Mock_findExpectedCall(t *testing.T) {
}
func Test_Mock_findExpectedCall_For_Unknown_Method(t *testing.T) {
t.Parallel()
m := new(Mock)
m.On("One", 1).Return("one")
@ -1200,6 +1277,7 @@ func Test_Mock_findExpectedCall_For_Unknown_Method(t *testing.T) {
}
func Test_Mock_findExpectedCall_Respects_Repeatability(t *testing.T) {
t.Parallel()
m := new(Mock)
m.On("One", 1).Return("one")
@ -1230,6 +1308,7 @@ func Test_Mock_findExpectedCall_Respects_Repeatability(t *testing.T) {
}
func Test_callString(t *testing.T) {
t.Parallel()
assert.Equal(t, `Method(int,bool,string)`, callString("Method", []interface{}{1, true, "something"}, false))
assert.Equal(t, `Method(<nil>)`, callString("Method", []interface{}{nil}, false))
@ -1237,6 +1316,7 @@ func Test_callString(t *testing.T) {
}
func Test_Mock_Called(t *testing.T) {
t.Parallel()
var mockedService = new(TestExampleImplementation)
@ -1264,6 +1344,7 @@ func asyncCall(m *Mock, ch chan Arguments) {
}
func Test_Mock_Called_blocks(t *testing.T) {
t.Parallel()
var mockedService = new(TestExampleImplementation)
@ -1297,6 +1378,7 @@ func Test_Mock_Called_blocks(t *testing.T) {
}
func Test_Mock_Called_For_Bounded_Repeatability(t *testing.T) {
t.Parallel()
var mockedService = new(TestExampleImplementation)
@ -1338,6 +1420,7 @@ func Test_Mock_Called_For_Bounded_Repeatability(t *testing.T) {
}
func Test_Mock_Called_For_SetTime_Expectation(t *testing.T) {
t.Parallel()
var mockedService = new(TestExampleImplementation)
@ -1354,6 +1437,7 @@ func Test_Mock_Called_For_SetTime_Expectation(t *testing.T) {
}
func Test_Mock_Called_Unexpected(t *testing.T) {
t.Parallel()
var mockedService = new(TestExampleImplementation)
@ -1365,6 +1449,7 @@ func Test_Mock_Called_Unexpected(t *testing.T) {
}
func Test_AssertExpectationsForObjects_Helper(t *testing.T) {
t.Parallel()
var mockedService1 = new(TestExampleImplementation)
var mockedService2 = new(TestExampleImplementation)
@ -1385,6 +1470,7 @@ func Test_AssertExpectationsForObjects_Helper(t *testing.T) {
}
func Test_AssertExpectationsForObjects_Helper_Failed(t *testing.T) {
t.Parallel()
var mockedService1 = new(TestExampleImplementation)
var mockedService2 = new(TestExampleImplementation)
@ -1404,6 +1490,7 @@ func Test_AssertExpectationsForObjects_Helper_Failed(t *testing.T) {
}
func Test_Mock_AssertExpectations(t *testing.T) {
t.Parallel()
var mockedService = new(TestExampleImplementation)
@ -1421,6 +1508,7 @@ func Test_Mock_AssertExpectations(t *testing.T) {
}
func Test_Mock_AssertExpectations_Placeholder_NoArgs(t *testing.T) {
t.Parallel()
var mockedService = new(TestExampleImplementation)
@ -1439,6 +1527,7 @@ func Test_Mock_AssertExpectations_Placeholder_NoArgs(t *testing.T) {
}
func Test_Mock_AssertExpectations_Placeholder(t *testing.T) {
t.Parallel()
var mockedService = new(TestExampleImplementation)
@ -1462,6 +1551,7 @@ func Test_Mock_AssertExpectations_Placeholder(t *testing.T) {
}
func Test_Mock_AssertExpectations_With_Pointers(t *testing.T) {
t.Parallel()
var mockedService = new(TestExampleImplementation)
@ -1483,6 +1573,7 @@ func Test_Mock_AssertExpectations_With_Pointers(t *testing.T) {
}
func Test_Mock_AssertExpectationsCustomType(t *testing.T) {
t.Parallel()
var mockedService = new(TestExampleImplementation)
@ -1500,6 +1591,7 @@ func Test_Mock_AssertExpectationsCustomType(t *testing.T) {
}
func Test_Mock_AssertExpectationsFunctionalOptionsType(t *testing.T) {
t.Parallel()
var mockedService = new(TestExampleImplementation)
@ -1517,6 +1609,7 @@ func Test_Mock_AssertExpectationsFunctionalOptionsType(t *testing.T) {
}
func Test_Mock_AssertExpectationsFunctionalOptionsType_Empty(t *testing.T) {
t.Parallel()
var mockedService = new(TestExampleImplementation)
@ -1534,6 +1627,7 @@ func Test_Mock_AssertExpectationsFunctionalOptionsType_Empty(t *testing.T) {
}
func Test_Mock_AssertExpectationsFunctionalOptionsType_Indirectly(t *testing.T) {
t.Parallel()
var mockedService = new(TestExampleImplementation)
@ -1551,6 +1645,7 @@ func Test_Mock_AssertExpectationsFunctionalOptionsType_Indirectly(t *testing.T)
}
func Test_Mock_AssertExpectationsFunctionalOptionsType_Diff_Func(t *testing.T) {
t.Parallel()
var mockedService = new(TestExampleImplementation)
@ -1565,6 +1660,7 @@ func Test_Mock_AssertExpectationsFunctionalOptionsType_Diff_Func(t *testing.T) {
}
func Test_Mock_AssertExpectationsFunctionalOptionsType_Diff_Arg(t *testing.T) {
t.Parallel()
var mockedService = new(TestExampleImplementation)
@ -1579,6 +1675,7 @@ func Test_Mock_AssertExpectationsFunctionalOptionsType_Diff_Arg(t *testing.T) {
}
func Test_Mock_AssertExpectations_With_Repeatability(t *testing.T) {
t.Parallel()
var mockedService = new(TestExampleImplementation)
@ -1600,6 +1697,7 @@ func Test_Mock_AssertExpectations_With_Repeatability(t *testing.T) {
}
func Test_Mock_AssertExpectations_Skipped_Test(t *testing.T) {
t.Parallel()
var mockedService = new(TestExampleImplementation)
@ -1610,6 +1708,7 @@ func Test_Mock_AssertExpectations_Skipped_Test(t *testing.T) {
}
func Test_Mock_TwoCallsWithDifferentArguments(t *testing.T) {
t.Parallel()
var mockedService = new(TestExampleImplementation)
@ -1629,6 +1728,7 @@ func Test_Mock_TwoCallsWithDifferentArguments(t *testing.T) {
}
func Test_Mock_AssertNumberOfCalls(t *testing.T) {
t.Parallel()
var mockedService = new(TestExampleImplementation)
@ -1643,6 +1743,7 @@ func Test_Mock_AssertNumberOfCalls(t *testing.T) {
}
func Test_Mock_AssertCalled(t *testing.T) {
t.Parallel()
var mockedService = new(TestExampleImplementation)
@ -1655,6 +1756,7 @@ func Test_Mock_AssertCalled(t *testing.T) {
}
func Test_Mock_AssertCalled_WithAnythingOfTypeArgument(t *testing.T) {
t.Parallel()
var mockedService = new(TestExampleImplementation)
@ -1669,6 +1771,7 @@ func Test_Mock_AssertCalled_WithAnythingOfTypeArgument(t *testing.T) {
}
func Test_Mock_AssertCalled_WithArguments(t *testing.T) {
t.Parallel()
var mockedService = new(TestExampleImplementation)
@ -1683,6 +1786,7 @@ func Test_Mock_AssertCalled_WithArguments(t *testing.T) {
}
func Test_Mock_AssertCalled_WithArguments_With_Repeatability(t *testing.T) {
t.Parallel()
var mockedService = new(TestExampleImplementation)
@ -1700,6 +1804,7 @@ func Test_Mock_AssertCalled_WithArguments_With_Repeatability(t *testing.T) {
}
func Test_Mock_AssertNotCalled(t *testing.T) {
t.Parallel()
var mockedService = new(TestExampleImplementation)
@ -1712,6 +1817,8 @@ func Test_Mock_AssertNotCalled(t *testing.T) {
}
func Test_Mock_IsMethodCallable(t *testing.T) {
t.Parallel()
var mockedService = new(TestExampleImplementation)
arg := []Call{{Repeatability: 1}, {Repeatability: 2}}
@ -1731,6 +1838,8 @@ func Test_Mock_IsMethodCallable(t *testing.T) {
}
func TestIsArgsEqual(t *testing.T) {
t.Parallel()
var expected = Arguments{5, 3, 4, 6, 7, 2}
// Copy elements 1 to 5
@ -1744,6 +1853,8 @@ func TestIsArgsEqual(t *testing.T) {
}
func Test_Mock_AssertOptional(t *testing.T) {
t.Parallel()
// Optional called
var ms1 = new(TestExampleImplementation)
ms1.On("TheExampleMethod", 1, 2, 3).Maybe().Return(4, nil)
@ -1772,6 +1883,7 @@ func Test_Mock_AssertOptional(t *testing.T) {
Arguments helper methods
*/
func Test_Arguments_Get(t *testing.T) {
t.Parallel()
var args = Arguments([]interface{}{"string", 123, true})
@ -1782,6 +1894,7 @@ func Test_Arguments_Get(t *testing.T) {
}
func Test_Arguments_Is(t *testing.T) {
t.Parallel()
var args = Arguments([]interface{}{"string", 123, true})
@ -1791,6 +1904,7 @@ func Test_Arguments_Is(t *testing.T) {
}
func Test_Arguments_Diff(t *testing.T) {
t.Parallel()
var args = Arguments([]interface{}{"Hello World", 123, true})
var diff string
@ -1804,6 +1918,7 @@ func Test_Arguments_Diff(t *testing.T) {
}
func Test_Arguments_Diff_DifferentNumberOfArgs(t *testing.T) {
t.Parallel()
var args = Arguments([]interface{}{"string", 123, true})
var diff string
@ -1816,6 +1931,7 @@ func Test_Arguments_Diff_DifferentNumberOfArgs(t *testing.T) {
}
func Test_Arguments_Diff_WithAnythingArgument(t *testing.T) {
t.Parallel()
var args = Arguments([]interface{}{"string", 123, true})
var count int
@ -1826,6 +1942,7 @@ func Test_Arguments_Diff_WithAnythingArgument(t *testing.T) {
}
func Test_Arguments_Diff_WithAnythingArgument_InActualToo(t *testing.T) {
t.Parallel()
var args = Arguments([]interface{}{"string", Anything, true})
var count int
@ -1836,6 +1953,7 @@ func Test_Arguments_Diff_WithAnythingArgument_InActualToo(t *testing.T) {
}
func Test_Arguments_Diff_WithAnythingOfTypeArgument(t *testing.T) {
t.Parallel()
var args = Arguments([]interface{}{"string", AnythingOfType("int"), true})
var count int
@ -1846,6 +1964,7 @@ func Test_Arguments_Diff_WithAnythingOfTypeArgument(t *testing.T) {
}
func Test_Arguments_Diff_WithAnythingOfTypeArgument_Failing(t *testing.T) {
t.Parallel()
var args = Arguments([]interface{}{"string", AnythingOfType("string"), true})
var count int
@ -1858,6 +1977,8 @@ func Test_Arguments_Diff_WithAnythingOfTypeArgument_Failing(t *testing.T) {
}
func Test_Arguments_Diff_WithIsTypeArgument(t *testing.T) {
t.Parallel()
var args = Arguments([]interface{}{"string", IsType(0), true})
var count int
_, count = args.Diff([]interface{}{"string", 123, true})
@ -1866,6 +1987,8 @@ func Test_Arguments_Diff_WithIsTypeArgument(t *testing.T) {
}
func Test_Arguments_Diff_WithIsTypeArgument_Failing(t *testing.T) {
t.Parallel()
var args = Arguments([]interface{}{"string", IsType(""), true})
var count int
var diff string
@ -1876,6 +1999,8 @@ func Test_Arguments_Diff_WithIsTypeArgument_Failing(t *testing.T) {
}
func Test_Arguments_Diff_WithArgMatcher(t *testing.T) {
t.Parallel()
matchFn := func(a int) bool {
return a == 123
}
@ -1899,6 +2024,7 @@ func Test_Arguments_Diff_WithArgMatcher(t *testing.T) {
}
func Test_Arguments_Assert(t *testing.T) {
t.Parallel()
var args = Arguments([]interface{}{"string", 123, true})
@ -1907,6 +2033,7 @@ func Test_Arguments_Assert(t *testing.T) {
}
func Test_Arguments_String_Representation(t *testing.T) {
t.Parallel()
var args = Arguments([]interface{}{"string", 123, true})
assert.Equal(t, `string,int,bool`, args.String())
@ -1914,6 +2041,7 @@ func Test_Arguments_String_Representation(t *testing.T) {
}
func Test_Arguments_String(t *testing.T) {
t.Parallel()
var args = Arguments([]interface{}{"string", 123, true})
assert.Equal(t, "string", args.String(0))
@ -1921,6 +2049,7 @@ func Test_Arguments_String(t *testing.T) {
}
func Test_Arguments_Error(t *testing.T) {
t.Parallel()
var err = errors.New("An Error")
var args = Arguments([]interface{}{"string", 123, true, err})
@ -1929,6 +2058,7 @@ func Test_Arguments_Error(t *testing.T) {
}
func Test_Arguments_Error_Nil(t *testing.T) {
t.Parallel()
var args = Arguments([]interface{}{"string", 123, true, nil})
assert.Equal(t, nil, args.Error(3))
@ -1936,6 +2066,7 @@ func Test_Arguments_Error_Nil(t *testing.T) {
}
func Test_Arguments_Int(t *testing.T) {
t.Parallel()
var args = Arguments([]interface{}{"string", 123, true})
assert.Equal(t, 123, args.Int(1))
@ -1943,6 +2074,7 @@ func Test_Arguments_Int(t *testing.T) {
}
func Test_Arguments_Bool(t *testing.T) {
t.Parallel()
var args = Arguments([]interface{}{"string", 123, true})
assert.Equal(t, true, args.Bool(2))
@ -1950,6 +2082,7 @@ func Test_Arguments_Bool(t *testing.T) {
}
func Test_WaitUntil_Parallel(t *testing.T) {
t.Parallel()
// make a test impl object
var mockedService = new(TestExampleImplementation)
@ -1976,6 +2109,8 @@ func Test_WaitUntil_Parallel(t *testing.T) {
}
func Test_MockMethodCalled(t *testing.T) {
t.Parallel()
m := new(Mock)
m.On("foo", "hello").Return("world")
@ -1986,6 +2121,8 @@ func Test_MockMethodCalled(t *testing.T) {
}
func Test_MockMethodCalled_Panic(t *testing.T) {
t.Parallel()
m := new(Mock)
m.On("foo", "hello").Panic("world panics")
@ -1995,6 +2132,8 @@ func Test_MockMethodCalled_Panic(t *testing.T) {
// Test to validate fix for racy concurrent call access in MethodCalled()
func Test_MockReturnAndCalledConcurrent(t *testing.T) {
t.Parallel()
iterations := 1000
m := &Mock{}
call := m.On("ConcurrencyTestMethod")
@ -2045,6 +2184,8 @@ func (tc *tCustomLogger) Errorf(format string, args ...interface{}) {
func (tc *tCustomLogger) FailNow() {}
func TestLoggingAssertExpectations(t *testing.T) {
t.Parallel()
m := new(timer)
m.On("GetTime", 0).Return("")
tcl := &tCustomLogger{t, []string{}, []string{}}
@ -2059,6 +2200,8 @@ func TestLoggingAssertExpectations(t *testing.T) {
}
func TestAfterTotalWaitTimeWhileExecution(t *testing.T) {
t.Parallel()
waitDuration := 1
total, waitMs := 5, time.Millisecond*time.Duration(waitDuration)
aTimer := new(timer)
@ -2083,6 +2226,8 @@ func TestAfterTotalWaitTimeWhileExecution(t *testing.T) {
}
func TestArgumentMatcherToPrintMismatch(t *testing.T) {
t.Parallel()
defer func() {
if r := recover(); r != nil {
matchingExp := regexp.MustCompile(
@ -2100,6 +2245,8 @@ func TestArgumentMatcherToPrintMismatch(t *testing.T) {
}
func TestArgumentMatcherToPrintMismatchWithReferenceType(t *testing.T) {
t.Parallel()
defer func() {
if r := recover(); r != nil {
matchingExp := regexp.MustCompile(
@ -2117,6 +2264,8 @@ func TestArgumentMatcherToPrintMismatchWithReferenceType(t *testing.T) {
}
func TestClosestCallMismatchedArgumentInformationShowsTheClosest(t *testing.T) {
t.Parallel()
defer func() {
if r := recover(); r != nil {
matchingExp := regexp.MustCompile(unexpectedCallRegex(`TheExampleMethod(int,int,int)`, `0: 1\s+1: 1\s+2: 2`, `0: 1\s+1: 1\s+2: 1`, `Diff: 0: PASS: \(int=1\) == \(int=1\)\s+1: PASS: \(int=1\) == \(int=1\)\s+2: FAIL: \(int=2\) != \(int=1\)`))
@ -2132,6 +2281,8 @@ func TestClosestCallMismatchedArgumentInformationShowsTheClosest(t *testing.T) {
}
func TestClosestCallFavorsFirstMock(t *testing.T) {
t.Parallel()
defer func() {
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}\]\)`
@ -2148,6 +2299,8 @@ func TestClosestCallFavorsFirstMock(t *testing.T) {
}
func TestClosestCallUsesRepeatabilityToFindClosest(t *testing.T) {
t.Parallel()
defer func() {
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}\]\)`
@ -2168,6 +2321,8 @@ func TestClosestCallUsesRepeatabilityToFindClosest(t *testing.T) {
}
func TestClosestCallMismatchedArgumentValueInformation(t *testing.T) {
t.Parallel()
defer func() {
if r := recover(); r != nil {
matchingExp := regexp.MustCompile(unexpectedCallRegex(`GetTime(int)`, "0: 1", "0: 999", `Diff: 0: FAIL: \(int=1\) != \(int=999\)`))
@ -2182,26 +2337,38 @@ func TestClosestCallMismatchedArgumentValueInformation(t *testing.T) {
}
func Test_isBetterMatchThanReturnsFalseIfCandidateCallIsNil(t *testing.T) {
t.Parallel()
assert.False(t, matchCandidate{}.isBetterMatchThan(matchCandidate{}))
}
func Test_isBetterMatchThanReturnsTrueIfOtherCandidateCallIsNil(t *testing.T) {
t.Parallel()
assert.True(t, matchCandidate{call: &Call{}}.isBetterMatchThan(matchCandidate{}))
}
func Test_isBetterMatchThanReturnsFalseIfDiffCountIsGreaterThanOther(t *testing.T) {
t.Parallel()
assert.False(t, matchCandidate{call: &Call{}, diffCount: 2}.isBetterMatchThan(matchCandidate{call: &Call{}, diffCount: 1}))
}
func Test_isBetterMatchThanReturnsTrueIfDiffCountIsLessThanOther(t *testing.T) {
t.Parallel()
assert.True(t, matchCandidate{call: &Call{}, diffCount: 1}.isBetterMatchThan(matchCandidate{call: &Call{}, diffCount: 2}))
}
func Test_isBetterMatchThanReturnsTrueIfRepeatabilityIsGreaterThanOther(t *testing.T) {
t.Parallel()
assert.True(t, matchCandidate{call: &Call{Repeatability: 1}, diffCount: 1}.isBetterMatchThan(matchCandidate{call: &Call{Repeatability: -1}, diffCount: 1}))
}
func Test_isBetterMatchThanReturnsFalseIfRepeatabilityIsLessThanOrEqualToOther(t *testing.T) {
t.Parallel()
assert.False(t, matchCandidate{call: &Call{Repeatability: 1}, diffCount: 1}.isBetterMatchThan(matchCandidate{call: &Call{Repeatability: 1}, diffCount: 1}))
}
@ -2217,6 +2384,8 @@ func ConcurrencyTestMethod(m *Mock) {
}
func TestConcurrentArgumentRead(t *testing.T) {
t.Parallel()
methodUnderTest := func(c caller, u user) {
go u.Use(c)
c.Call()

View File

@ -23,6 +23,8 @@
//
// The `require` package have same global functions as in the `assert` package,
// but instead of returning a boolean result they call `t.FailNow()`.
// A consequence of this is that it must be called from the goroutine running
// the test function, not from other goroutines created during the test.
//
// Every assertion function also takes an optional string message as the final argument,
// allowing custom error messages to be appended to the message the assertion method outputs.

View File

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

View File

@ -117,10 +117,19 @@ func ElementsMatchf(t TestingT, listA interface{}, listB interface{}, msg string
t.FailNow()
}
// Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either
// a slice or a channel with len == 0.
// Empty asserts that the given value is "empty".
//
// [Zero values] are "empty".
//
// Arrays are "empty" if every element is the zero value of the type (stricter than "empty").
//
// Slices, maps and channels with zero length are "empty".
//
// Pointer values are "empty" if the pointer is nil or if the pointed value is "empty".
//
// require.Empty(t, obj)
//
// [Zero values]: https://go.dev/ref/spec#The_zero_value
func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@ -131,10 +140,19 @@ func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) {
t.FailNow()
}
// Emptyf asserts that the specified object is empty. I.e. nil, "", false, 0 or either
// a slice or a channel with len == 0.
// Emptyf asserts that the given value is "empty".
//
// [Zero values] are "empty".
//
// Arrays are "empty" if every element is the zero value of the type (stricter than "empty").
//
// Slices, maps and channels with zero length are "empty".
//
// Pointer values are "empty" if the pointer is nil or if the pointed value is "empty".
//
// require.Emptyf(t, obj, "error message %s", "formatted")
//
// [Zero values]: https://go.dev/ref/spec#The_zero_value
func Emptyf(t TestingT, object interface{}, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@ -279,10 +297,8 @@ func Equalf(t TestingT, expected interface{}, actual interface{}, msg string, ar
// Error asserts that a function returned an error (i.e. not `nil`).
//
// actualObj, err := SomeFunction()
// if require.Error(t, err) {
// require.Equal(t, expectedError, err)
// }
// actualObj, err := SomeFunction()
// require.Error(t, err)
func Error(t TestingT, err error, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@ -373,10 +389,8 @@ func ErrorIsf(t TestingT, err error, target error, msg string, args ...interface
// Errorf asserts that a function returned an error (i.e. not `nil`).
//
// actualObj, err := SomeFunction()
// if require.Errorf(t, err, "error message %s", "formatted") {
// require.Equal(t, expectedErrorf, err)
// }
// actualObj, err := SomeFunction()
// require.Errorf(t, err, "error message %s", "formatted")
func Errorf(t TestingT, err error, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@ -1097,7 +1111,35 @@ func IsNonIncreasingf(t TestingT, object interface{}, msg string, args ...interf
t.FailNow()
}
// IsNotType asserts that the specified objects are not of the same type.
//
// require.IsNotType(t, &NotMyStruct{}, &MyStruct{})
func IsNotType(t TestingT, theType interface{}, object interface{}, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
}
if assert.IsNotType(t, theType, object, msgAndArgs...) {
return
}
t.FailNow()
}
// IsNotTypef asserts that the specified objects are not of the same type.
//
// require.IsNotTypef(t, &NotMyStruct{}, &MyStruct{}, "error message %s", "formatted")
func IsNotTypef(t TestingT, theType interface{}, object interface{}, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
}
if assert.IsNotTypef(t, theType, object, msg, args...) {
return
}
t.FailNow()
}
// IsType asserts that the specified objects are of the same type.
//
// require.IsType(t, &MyStruct{}, &MyStruct{})
func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@ -1109,6 +1151,8 @@ func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs
}
// IsTypef asserts that the specified objects are of the same type.
//
// require.IsTypef(t, &MyStruct{}, &MyStruct{}, "error message %s", "formatted")
func IsTypef(t TestingT, expectedType interface{}, object interface{}, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@ -1469,8 +1513,7 @@ func NotElementsMatchf(t TestingT, listA interface{}, listB interface{}, msg str
t.FailNow()
}
// 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.
// NotEmpty asserts that the specified object is NOT [Empty].
//
// if require.NotEmpty(t, obj) {
// require.Equal(t, "two", obj[1])
@ -1485,8 +1528,7 @@ func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) {
t.FailNow()
}
// 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.
// NotEmptyf asserts that the specified object is NOT [Empty].
//
// if require.NotEmptyf(t, obj, "error message %s", "formatted") {
// require.Equal(t, "two", obj[1])
@ -1745,12 +1787,15 @@ func NotSamef(t TestingT, expected interface{}, actual interface{}, msg string,
t.FailNow()
}
// NotSubset asserts that the specified list(array, slice...) or map does NOT
// contain all elements given in the specified subset list(array, slice...) or
// map.
// NotSubset asserts that the list (array, slice, or map) does NOT contain all
// elements given in the subset (array, slice, or map).
// Map elements are key-value pairs unless compared with an array or slice where
// only the map key is evaluated.
//
// require.NotSubset(t, [1, 3, 4], [1, 2])
// require.NotSubset(t, {"x": 1, "y": 2}, {"z": 3})
// require.NotSubset(t, [1, 3, 4], {1: "one", 2: "two"})
// require.NotSubset(t, {"x": 1, "y": 2}, ["z"])
func NotSubset(t TestingT, list interface{}, subset interface{}, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@ -1761,12 +1806,15 @@ func NotSubset(t TestingT, list interface{}, subset interface{}, msgAndArgs ...i
t.FailNow()
}
// NotSubsetf asserts that the specified list(array, slice...) or map does NOT
// contain all elements given in the specified subset list(array, slice...) or
// map.
// NotSubsetf asserts that the list (array, slice, or map) does NOT contain all
// elements given in the subset (array, slice, or map).
// Map elements are key-value pairs unless compared with an array or slice where
// only the map key is evaluated.
//
// require.NotSubsetf(t, [1, 3, 4], [1, 2], "error message %s", "formatted")
// require.NotSubsetf(t, {"x": 1, "y": 2}, {"z": 3}, "error message %s", "formatted")
// require.NotSubsetf(t, [1, 3, 4], {1: "one", 2: "two"}, "error message %s", "formatted")
// require.NotSubsetf(t, {"x": 1, "y": 2}, ["z"], "error message %s", "formatted")
func NotSubsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@ -1971,11 +2019,15 @@ func Samef(t TestingT, expected interface{}, actual interface{}, msg string, arg
t.FailNow()
}
// Subset asserts that the specified list(array, slice...) or map contains all
// elements given in the specified subset list(array, slice...) or map.
// Subset asserts that the list (array, slice, or map) contains all elements
// given in the subset (array, slice, or map).
// Map elements are key-value pairs unless compared with an array or slice where
// only the map key is evaluated.
//
// require.Subset(t, [1, 2, 3], [1, 2])
// require.Subset(t, {"x": 1, "y": 2}, {"x": 1})
// require.Subset(t, [1, 2, 3], {1: "one", 2: "two"})
// require.Subset(t, {"x": 1, "y": 2}, ["x"])
func Subset(t TestingT, list interface{}, subset interface{}, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@ -1986,11 +2038,15 @@ func Subset(t TestingT, list interface{}, subset interface{}, msgAndArgs ...inte
t.FailNow()
}
// Subsetf asserts that the specified list(array, slice...) or map contains all
// elements given in the specified subset list(array, slice...) or map.
// Subsetf asserts that the list (array, slice, or map) contains all elements
// given in the subset (array, slice, or map).
// Map elements are key-value pairs unless compared with an array or slice where
// only the map key is evaluated.
//
// require.Subsetf(t, [1, 2, 3], [1, 2], "error message %s", "formatted")
// require.Subsetf(t, {"x": 1, "y": 2}, {"x": 1}, "error message %s", "formatted")
// require.Subsetf(t, [1, 2, 3], {1: "one", 2: "two"}, "error message %s", "formatted")
// require.Subsetf(t, {"x": 1, "y": 2}, ["x"], "error message %s", "formatted")
func Subsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()

View File

@ -93,10 +93,19 @@ func (a *Assertions) ElementsMatchf(listA interface{}, listB interface{}, msg st
ElementsMatchf(a.t, listA, listB, msg, args...)
}
// Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either
// a slice or a channel with len == 0.
// Empty asserts that the given value is "empty".
//
// [Zero values] are "empty".
//
// Arrays are "empty" if every element is the zero value of the type (stricter than "empty").
//
// Slices, maps and channels with zero length are "empty".
//
// Pointer values are "empty" if the pointer is nil or if the pointed value is "empty".
//
// a.Empty(obj)
//
// [Zero values]: https://go.dev/ref/spec#The_zero_value
func (a *Assertions) Empty(object interface{}, msgAndArgs ...interface{}) {
if h, ok := a.t.(tHelper); ok {
h.Helper()
@ -104,10 +113,19 @@ func (a *Assertions) Empty(object interface{}, msgAndArgs ...interface{}) {
Empty(a.t, object, msgAndArgs...)
}
// Emptyf asserts that the specified object is empty. I.e. nil, "", false, 0 or either
// a slice or a channel with len == 0.
// Emptyf asserts that the given value is "empty".
//
// [Zero values] are "empty".
//
// Arrays are "empty" if every element is the zero value of the type (stricter than "empty").
//
// Slices, maps and channels with zero length are "empty".
//
// Pointer values are "empty" if the pointer is nil or if the pointed value is "empty".
//
// a.Emptyf(obj, "error message %s", "formatted")
//
// [Zero values]: https://go.dev/ref/spec#The_zero_value
func (a *Assertions) Emptyf(object interface{}, msg string, args ...interface{}) {
if h, ok := a.t.(tHelper); ok {
h.Helper()
@ -225,10 +243,8 @@ func (a *Assertions) Equalf(expected interface{}, actual interface{}, msg string
// Error asserts that a function returned an error (i.e. not `nil`).
//
// actualObj, err := SomeFunction()
// if a.Error(err) {
// assert.Equal(t, expectedError, err)
// }
// actualObj, err := SomeFunction()
// a.Error(err)
func (a *Assertions) Error(err error, msgAndArgs ...interface{}) {
if h, ok := a.t.(tHelper); ok {
h.Helper()
@ -298,10 +314,8 @@ func (a *Assertions) ErrorIsf(err error, target error, msg string, args ...inter
// Errorf asserts that a function returned an error (i.e. not `nil`).
//
// actualObj, err := SomeFunction()
// if a.Errorf(err, "error message %s", "formatted") {
// assert.Equal(t, expectedErrorf, err)
// }
// actualObj, err := SomeFunction()
// a.Errorf(err, "error message %s", "formatted")
func (a *Assertions) Errorf(err error, msg string, args ...interface{}) {
if h, ok := a.t.(tHelper); ok {
h.Helper()
@ -869,7 +883,29 @@ func (a *Assertions) IsNonIncreasingf(object interface{}, msg string, args ...in
IsNonIncreasingf(a.t, object, msg, args...)
}
// IsNotType asserts that the specified objects are not of the same type.
//
// a.IsNotType(&NotMyStruct{}, &MyStruct{})
func (a *Assertions) IsNotType(theType interface{}, object interface{}, msgAndArgs ...interface{}) {
if h, ok := a.t.(tHelper); ok {
h.Helper()
}
IsNotType(a.t, theType, object, msgAndArgs...)
}
// IsNotTypef asserts that the specified objects are not of the same type.
//
// a.IsNotTypef(&NotMyStruct{}, &MyStruct{}, "error message %s", "formatted")
func (a *Assertions) IsNotTypef(theType interface{}, object interface{}, msg string, args ...interface{}) {
if h, ok := a.t.(tHelper); ok {
h.Helper()
}
IsNotTypef(a.t, theType, object, msg, args...)
}
// IsType asserts that the specified objects are of the same type.
//
// a.IsType(&MyStruct{}, &MyStruct{})
func (a *Assertions) IsType(expectedType interface{}, object interface{}, msgAndArgs ...interface{}) {
if h, ok := a.t.(tHelper); ok {
h.Helper()
@ -878,6 +914,8 @@ func (a *Assertions) IsType(expectedType interface{}, object interface{}, msgAnd
}
// IsTypef asserts that the specified objects are of the same type.
//
// a.IsTypef(&MyStruct{}, &MyStruct{}, "error message %s", "formatted")
func (a *Assertions) IsTypef(expectedType interface{}, object interface{}, msg string, args ...interface{}) {
if h, ok := a.t.(tHelper); ok {
h.Helper()
@ -1163,8 +1201,7 @@ func (a *Assertions) NotElementsMatchf(listA interface{}, listB interface{}, msg
NotElementsMatchf(a.t, listA, listB, msg, args...)
}
// 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.
// NotEmpty asserts that the specified object is NOT [Empty].
//
// if a.NotEmpty(obj) {
// assert.Equal(t, "two", obj[1])
@ -1176,8 +1213,7 @@ func (a *Assertions) NotEmpty(object interface{}, msgAndArgs ...interface{}) {
NotEmpty(a.t, object, msgAndArgs...)
}
// 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.
// NotEmptyf asserts that the specified object is NOT [Empty].
//
// if a.NotEmptyf(obj, "error message %s", "formatted") {
// assert.Equal(t, "two", obj[1])
@ -1379,12 +1415,15 @@ func (a *Assertions) NotSamef(expected interface{}, actual interface{}, msg stri
NotSamef(a.t, expected, actual, msg, args...)
}
// NotSubset asserts that the specified list(array, slice...) or map does NOT
// contain all elements given in the specified subset list(array, slice...) or
// map.
// NotSubset asserts that the list (array, slice, or map) does NOT contain all
// elements given in the subset (array, slice, or map).
// Map elements are key-value pairs unless compared with an array or slice where
// only the map key is evaluated.
//
// a.NotSubset([1, 3, 4], [1, 2])
// a.NotSubset({"x": 1, "y": 2}, {"z": 3})
// a.NotSubset([1, 3, 4], {1: "one", 2: "two"})
// a.NotSubset({"x": 1, "y": 2}, ["z"])
func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs ...interface{}) {
if h, ok := a.t.(tHelper); ok {
h.Helper()
@ -1392,12 +1431,15 @@ func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs
NotSubset(a.t, list, subset, msgAndArgs...)
}
// NotSubsetf asserts that the specified list(array, slice...) or map does NOT
// contain all elements given in the specified subset list(array, slice...) or
// map.
// NotSubsetf asserts that the list (array, slice, or map) does NOT contain all
// elements given in the subset (array, slice, or map).
// Map elements are key-value pairs unless compared with an array or slice where
// only the map key is evaluated.
//
// a.NotSubsetf([1, 3, 4], [1, 2], "error message %s", "formatted")
// a.NotSubsetf({"x": 1, "y": 2}, {"z": 3}, "error message %s", "formatted")
// a.NotSubsetf([1, 3, 4], {1: "one", 2: "two"}, "error message %s", "formatted")
// a.NotSubsetf({"x": 1, "y": 2}, ["z"], "error message %s", "formatted")
func (a *Assertions) NotSubsetf(list interface{}, subset interface{}, msg string, args ...interface{}) {
if h, ok := a.t.(tHelper); ok {
h.Helper()
@ -1557,11 +1599,15 @@ func (a *Assertions) Samef(expected interface{}, actual interface{}, msg string,
Samef(a.t, expected, actual, msg, args...)
}
// Subset asserts that the specified list(array, slice...) or map contains all
// elements given in the specified subset list(array, slice...) or map.
// Subset asserts that the list (array, slice, or map) contains all elements
// given in the subset (array, slice, or map).
// Map elements are key-value pairs unless compared with an array or slice where
// only the map key is evaluated.
//
// a.Subset([1, 2, 3], [1, 2])
// a.Subset({"x": 1, "y": 2}, {"x": 1})
// a.Subset([1, 2, 3], {1: "one", 2: "two"})
// a.Subset({"x": 1, "y": 2}, ["x"])
func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ...interface{}) {
if h, ok := a.t.(tHelper); ok {
h.Helper()
@ -1569,11 +1615,15 @@ func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ...
Subset(a.t, list, subset, msgAndArgs...)
}
// Subsetf asserts that the specified list(array, slice...) or map contains all
// elements given in the specified subset list(array, slice...) or map.
// Subsetf asserts that the list (array, slice, or map) contains all elements
// given in the subset (array, slice, or map).
// Map elements are key-value pairs unless compared with an array or slice where
// only the map key is evaluated.
//
// a.Subsetf([1, 2, 3], [1, 2], "error message %s", "formatted")
// a.Subsetf({"x": 1, "y": 2}, {"x": 1}, "error message %s", "formatted")
// a.Subsetf([1, 2, 3], {1: "one", 2: "two"}, "error message %s", "formatted")
// a.Subsetf({"x": 1, "y": 2}, ["x"], "error message %s", "formatted")
func (a *Assertions) Subsetf(list interface{}, subset interface{}, msg string, args ...interface{}) {
if h, ok := a.t.(tHelper); ok {
h.Helper()

View File

@ -29,6 +29,9 @@ type MockT struct {
Failed bool
}
// Helper is like [testing.T.Helper] but does nothing.
func (MockT) Helper() {}
func (t *MockT) FailNow() {
t.Failed = true
}
@ -38,6 +41,7 @@ func (t *MockT) Errorf(format string, args ...interface{}) {
}
func TestImplements(t *testing.T) {
t.Parallel()
Implements(t, (*AssertionTesterInterface)(nil), new(AssertionTesterConformingObject))
@ -49,6 +53,7 @@ func TestImplements(t *testing.T) {
}
func TestIsType(t *testing.T) {
t.Parallel()
IsType(t, new(AssertionTesterConformingObject), new(AssertionTesterConformingObject))
@ -60,6 +65,7 @@ func TestIsType(t *testing.T) {
}
func TestEqual(t *testing.T) {
t.Parallel()
Equal(t, 1, 1)
@ -72,6 +78,7 @@ func TestEqual(t *testing.T) {
}
func TestNotEqual(t *testing.T) {
t.Parallel()
NotEqual(t, 1, 2)
mockT := new(MockT)
@ -82,6 +89,7 @@ func TestNotEqual(t *testing.T) {
}
func TestExactly(t *testing.T) {
t.Parallel()
a := float32(1)
b := float32(1)
@ -97,6 +105,7 @@ func TestExactly(t *testing.T) {
}
func TestNotNil(t *testing.T) {
t.Parallel()
NotNil(t, new(AssertionTesterConformingObject))
@ -108,6 +117,7 @@ func TestNotNil(t *testing.T) {
}
func TestNil(t *testing.T) {
t.Parallel()
Nil(t, nil)
@ -119,6 +129,7 @@ func TestNil(t *testing.T) {
}
func TestTrue(t *testing.T) {
t.Parallel()
True(t, true)
@ -130,6 +141,7 @@ func TestTrue(t *testing.T) {
}
func TestFalse(t *testing.T) {
t.Parallel()
False(t, false)
@ -141,6 +153,7 @@ func TestFalse(t *testing.T) {
}
func TestContains(t *testing.T) {
t.Parallel()
Contains(t, "Hello World", "Hello")
@ -152,6 +165,7 @@ func TestContains(t *testing.T) {
}
func TestNotContains(t *testing.T) {
t.Parallel()
NotContains(t, "Hello World", "Hello!")
@ -163,6 +177,7 @@ func TestNotContains(t *testing.T) {
}
func TestPanics(t *testing.T) {
t.Parallel()
Panics(t, func() {
panic("Panic!")
@ -176,6 +191,7 @@ func TestPanics(t *testing.T) {
}
func TestNotPanics(t *testing.T) {
t.Parallel()
NotPanics(t, func() {})
@ -189,6 +205,7 @@ func TestNotPanics(t *testing.T) {
}
func TestNoError(t *testing.T) {
t.Parallel()
NoError(t, nil)
@ -200,6 +217,7 @@ func TestNoError(t *testing.T) {
}
func TestError(t *testing.T) {
t.Parallel()
Error(t, errors.New("some error"))
@ -211,6 +229,7 @@ func TestError(t *testing.T) {
}
func TestErrorContains(t *testing.T) {
t.Parallel()
ErrorContains(t, errors.New("some error: another error"), "some error")
@ -222,6 +241,7 @@ func TestErrorContains(t *testing.T) {
}
func TestEqualError(t *testing.T) {
t.Parallel()
EqualError(t, errors.New("some error"), "some error")
@ -233,6 +253,7 @@ func TestEqualError(t *testing.T) {
}
func TestEmpty(t *testing.T) {
t.Parallel()
Empty(t, "")
@ -244,6 +265,7 @@ func TestEmpty(t *testing.T) {
}
func TestNotEmpty(t *testing.T) {
t.Parallel()
NotEmpty(t, "x")
@ -255,6 +277,7 @@ func TestNotEmpty(t *testing.T) {
}
func TestWithinDuration(t *testing.T) {
t.Parallel()
a := time.Now()
b := a.Add(10 * time.Second)
@ -269,6 +292,7 @@ func TestWithinDuration(t *testing.T) {
}
func TestInDelta(t *testing.T) {
t.Parallel()
InDelta(t, 1.001, 1, 0.01)
@ -280,6 +304,7 @@ func TestInDelta(t *testing.T) {
}
func TestZero(t *testing.T) {
t.Parallel()
Zero(t, "")
@ -291,6 +316,7 @@ func TestZero(t *testing.T) {
}
func TestNotZero(t *testing.T) {
t.Parallel()
NotZero(t, "x")
@ -302,6 +328,8 @@ func TestNotZero(t *testing.T) {
}
func TestJSONEq_EqualSONString(t *testing.T) {
t.Parallel()
mockT := new(MockT)
JSONEq(mockT, `{"hello": "world", "foo": "bar"}`, `{"hello": "world", "foo": "bar"}`)
if mockT.Failed {
@ -310,6 +338,8 @@ func TestJSONEq_EqualSONString(t *testing.T) {
}
func TestJSONEq_EquivalentButNotEqual(t *testing.T) {
t.Parallel()
mockT := new(MockT)
JSONEq(mockT, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`)
if mockT.Failed {
@ -318,6 +348,8 @@ func TestJSONEq_EquivalentButNotEqual(t *testing.T) {
}
func TestJSONEq_HashOfArraysAndHashes(t *testing.T) {
t.Parallel()
mockT := new(MockT)
JSONEq(mockT, "{\r\n\t\"numeric\": 1.5,\r\n\t\"array\": [{\"foo\": \"bar\"}, 1, \"string\", [\"nested\", \"array\", 5.5]],\r\n\t\"hash\": {\"nested\": \"hash\", \"nested_slice\": [\"this\", \"is\", \"nested\"]},\r\n\t\"string\": \"foo\"\r\n}",
"{\r\n\t\"numeric\": 1.5,\r\n\t\"hash\": {\"nested\": \"hash\", \"nested_slice\": [\"this\", \"is\", \"nested\"]},\r\n\t\"string\": \"foo\",\r\n\t\"array\": [{\"foo\": \"bar\"}, 1, \"string\", [\"nested\", \"array\", 5.5]]\r\n}")
@ -327,6 +359,8 @@ func TestJSONEq_HashOfArraysAndHashes(t *testing.T) {
}
func TestJSONEq_Array(t *testing.T) {
t.Parallel()
mockT := new(MockT)
JSONEq(mockT, `["foo", {"hello": "world", "nested": "hash"}]`, `["foo", {"nested": "hash", "hello": "world"}]`)
if mockT.Failed {
@ -335,6 +369,8 @@ func TestJSONEq_Array(t *testing.T) {
}
func TestJSONEq_HashAndArrayNotEquivalent(t *testing.T) {
t.Parallel()
mockT := new(MockT)
JSONEq(mockT, `["foo", {"hello": "world", "nested": "hash"}]`, `{"foo": "bar", {"nested": "hash", "hello": "world"}}`)
if !mockT.Failed {
@ -343,6 +379,8 @@ func TestJSONEq_HashAndArrayNotEquivalent(t *testing.T) {
}
func TestJSONEq_HashesNotEquivalent(t *testing.T) {
t.Parallel()
mockT := new(MockT)
JSONEq(mockT, `{"foo": "bar"}`, `{"foo": "bar", "hello": "world"}`)
if !mockT.Failed {
@ -351,6 +389,8 @@ func TestJSONEq_HashesNotEquivalent(t *testing.T) {
}
func TestJSONEq_ActualIsNotJSON(t *testing.T) {
t.Parallel()
mockT := new(MockT)
JSONEq(mockT, `{"foo": "bar"}`, "Not JSON")
if !mockT.Failed {
@ -359,6 +399,8 @@ func TestJSONEq_ActualIsNotJSON(t *testing.T) {
}
func TestJSONEq_ExpectedIsNotJSON(t *testing.T) {
t.Parallel()
mockT := new(MockT)
JSONEq(mockT, "Not JSON", `{"foo": "bar", "hello": "world"}`)
if !mockT.Failed {
@ -367,6 +409,8 @@ func TestJSONEq_ExpectedIsNotJSON(t *testing.T) {
}
func TestJSONEq_ExpectedAndActualNotJSON(t *testing.T) {
t.Parallel()
mockT := new(MockT)
JSONEq(mockT, "Not JSON", "Not JSON")
if !mockT.Failed {
@ -375,6 +419,8 @@ func TestJSONEq_ExpectedAndActualNotJSON(t *testing.T) {
}
func TestJSONEq_ArraysOfDifferentOrder(t *testing.T) {
t.Parallel()
mockT := new(MockT)
JSONEq(mockT, `["foo", {"hello": "world", "nested": "hash"}]`, `[{ "hello": "world", "nested": "hash"}, "foo"]`)
if !mockT.Failed {
@ -383,6 +429,8 @@ func TestJSONEq_ArraysOfDifferentOrder(t *testing.T) {
}
func TestYAMLEq_EqualYAMLString(t *testing.T) {
t.Parallel()
mockT := new(MockT)
YAMLEq(mockT, `{"hello": "world", "foo": "bar"}`, `{"hello": "world", "foo": "bar"}`)
if mockT.Failed {
@ -391,6 +439,8 @@ func TestYAMLEq_EqualYAMLString(t *testing.T) {
}
func TestYAMLEq_EquivalentButNotEqual(t *testing.T) {
t.Parallel()
mockT := new(MockT)
YAMLEq(mockT, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`)
if mockT.Failed {
@ -399,6 +449,8 @@ func TestYAMLEq_EquivalentButNotEqual(t *testing.T) {
}
func TestYAMLEq_HashOfArraysAndHashes(t *testing.T) {
t.Parallel()
mockT := new(MockT)
expected := `
numeric: 1.5
@ -432,6 +484,8 @@ array:
}
func TestYAMLEq_Array(t *testing.T) {
t.Parallel()
mockT := new(MockT)
YAMLEq(mockT, `["foo", {"hello": "world", "nested": "hash"}]`, `["foo", {"nested": "hash", "hello": "world"}]`)
if mockT.Failed {
@ -440,6 +494,8 @@ func TestYAMLEq_Array(t *testing.T) {
}
func TestYAMLEq_HashAndArrayNotEquivalent(t *testing.T) {
t.Parallel()
mockT := new(MockT)
YAMLEq(mockT, `["foo", {"hello": "world", "nested": "hash"}]`, `{"foo": "bar", {"nested": "hash", "hello": "world"}}`)
if !mockT.Failed {
@ -448,6 +504,8 @@ func TestYAMLEq_HashAndArrayNotEquivalent(t *testing.T) {
}
func TestYAMLEq_HashesNotEquivalent(t *testing.T) {
t.Parallel()
mockT := new(MockT)
YAMLEq(mockT, `{"foo": "bar"}`, `{"foo": "bar", "hello": "world"}`)
if !mockT.Failed {
@ -456,6 +514,8 @@ func TestYAMLEq_HashesNotEquivalent(t *testing.T) {
}
func TestYAMLEq_ActualIsSimpleString(t *testing.T) {
t.Parallel()
mockT := new(MockT)
YAMLEq(mockT, `{"foo": "bar"}`, "Simple String")
if !mockT.Failed {
@ -464,6 +524,8 @@ func TestYAMLEq_ActualIsSimpleString(t *testing.T) {
}
func TestYAMLEq_ExpectedIsSimpleString(t *testing.T) {
t.Parallel()
mockT := new(MockT)
YAMLEq(mockT, "Simple String", `{"foo": "bar", "hello": "world"}`)
if !mockT.Failed {
@ -472,6 +534,8 @@ func TestYAMLEq_ExpectedIsSimpleString(t *testing.T) {
}
func TestYAMLEq_ExpectedAndActualSimpleString(t *testing.T) {
t.Parallel()
mockT := new(MockT)
YAMLEq(mockT, "Simple String", "Simple String")
if mockT.Failed {
@ -480,6 +544,8 @@ func TestYAMLEq_ExpectedAndActualSimpleString(t *testing.T) {
}
func TestYAMLEq_ArraysOfDifferentOrder(t *testing.T) {
t.Parallel()
mockT := new(MockT)
YAMLEq(mockT, `["foo", {"hello": "world", "nested": "hash"}]`, `[{ "hello": "world", "nested": "hash"}, "foo"]`)
if !mockT.Failed {
@ -518,6 +584,8 @@ func ExampleComparisonAssertionFunc() {
}
func TestComparisonAssertionFunc(t *testing.T) {
t.Parallel()
type iface interface {
Name() string
}
@ -579,6 +647,8 @@ func ExampleValueAssertionFunc() {
}
func TestValueAssertionFunc(t *testing.T) {
t.Parallel()
tests := []struct {
name string
value interface{}
@ -625,6 +695,8 @@ func ExampleBoolAssertionFunc() {
}
func TestBoolAssertionFunc(t *testing.T) {
t.Parallel()
tests := []struct {
name string
value bool
@ -668,6 +740,8 @@ func ExampleErrorAssertionFunc() {
}
func TestErrorAssertionFunc(t *testing.T) {
t.Parallel()
tests := []struct {
name string
err error
@ -685,6 +759,8 @@ func TestErrorAssertionFunc(t *testing.T) {
}
func TestEventuallyWithTFalse(t *testing.T) {
t.Parallel()
mockT := new(MockT)
condition := func(collect *assert.CollectT) {
@ -696,6 +772,8 @@ func TestEventuallyWithTFalse(t *testing.T) {
}
func TestEventuallyWithTTrue(t *testing.T) {
t.Parallel()
mockT := new(MockT)
counter := 0

View File

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

View File

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

View File

@ -7,6 +7,7 @@ import (
"reflect"
"regexp"
"runtime/debug"
"strings"
"sync"
"testing"
"time"
@ -15,7 +16,6 @@ import (
"github.com/stretchr/testify/require"
)
var allTestsFilter = func(_, _ string) (bool, error) { return true, nil }
var matchMethod = flag.String("testify.m", "", "regular expression to select tests of the testify suite to run")
// Suite is a basic testing suite with methods for storing and
@ -116,6 +116,11 @@ func (suite *Suite) Run(name string, subtest func()) bool {
})
}
type test = struct {
name string
run func(t *testing.T)
}
// Run takes a testing suite and runs all of the tests attached
// to it.
func Run(t *testing.T, suite TestingSuite) {
@ -124,45 +129,39 @@ func Run(t *testing.T, suite TestingSuite) {
suite.SetT(t)
suite.SetS(suite)
var suiteSetupDone bool
var stats *SuiteInformation
if _, ok := suite.(WithStats); ok {
stats = newSuiteInformation()
}
tests := []testing.InternalTest{}
var tests []test
methodFinder := reflect.TypeOf(suite)
suiteName := methodFinder.Elem().Name()
for i := 0; i < methodFinder.NumMethod(); i++ {
method := methodFinder.Method(i)
ok, err := methodFilter(method.Name)
var matchMethodRE *regexp.Regexp
if *matchMethod != "" {
var err error
matchMethodRE, err = regexp.Compile(*matchMethod)
if err != nil {
fmt.Fprintf(os.Stderr, "testify: invalid regexp for -m: %s\n", err)
os.Exit(1)
}
}
if !ok {
for i := 0; i < methodFinder.NumMethod(); i++ {
method := methodFinder.Method(i)
if !strings.HasPrefix(method.Name, "Test") {
continue
}
// Apply -testify.m filter
if matchMethodRE != nil && !matchMethodRE.MatchString(method.Name) {
continue
}
if !suiteSetupDone {
if stats != nil {
stats.Start = time.Now()
}
if setupAllSuite, ok := suite.(SetupAllSuite); ok {
setupAllSuite.SetupSuite()
}
suiteSetupDone = true
}
test := testing.InternalTest{
Name: method.Name,
F: func(t *testing.T) {
test := test{
name: method.Name,
run: func(t *testing.T) {
parentT := suite.T()
suite.SetT(t)
defer recoverAndFailOnPanic(t)
@ -171,10 +170,7 @@ func Run(t *testing.T, suite TestingSuite) {
r := recover()
if stats != nil {
passed := !t.Failed() && r == nil
stats.end(method.Name, passed)
}
stats.end(method.Name, !t.Failed() && r == nil)
if afterTestSuite, ok := suite.(AfterTest); ok {
afterTestSuite.AfterTest(suiteName, method.Name)
@ -195,59 +191,47 @@ func Run(t *testing.T, suite TestingSuite) {
beforeTestSuite.BeforeTest(methodFinder.Elem().Name(), method.Name)
}
if stats != nil {
stats.start(method.Name)
}
stats.start(method.Name)
method.Func.Call([]reflect.Value{reflect.ValueOf(suite)})
},
}
tests = append(tests, test)
}
if suiteSetupDone {
defer func() {
if tearDownAllSuite, ok := suite.(TearDownAllSuite); ok {
tearDownAllSuite.TearDownSuite()
}
if suiteWithStats, measureStats := suite.(WithStats); measureStats {
stats.End = time.Now()
suiteWithStats.HandleStats(suiteName, stats)
}
}()
if len(tests) == 0 {
return
}
if stats != nil {
stats.Start = time.Now()
}
if setupAllSuite, ok := suite.(SetupAllSuite); ok {
setupAllSuite.SetupSuite()
}
defer func() {
if tearDownAllSuite, ok := suite.(TearDownAllSuite); ok {
tearDownAllSuite.TearDownSuite()
}
if suiteWithStats, measureStats := suite.(WithStats); measureStats {
stats.End = time.Now()
suiteWithStats.HandleStats(suiteName, stats)
}
}()
runTests(t, tests)
}
// Filtering method according to set regular expression
// specified command-line argument -m
func methodFilter(name string) (bool, error) {
if ok, _ := regexp.MatchString("^Test", name); !ok {
return false, nil
}
return regexp.MatchString(*matchMethod, name)
}
func runTests(t testing.TB, tests []testing.InternalTest) {
func runTests(t *testing.T, tests []test) {
if len(tests) == 0 {
t.Log("warning: no tests to run")
return
}
r, ok := t.(runner)
if !ok { // backwards compatibility with Go 1.6 and below
if !testing.RunTests(allTestsFilter, tests) {
t.Fail()
}
return
}
for _, test := range tests {
r.Run(test.Name, test.F)
t.Run(test.name, test.run)
}
}
type runner interface {
Run(name string, f func(t *testing.T)) bool
}

View File

@ -4,7 +4,7 @@ import (
"bytes"
"errors"
"flag"
"io/ioutil"
"io"
"math/rand"
"os"
"os/exec"
@ -16,6 +16,11 @@ import (
"github.com/stretchr/testify/require"
)
// allTestsFilter is a yes filter for testing.RunTests
func allTestsFilter(pat, str string) (bool, error) {
return true, nil
}
// SuiteRequireTwice is intended to test the usage of suite.Require in two
// different tests
type SuiteRequireTwice struct{ Suite }
@ -440,7 +445,7 @@ func (sc *StdoutCapture) StopCapture() (string, error) {
}
os.Stdout.Close()
os.Stdout = sc.oldStdout
bytes, err := ioutil.ReadAll(sc.readPipe)
bytes, err := io.ReadAll(sc.readPipe)
if err != nil {
return "", err
}