- assert: fixes a bug that would cause a panic if there were any
function calls before `assert.Check` on the same line
- golden: create the directory if it does not exist, when run with
`-test.update-golden`
full diff: https://github.com/gotestyourself/gotest.tools/compare/v3.0.2...v3.0.3
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
| ... | ... |
@@ -24,7 +24,7 @@ golang.org/x/sys eeed37f84f13f52d35e095e8023b |
| 24 | 24 |
github.com/docker/go-units 519db1ee28dcc9fd2474ae59fca29a810482bfb1 # v0.4.0 |
| 25 | 25 |
github.com/docker/go-connections 7395e3f8aa162843a74ed6d48e79627d9792ac55 # v0.4.0 |
| 26 | 26 |
golang.org/x/text 23ae387dee1f90d29a23c0e87ee0b46038fbed0e # v0.3.3 |
| 27 |
-gotest.tools/v3 bb0d8a963040ea5048dcef1a14d8f8b58a33d4b3 # v3.0.2 |
|
| 27 |
+gotest.tools/v3 568bc57cc5c19a2ef85e5749870b49a4cc2ab54d # v3.0.3 |
|
| 28 | 28 |
github.com/google/go-cmp 3af367b6b30c263d47e8895973edcca9a49cf029 # v0.2.0 |
| 29 | 29 |
github.com/syndtr/gocapability 42c35b4376354fd554efc7ad35e0b7f94e3a0ffb |
| 30 | 30 |
|
| ... | ... |
@@ -2,7 +2,7 @@ |
| 2 | 2 |
|
| 3 | 3 |
A collection of packages to augment `testing` and support common patterns. |
| 4 | 4 |
|
| 5 |
-[](http://gotest.tools) |
|
| 5 |
+[](https://pkg.go.dev/gotest.tools/v3/?tab=subdirectories) |
|
| 6 | 6 |
[](https://circleci.com/gh/gotestyourself/gotest.tools/tree/master) |
| 7 | 7 |
[](https://goreportcard.com/report/gotest.tools) |
| 8 | 8 |
|
| ... | ... |
@@ -24,19 +24,19 @@ module paths pin to version `v2.3.0`. |
| 24 | 24 |
|
| 25 | 25 |
## Packages |
| 26 | 26 |
|
| 27 |
-* [assert](http://gotest.tools/assert) - |
|
| 27 |
+* [assert](http://pkg.go.dev/gotest.tools/v3/assert) - |
|
| 28 | 28 |
compare values and fail the test when a comparison fails |
| 29 |
-* [env](http://gotest.tools/env) - |
|
| 29 |
+* [env](http://pkg.go.dev/gotest.tools/v3/env) - |
|
| 30 | 30 |
test code which uses environment variables |
| 31 |
-* [fs](http://gotest.tools/fs) - |
|
| 31 |
+* [fs](http://pkg.go.dev/gotest.tools/v3/fs) - |
|
| 32 | 32 |
create temporary files and compare a filesystem tree to an expected value |
| 33 |
-* [golden](http://gotest.tools/golden) - |
|
| 33 |
+* [golden](http://pkg.go.dev/gotest.tools/v3/golden) - |
|
| 34 | 34 |
compare large multi-line strings against values frozen in golden files |
| 35 |
-* [icmd](http://gotest.tools/icmd) - |
|
| 35 |
+* [icmd](http://pkg.go.dev/gotest.tools/v3/icmd) - |
|
| 36 | 36 |
execute binaries and test the output |
| 37 |
-* [poll](http://gotest.tools/poll) - |
|
| 37 |
+* [poll](http://pkg.go.dev/gotest.tools/v3/poll) - |
|
| 38 | 38 |
test asynchronous code by polling until a desired state is reached |
| 39 |
-* [skip](http://gotest.tools/skip) - |
|
| 39 |
+* [skip](http://pkg.go.dev/gotest.tools/v3/skip) - |
|
| 40 | 40 |
skip a test and print the source code of the condition used to skip the test |
| 41 | 41 |
|
| 42 | 42 |
## Related |
| ... | ... |
@@ -49,7 +49,7 @@ The example below shows assert used with some common types. |
| 49 | 49 |
|
| 50 | 50 |
Comparisons |
| 51 | 51 |
|
| 52 |
-Package http://gotest.tools/assert/cmp provides |
|
| 52 |
+Package http://pkg.go.dev/gotest.tools/v3/assert/cmp provides |
|
| 53 | 53 |
many common comparisons. Additional comparisons can be written to compare |
| 54 | 54 |
values in other ways. See the example Assert (CustomComparison). |
| 55 | 55 |
|
| ... | ... |
@@ -58,22 +58,16 @@ Automated migration from testify |
| 58 | 58 |
gty-migrate-from-testify is a command which translates Go source code from |
| 59 | 59 |
testify assertions to the assertions provided by this package. |
| 60 | 60 |
|
| 61 |
-See http://gotest.tools/assert/cmd/gty-migrate-from-testify. |
|
| 61 |
+See http://pkg.go.dev/gotest.tools/v3/assert/cmd/gty-migrate-from-testify. |
|
| 62 | 62 |
|
| 63 | 63 |
|
| 64 | 64 |
*/ |
| 65 | 65 |
package assert // import "gotest.tools/v3/assert" |
| 66 | 66 |
|
| 67 | 67 |
import ( |
| 68 |
- "fmt" |
|
| 69 |
- "go/ast" |
|
| 70 |
- "go/token" |
|
| 71 |
- "reflect" |
|
| 72 |
- |
|
| 73 | 68 |
gocmp "github.com/google/go-cmp/cmp" |
| 74 | 69 |
"gotest.tools/v3/assert/cmp" |
| 75 |
- "gotest.tools/v3/internal/format" |
|
| 76 |
- "gotest.tools/v3/internal/source" |
|
| 70 |
+ "gotest.tools/v3/internal/assert" |
|
| 77 | 71 |
) |
| 78 | 72 |
|
| 79 | 73 |
// BoolOrComparison can be a bool, or cmp.Comparison. See Assert() for usage. |
| ... | ... |
@@ -90,128 +84,6 @@ type helperT interface {
|
| 90 | 90 |
Helper() |
| 91 | 91 |
} |
| 92 | 92 |
|
| 93 |
-const failureMessage = "assertion failed: " |
|
| 94 |
- |
|
| 95 |
-// nolint: gocyclo |
|
| 96 |
-func assert( |
|
| 97 |
- t TestingT, |
|
| 98 |
- failer func(), |
|
| 99 |
- argSelector argSelector, |
|
| 100 |
- comparison BoolOrComparison, |
|
| 101 |
- msgAndArgs ...interface{},
|
|
| 102 |
-) bool {
|
|
| 103 |
- if ht, ok := t.(helperT); ok {
|
|
| 104 |
- ht.Helper() |
|
| 105 |
- } |
|
| 106 |
- var success bool |
|
| 107 |
- switch check := comparison.(type) {
|
|
| 108 |
- case bool: |
|
| 109 |
- if check {
|
|
| 110 |
- return true |
|
| 111 |
- } |
|
| 112 |
- logFailureFromBool(t, msgAndArgs...) |
|
| 113 |
- |
|
| 114 |
- // Undocumented legacy comparison without Result type |
|
| 115 |
- case func() (success bool, message string): |
|
| 116 |
- success = runCompareFunc(t, check, msgAndArgs...) |
|
| 117 |
- |
|
| 118 |
- case nil: |
|
| 119 |
- return true |
|
| 120 |
- |
|
| 121 |
- case error: |
|
| 122 |
- msg := failureMsgFromError(check) |
|
| 123 |
- t.Log(format.WithCustomMessage(failureMessage+msg, msgAndArgs...)) |
|
| 124 |
- |
|
| 125 |
- case cmp.Comparison: |
|
| 126 |
- success = runComparison(t, argSelector, check, msgAndArgs...) |
|
| 127 |
- |
|
| 128 |
- case func() cmp.Result: |
|
| 129 |
- success = runComparison(t, argSelector, check, msgAndArgs...) |
|
| 130 |
- |
|
| 131 |
- default: |
|
| 132 |
- t.Log(fmt.Sprintf("invalid Comparison: %v (%T)", check, check))
|
|
| 133 |
- } |
|
| 134 |
- |
|
| 135 |
- if success {
|
|
| 136 |
- return true |
|
| 137 |
- } |
|
| 138 |
- failer() |
|
| 139 |
- return false |
|
| 140 |
-} |
|
| 141 |
- |
|
| 142 |
-func runCompareFunc( |
|
| 143 |
- t TestingT, |
|
| 144 |
- f func() (success bool, message string), |
|
| 145 |
- msgAndArgs ...interface{},
|
|
| 146 |
-) bool {
|
|
| 147 |
- if ht, ok := t.(helperT); ok {
|
|
| 148 |
- ht.Helper() |
|
| 149 |
- } |
|
| 150 |
- if success, message := f(); !success {
|
|
| 151 |
- t.Log(format.WithCustomMessage(failureMessage+message, msgAndArgs...)) |
|
| 152 |
- return false |
|
| 153 |
- } |
|
| 154 |
- return true |
|
| 155 |
-} |
|
| 156 |
- |
|
| 157 |
-func logFailureFromBool(t TestingT, msgAndArgs ...interface{}) {
|
|
| 158 |
- if ht, ok := t.(helperT); ok {
|
|
| 159 |
- ht.Helper() |
|
| 160 |
- } |
|
| 161 |
- const stackIndex = 3 // Assert()/Check(), assert(), formatFailureFromBool() |
|
| 162 |
- const comparisonArgPos = 1 |
|
| 163 |
- args, err := source.CallExprArgs(stackIndex) |
|
| 164 |
- if err != nil {
|
|
| 165 |
- t.Log(err.Error()) |
|
| 166 |
- return |
|
| 167 |
- } |
|
| 168 |
- |
|
| 169 |
- msg, err := boolFailureMessage(args[comparisonArgPos]) |
|
| 170 |
- if err != nil {
|
|
| 171 |
- t.Log(err.Error()) |
|
| 172 |
- msg = "expression is false" |
|
| 173 |
- } |
|
| 174 |
- |
|
| 175 |
- t.Log(format.WithCustomMessage(failureMessage+msg, msgAndArgs...)) |
|
| 176 |
-} |
|
| 177 |
- |
|
| 178 |
-func failureMsgFromError(err error) string {
|
|
| 179 |
- // Handle errors with non-nil types |
|
| 180 |
- v := reflect.ValueOf(err) |
|
| 181 |
- if v.Kind() == reflect.Ptr && v.IsNil() {
|
|
| 182 |
- return fmt.Sprintf("error is not nil: error has type %T", err)
|
|
| 183 |
- } |
|
| 184 |
- return "error is not nil: " + err.Error() |
|
| 185 |
-} |
|
| 186 |
- |
|
| 187 |
-func boolFailureMessage(expr ast.Expr) (string, error) {
|
|
| 188 |
- if binaryExpr, ok := expr.(*ast.BinaryExpr); ok && binaryExpr.Op == token.NEQ {
|
|
| 189 |
- x, err := source.FormatNode(binaryExpr.X) |
|
| 190 |
- if err != nil {
|
|
| 191 |
- return "", err |
|
| 192 |
- } |
|
| 193 |
- y, err := source.FormatNode(binaryExpr.Y) |
|
| 194 |
- if err != nil {
|
|
| 195 |
- return "", err |
|
| 196 |
- } |
|
| 197 |
- return x + " is " + y, nil |
|
| 198 |
- } |
|
| 199 |
- |
|
| 200 |
- if unaryExpr, ok := expr.(*ast.UnaryExpr); ok && unaryExpr.Op == token.NOT {
|
|
| 201 |
- x, err := source.FormatNode(unaryExpr.X) |
|
| 202 |
- if err != nil {
|
|
| 203 |
- return "", err |
|
| 204 |
- } |
|
| 205 |
- return x + " is true", nil |
|
| 206 |
- } |
|
| 207 |
- |
|
| 208 |
- formatted, err := source.FormatNode(expr) |
|
| 209 |
- if err != nil {
|
|
| 210 |
- return "", err |
|
| 211 |
- } |
|
| 212 |
- return "expression is false: " + formatted, nil |
|
| 213 |
-} |
|
| 214 |
- |
|
| 215 | 93 |
// Assert performs a comparison. If the comparison fails, the test is marked as |
| 216 | 94 |
// failed, a failure message is logged, and execution is stopped immediately. |
| 217 | 95 |
// |
| ... | ... |
@@ -222,7 +94,7 @@ func boolFailureMessage(expr ast.Expr) (string, error) {
|
| 222 | 222 |
// cmp.Comparison |
| 223 | 223 |
// Uses cmp.Result.Success() to check for success of failure. |
| 224 | 224 |
// The comparison is responsible for producing a helpful failure message. |
| 225 |
-// http://gotest.tools/assert/cmp provides many common comparisons. |
|
| 225 |
+// http://pkg.go.dev/gotest.tools/v3/assert/cmp provides many common comparisons. |
|
| 226 | 226 |
// error |
| 227 | 227 |
// A nil value is considered success. |
| 228 | 228 |
// A non-nil error is a failure, err.Error() is used as the failure message. |
| ... | ... |
@@ -230,7 +102,9 @@ func Assert(t TestingT, comparison BoolOrComparison, msgAndArgs ...interface{})
|
| 230 | 230 |
if ht, ok := t.(helperT); ok {
|
| 231 | 231 |
ht.Helper() |
| 232 | 232 |
} |
| 233 |
- assert(t, t.FailNow, argsFromComparisonCall, comparison, msgAndArgs...) |
|
| 233 |
+ if !assert.Eval(t, assert.ArgsFromComparisonCall, comparison, msgAndArgs...) {
|
|
| 234 |
+ t.FailNow() |
|
| 235 |
+ } |
|
| 234 | 236 |
} |
| 235 | 237 |
|
| 236 | 238 |
// Check performs a comparison. If the comparison fails the test is marked as |
| ... | ... |
@@ -242,7 +116,11 @@ func Check(t TestingT, comparison BoolOrComparison, msgAndArgs ...interface{}) b
|
| 242 | 242 |
if ht, ok := t.(helperT); ok {
|
| 243 | 243 |
ht.Helper() |
| 244 | 244 |
} |
| 245 |
- return assert(t, t.Fail, argsFromComparisonCall, comparison, msgAndArgs...) |
|
| 245 |
+ if !assert.Eval(t, assert.ArgsFromComparisonCall, comparison, msgAndArgs...) {
|
|
| 246 |
+ t.Fail() |
|
| 247 |
+ return false |
|
| 248 |
+ } |
|
| 249 |
+ return true |
|
| 246 | 250 |
} |
| 247 | 251 |
|
| 248 | 252 |
// NilError fails the test immediately if err is not nil. |
| ... | ... |
@@ -251,7 +129,9 @@ func NilError(t TestingT, err error, msgAndArgs ...interface{}) {
|
| 251 | 251 |
if ht, ok := t.(helperT); ok {
|
| 252 | 252 |
ht.Helper() |
| 253 | 253 |
} |
| 254 |
- assert(t, t.FailNow, argsAfterT, err, msgAndArgs...) |
|
| 254 |
+ if !assert.Eval(t, assert.ArgsAfterT, err, msgAndArgs...) {
|
|
| 255 |
+ t.FailNow() |
|
| 256 |
+ } |
|
| 255 | 257 |
} |
| 256 | 258 |
|
| 257 | 259 |
// Equal uses the == operator to assert two values are equal and fails the test |
| ... | ... |
@@ -270,13 +150,15 @@ func Equal(t TestingT, x, y interface{}, msgAndArgs ...interface{}) {
|
| 270 | 270 |
if ht, ok := t.(helperT); ok {
|
| 271 | 271 |
ht.Helper() |
| 272 | 272 |
} |
| 273 |
- assert(t, t.FailNow, argsAfterT, cmp.Equal(x, y), msgAndArgs...) |
|
| 273 |
+ if !assert.Eval(t, assert.ArgsAfterT, cmp.Equal(x, y), msgAndArgs...) {
|
|
| 274 |
+ t.FailNow() |
|
| 275 |
+ } |
|
| 274 | 276 |
} |
| 275 | 277 |
|
| 276 | 278 |
// DeepEqual uses google/go-cmp (https://godoc.org/github.com/google/go-cmp/cmp) |
| 277 | 279 |
// to assert two values are equal and fails the test if they are not equal. |
| 278 | 280 |
// |
| 279 |
-// Package http://gotest.tools/assert/opt provides some additional |
|
| 281 |
+// Package http://pkg.go.dev/gotest.tools/v3/assert/opt provides some additional |
|
| 280 | 282 |
// commonly used Options. |
| 281 | 283 |
// |
| 282 | 284 |
// This is equivalent to Assert(t, cmp.DeepEqual(x, y)). |
| ... | ... |
@@ -284,7 +166,9 @@ func DeepEqual(t TestingT, x, y interface{}, opts ...gocmp.Option) {
|
| 284 | 284 |
if ht, ok := t.(helperT); ok {
|
| 285 | 285 |
ht.Helper() |
| 286 | 286 |
} |
| 287 |
- assert(t, t.FailNow, argsAfterT, cmp.DeepEqual(x, y, opts...)) |
|
| 287 |
+ if !assert.Eval(t, assert.ArgsAfterT, cmp.DeepEqual(x, y, opts...)) {
|
|
| 288 |
+ t.FailNow() |
|
| 289 |
+ } |
|
| 288 | 290 |
} |
| 289 | 291 |
|
| 290 | 292 |
// Error fails the test if err is nil, or the error message is not the expected |
| ... | ... |
@@ -294,7 +178,9 @@ func Error(t TestingT, err error, message string, msgAndArgs ...interface{}) {
|
| 294 | 294 |
if ht, ok := t.(helperT); ok {
|
| 295 | 295 |
ht.Helper() |
| 296 | 296 |
} |
| 297 |
- assert(t, t.FailNow, argsAfterT, cmp.Error(err, message), msgAndArgs...) |
|
| 297 |
+ if !assert.Eval(t, assert.ArgsAfterT, cmp.Error(err, message), msgAndArgs...) {
|
|
| 298 |
+ t.FailNow() |
|
| 299 |
+ } |
|
| 298 | 300 |
} |
| 299 | 301 |
|
| 300 | 302 |
// ErrorContains fails the test if err is nil, or the error message does not |
| ... | ... |
@@ -304,7 +190,9 @@ func ErrorContains(t TestingT, err error, substring string, msgAndArgs ...interf |
| 304 | 304 |
if ht, ok := t.(helperT); ok {
|
| 305 | 305 |
ht.Helper() |
| 306 | 306 |
} |
| 307 |
- assert(t, t.FailNow, argsAfterT, cmp.ErrorContains(err, substring), msgAndArgs...) |
|
| 307 |
+ if !assert.Eval(t, assert.ArgsAfterT, cmp.ErrorContains(err, substring), msgAndArgs...) {
|
|
| 308 |
+ t.FailNow() |
|
| 309 |
+ } |
|
| 308 | 310 |
} |
| 309 | 311 |
|
| 310 | 312 |
// ErrorType fails the test if err is nil, or err is not the expected type. |
| ... | ... |
@@ -325,5 +213,7 @@ func ErrorType(t TestingT, err error, expected interface{}, msgAndArgs ...interf
|
| 325 | 325 |
if ht, ok := t.(helperT); ok {
|
| 326 | 326 |
ht.Helper() |
| 327 | 327 |
} |
| 328 |
- assert(t, t.FailNow, argsAfterT, cmp.ErrorType(err, expected), msgAndArgs...) |
|
| 328 |
+ if !assert.Eval(t, assert.ArgsAfterT, cmp.ErrorType(err, expected), msgAndArgs...) {
|
|
| 329 |
+ t.FailNow() |
|
| 330 |
+ } |
|
| 329 | 331 |
} |
| ... | ... |
@@ -21,7 +21,7 @@ type Comparison func() Result |
| 21 | 21 |
// and succeeds if the values are equal. |
| 22 | 22 |
// |
| 23 | 23 |
// The comparison can be customized using comparison Options. |
| 24 |
-// Package http://gotest.tools/assert/opt provides some additional |
|
| 24 |
+// Package http://pkg.go.dev/gotest.tools/v3/assert/opt provides some additional |
|
| 25 | 25 |
// commonly used Options. |
| 26 | 26 |
func DeepEqual(x, y interface{}, opts ...cmp.Option) Comparison {
|
| 27 | 27 |
return func() (result Result) {
|
| ... | ... |
@@ -52,13 +52,12 @@ func ResultFromError(err error) Result {
|
| 52 | 52 |
} |
| 53 | 53 |
|
| 54 | 54 |
type templatedResult struct {
|
| 55 |
- success bool |
|
| 56 | 55 |
template string |
| 57 | 56 |
data map[string]interface{}
|
| 58 | 57 |
} |
| 59 | 58 |
|
| 60 | 59 |
func (r templatedResult) Success() bool {
|
| 61 |
- return r.success |
|
| 60 |
+ return false |
|
| 62 | 61 |
} |
| 63 | 62 |
|
| 64 | 63 |
func (r templatedResult) FailureMessage(args []ast.Expr) string {
|
| 65 | 64 |
deleted file mode 100644 |
| ... | ... |
@@ -1,106 +0,0 @@ |
| 1 |
-package assert |
|
| 2 |
- |
|
| 3 |
-import ( |
|
| 4 |
- "fmt" |
|
| 5 |
- "go/ast" |
|
| 6 |
- |
|
| 7 |
- "gotest.tools/v3/assert/cmp" |
|
| 8 |
- "gotest.tools/v3/internal/format" |
|
| 9 |
- "gotest.tools/v3/internal/source" |
|
| 10 |
-) |
|
| 11 |
- |
|
| 12 |
-func runComparison( |
|
| 13 |
- t TestingT, |
|
| 14 |
- argSelector argSelector, |
|
| 15 |
- f cmp.Comparison, |
|
| 16 |
- msgAndArgs ...interface{},
|
|
| 17 |
-) bool {
|
|
| 18 |
- if ht, ok := t.(helperT); ok {
|
|
| 19 |
- ht.Helper() |
|
| 20 |
- } |
|
| 21 |
- result := f() |
|
| 22 |
- if result.Success() {
|
|
| 23 |
- return true |
|
| 24 |
- } |
|
| 25 |
- |
|
| 26 |
- var message string |
|
| 27 |
- switch typed := result.(type) {
|
|
| 28 |
- case resultWithComparisonArgs: |
|
| 29 |
- const stackIndex = 3 // Assert/Check, assert, runComparison |
|
| 30 |
- args, err := source.CallExprArgs(stackIndex) |
|
| 31 |
- if err != nil {
|
|
| 32 |
- t.Log(err.Error()) |
|
| 33 |
- } |
|
| 34 |
- message = typed.FailureMessage(filterPrintableExpr(argSelector(args))) |
|
| 35 |
- case resultBasic: |
|
| 36 |
- message = typed.FailureMessage() |
|
| 37 |
- default: |
|
| 38 |
- message = fmt.Sprintf("comparison returned invalid Result type: %T", result)
|
|
| 39 |
- } |
|
| 40 |
- |
|
| 41 |
- t.Log(format.WithCustomMessage(failureMessage+message, msgAndArgs...)) |
|
| 42 |
- return false |
|
| 43 |
-} |
|
| 44 |
- |
|
| 45 |
-type resultWithComparisonArgs interface {
|
|
| 46 |
- FailureMessage(args []ast.Expr) string |
|
| 47 |
-} |
|
| 48 |
- |
|
| 49 |
-type resultBasic interface {
|
|
| 50 |
- FailureMessage() string |
|
| 51 |
-} |
|
| 52 |
- |
|
| 53 |
-// filterPrintableExpr filters the ast.Expr slice to only include Expr that are |
|
| 54 |
-// easy to read when printed and contain relevant information to an assertion. |
|
| 55 |
-// |
|
| 56 |
-// Ident and SelectorExpr are included because they print nicely and the variable |
|
| 57 |
-// names may provide additional context to their values. |
|
| 58 |
-// BasicLit and CompositeLit are excluded because their source is equivalent to |
|
| 59 |
-// their value, which is already available. |
|
| 60 |
-// Other types are ignored for now, but could be added if they are relevant. |
|
| 61 |
-func filterPrintableExpr(args []ast.Expr) []ast.Expr {
|
|
| 62 |
- result := make([]ast.Expr, len(args)) |
|
| 63 |
- for i, arg := range args {
|
|
| 64 |
- if isShortPrintableExpr(arg) {
|
|
| 65 |
- result[i] = arg |
|
| 66 |
- continue |
|
| 67 |
- } |
|
| 68 |
- |
|
| 69 |
- if starExpr, ok := arg.(*ast.StarExpr); ok {
|
|
| 70 |
- result[i] = starExpr.X |
|
| 71 |
- continue |
|
| 72 |
- } |
|
| 73 |
- } |
|
| 74 |
- return result |
|
| 75 |
-} |
|
| 76 |
- |
|
| 77 |
-func isShortPrintableExpr(expr ast.Expr) bool {
|
|
| 78 |
- switch expr.(type) {
|
|
| 79 |
- case *ast.Ident, *ast.SelectorExpr, *ast.IndexExpr, *ast.SliceExpr: |
|
| 80 |
- return true |
|
| 81 |
- case *ast.BinaryExpr, *ast.UnaryExpr: |
|
| 82 |
- return true |
|
| 83 |
- default: |
|
| 84 |
- // CallExpr, ParenExpr, TypeAssertExpr, KeyValueExpr, StarExpr |
|
| 85 |
- return false |
|
| 86 |
- } |
|
| 87 |
-} |
|
| 88 |
- |
|
| 89 |
-type argSelector func([]ast.Expr) []ast.Expr |
|
| 90 |
- |
|
| 91 |
-func argsAfterT(args []ast.Expr) []ast.Expr {
|
|
| 92 |
- if len(args) < 1 {
|
|
| 93 |
- return nil |
|
| 94 |
- } |
|
| 95 |
- return args[1:] |
|
| 96 |
-} |
|
| 97 |
- |
|
| 98 |
-func argsFromComparisonCall(args []ast.Expr) []ast.Expr {
|
|
| 99 |
- if len(args) < 1 {
|
|
| 100 |
- return nil |
|
| 101 |
- } |
|
| 102 |
- if callExpr, ok := args[1].(*ast.CallExpr); ok {
|
|
| 103 |
- return callExpr.Args |
|
| 104 |
- } |
|
| 105 |
- return nil |
|
| 106 |
-} |
| 8 | 8 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,143 @@ |
| 0 |
+package assert |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "fmt" |
|
| 4 |
+ "go/ast" |
|
| 5 |
+ "go/token" |
|
| 6 |
+ "reflect" |
|
| 7 |
+ |
|
| 8 |
+ "gotest.tools/v3/assert/cmp" |
|
| 9 |
+ "gotest.tools/v3/internal/format" |
|
| 10 |
+ "gotest.tools/v3/internal/source" |
|
| 11 |
+) |
|
| 12 |
+ |
|
| 13 |
+// LogT is the subset of testing.T used by the assert package. |
|
| 14 |
+type LogT interface {
|
|
| 15 |
+ Log(args ...interface{})
|
|
| 16 |
+} |
|
| 17 |
+ |
|
| 18 |
+type helperT interface {
|
|
| 19 |
+ Helper() |
|
| 20 |
+} |
|
| 21 |
+ |
|
| 22 |
+const failureMessage = "assertion failed: " |
|
| 23 |
+ |
|
| 24 |
+// Eval the comparison and print a failure messages if the comparison has failed. |
|
| 25 |
+// nolint: gocyclo |
|
| 26 |
+func Eval( |
|
| 27 |
+ t LogT, |
|
| 28 |
+ argSelector argSelector, |
|
| 29 |
+ comparison interface{},
|
|
| 30 |
+ msgAndArgs ...interface{},
|
|
| 31 |
+) bool {
|
|
| 32 |
+ if ht, ok := t.(helperT); ok {
|
|
| 33 |
+ ht.Helper() |
|
| 34 |
+ } |
|
| 35 |
+ var success bool |
|
| 36 |
+ switch check := comparison.(type) {
|
|
| 37 |
+ case bool: |
|
| 38 |
+ if check {
|
|
| 39 |
+ return true |
|
| 40 |
+ } |
|
| 41 |
+ logFailureFromBool(t, msgAndArgs...) |
|
| 42 |
+ |
|
| 43 |
+ // Undocumented legacy comparison without Result type |
|
| 44 |
+ case func() (success bool, message string): |
|
| 45 |
+ success = runCompareFunc(t, check, msgAndArgs...) |
|
| 46 |
+ |
|
| 47 |
+ case nil: |
|
| 48 |
+ return true |
|
| 49 |
+ |
|
| 50 |
+ case error: |
|
| 51 |
+ msg := failureMsgFromError(check) |
|
| 52 |
+ t.Log(format.WithCustomMessage(failureMessage+msg, msgAndArgs...)) |
|
| 53 |
+ |
|
| 54 |
+ case cmp.Comparison: |
|
| 55 |
+ success = RunComparison(t, argSelector, check, msgAndArgs...) |
|
| 56 |
+ |
|
| 57 |
+ case func() cmp.Result: |
|
| 58 |
+ success = RunComparison(t, argSelector, check, msgAndArgs...) |
|
| 59 |
+ |
|
| 60 |
+ default: |
|
| 61 |
+ t.Log(fmt.Sprintf("invalid Comparison: %v (%T)", check, check))
|
|
| 62 |
+ } |
|
| 63 |
+ return success |
|
| 64 |
+} |
|
| 65 |
+ |
|
| 66 |
+func runCompareFunc( |
|
| 67 |
+ t LogT, |
|
| 68 |
+ f func() (success bool, message string), |
|
| 69 |
+ msgAndArgs ...interface{},
|
|
| 70 |
+) bool {
|
|
| 71 |
+ if ht, ok := t.(helperT); ok {
|
|
| 72 |
+ ht.Helper() |
|
| 73 |
+ } |
|
| 74 |
+ if success, message := f(); !success {
|
|
| 75 |
+ t.Log(format.WithCustomMessage(failureMessage+message, msgAndArgs...)) |
|
| 76 |
+ return false |
|
| 77 |
+ } |
|
| 78 |
+ return true |
|
| 79 |
+} |
|
| 80 |
+ |
|
| 81 |
+func logFailureFromBool(t LogT, msgAndArgs ...interface{}) {
|
|
| 82 |
+ if ht, ok := t.(helperT); ok {
|
|
| 83 |
+ ht.Helper() |
|
| 84 |
+ } |
|
| 85 |
+ const stackIndex = 3 // Assert()/Check(), assert(), logFailureFromBool() |
|
| 86 |
+ args, err := source.CallExprArgs(stackIndex) |
|
| 87 |
+ if err != nil {
|
|
| 88 |
+ t.Log(err.Error()) |
|
| 89 |
+ return |
|
| 90 |
+ } |
|
| 91 |
+ |
|
| 92 |
+ const comparisonArgIndex = 1 // Assert(t, comparison) |
|
| 93 |
+ if len(args) <= comparisonArgIndex {
|
|
| 94 |
+ t.Log(failureMessage + "but assert failed to find the expression to print") |
|
| 95 |
+ return |
|
| 96 |
+ } |
|
| 97 |
+ |
|
| 98 |
+ msg, err := boolFailureMessage(args[comparisonArgIndex]) |
|
| 99 |
+ if err != nil {
|
|
| 100 |
+ t.Log(err.Error()) |
|
| 101 |
+ msg = "expression is false" |
|
| 102 |
+ } |
|
| 103 |
+ |
|
| 104 |
+ t.Log(format.WithCustomMessage(failureMessage+msg, msgAndArgs...)) |
|
| 105 |
+} |
|
| 106 |
+ |
|
| 107 |
+func failureMsgFromError(err error) string {
|
|
| 108 |
+ // Handle errors with non-nil types |
|
| 109 |
+ v := reflect.ValueOf(err) |
|
| 110 |
+ if v.Kind() == reflect.Ptr && v.IsNil() {
|
|
| 111 |
+ return fmt.Sprintf("error is not nil: error has type %T", err)
|
|
| 112 |
+ } |
|
| 113 |
+ return "error is not nil: " + err.Error() |
|
| 114 |
+} |
|
| 115 |
+ |
|
| 116 |
+func boolFailureMessage(expr ast.Expr) (string, error) {
|
|
| 117 |
+ if binaryExpr, ok := expr.(*ast.BinaryExpr); ok && binaryExpr.Op == token.NEQ {
|
|
| 118 |
+ x, err := source.FormatNode(binaryExpr.X) |
|
| 119 |
+ if err != nil {
|
|
| 120 |
+ return "", err |
|
| 121 |
+ } |
|
| 122 |
+ y, err := source.FormatNode(binaryExpr.Y) |
|
| 123 |
+ if err != nil {
|
|
| 124 |
+ return "", err |
|
| 125 |
+ } |
|
| 126 |
+ return x + " is " + y, nil |
|
| 127 |
+ } |
|
| 128 |
+ |
|
| 129 |
+ if unaryExpr, ok := expr.(*ast.UnaryExpr); ok && unaryExpr.Op == token.NOT {
|
|
| 130 |
+ x, err := source.FormatNode(unaryExpr.X) |
|
| 131 |
+ if err != nil {
|
|
| 132 |
+ return "", err |
|
| 133 |
+ } |
|
| 134 |
+ return x + " is true", nil |
|
| 135 |
+ } |
|
| 136 |
+ |
|
| 137 |
+ formatted, err := source.FormatNode(expr) |
|
| 138 |
+ if err != nil {
|
|
| 139 |
+ return "", err |
|
| 140 |
+ } |
|
| 141 |
+ return "expression is false: " + formatted, nil |
|
| 142 |
+} |
| 0 | 143 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,125 @@ |
| 0 |
+package assert |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "fmt" |
|
| 4 |
+ "go/ast" |
|
| 5 |
+ |
|
| 6 |
+ "gotest.tools/v3/assert/cmp" |
|
| 7 |
+ "gotest.tools/v3/internal/format" |
|
| 8 |
+ "gotest.tools/v3/internal/source" |
|
| 9 |
+) |
|
| 10 |
+ |
|
| 11 |
+// RunComparison and return Comparison.Success. If the comparison fails a messages |
|
| 12 |
+// will be printed using t.Log. |
|
| 13 |
+func RunComparison( |
|
| 14 |
+ t LogT, |
|
| 15 |
+ argSelector argSelector, |
|
| 16 |
+ f cmp.Comparison, |
|
| 17 |
+ msgAndArgs ...interface{},
|
|
| 18 |
+) bool {
|
|
| 19 |
+ if ht, ok := t.(helperT); ok {
|
|
| 20 |
+ ht.Helper() |
|
| 21 |
+ } |
|
| 22 |
+ result := f() |
|
| 23 |
+ if result.Success() {
|
|
| 24 |
+ return true |
|
| 25 |
+ } |
|
| 26 |
+ |
|
| 27 |
+ var message string |
|
| 28 |
+ switch typed := result.(type) {
|
|
| 29 |
+ case resultWithComparisonArgs: |
|
| 30 |
+ const stackIndex = 3 // Assert/Check, assert, RunComparison |
|
| 31 |
+ args, err := source.CallExprArgs(stackIndex) |
|
| 32 |
+ if err != nil {
|
|
| 33 |
+ t.Log(err.Error()) |
|
| 34 |
+ } |
|
| 35 |
+ message = typed.FailureMessage(filterPrintableExpr(argSelector(args))) |
|
| 36 |
+ case resultBasic: |
|
| 37 |
+ message = typed.FailureMessage() |
|
| 38 |
+ default: |
|
| 39 |
+ message = fmt.Sprintf("comparison returned invalid Result type: %T", result)
|
|
| 40 |
+ } |
|
| 41 |
+ |
|
| 42 |
+ t.Log(format.WithCustomMessage(failureMessage+message, msgAndArgs...)) |
|
| 43 |
+ return false |
|
| 44 |
+} |
|
| 45 |
+ |
|
| 46 |
+type resultWithComparisonArgs interface {
|
|
| 47 |
+ FailureMessage(args []ast.Expr) string |
|
| 48 |
+} |
|
| 49 |
+ |
|
| 50 |
+type resultBasic interface {
|
|
| 51 |
+ FailureMessage() string |
|
| 52 |
+} |
|
| 53 |
+ |
|
| 54 |
+// filterPrintableExpr filters the ast.Expr slice to only include Expr that are |
|
| 55 |
+// easy to read when printed and contain relevant information to an assertion. |
|
| 56 |
+// |
|
| 57 |
+// Ident and SelectorExpr are included because they print nicely and the variable |
|
| 58 |
+// names may provide additional context to their values. |
|
| 59 |
+// BasicLit and CompositeLit are excluded because their source is equivalent to |
|
| 60 |
+// their value, which is already available. |
|
| 61 |
+// Other types are ignored for now, but could be added if they are relevant. |
|
| 62 |
+func filterPrintableExpr(args []ast.Expr) []ast.Expr {
|
|
| 63 |
+ result := make([]ast.Expr, len(args)) |
|
| 64 |
+ for i, arg := range args {
|
|
| 65 |
+ if isShortPrintableExpr(arg) {
|
|
| 66 |
+ result[i] = arg |
|
| 67 |
+ continue |
|
| 68 |
+ } |
|
| 69 |
+ |
|
| 70 |
+ if starExpr, ok := arg.(*ast.StarExpr); ok {
|
|
| 71 |
+ result[i] = starExpr.X |
|
| 72 |
+ continue |
|
| 73 |
+ } |
|
| 74 |
+ } |
|
| 75 |
+ return result |
|
| 76 |
+} |
|
| 77 |
+ |
|
| 78 |
+func isShortPrintableExpr(expr ast.Expr) bool {
|
|
| 79 |
+ switch expr.(type) {
|
|
| 80 |
+ case *ast.Ident, *ast.SelectorExpr, *ast.IndexExpr, *ast.SliceExpr: |
|
| 81 |
+ return true |
|
| 82 |
+ case *ast.BinaryExpr, *ast.UnaryExpr: |
|
| 83 |
+ return true |
|
| 84 |
+ default: |
|
| 85 |
+ // CallExpr, ParenExpr, TypeAssertExpr, KeyValueExpr, StarExpr |
|
| 86 |
+ return false |
|
| 87 |
+ } |
|
| 88 |
+} |
|
| 89 |
+ |
|
| 90 |
+type argSelector func([]ast.Expr) []ast.Expr |
|
| 91 |
+ |
|
| 92 |
+// ArgsAfterT selects args starting at position 1. Used when the caller has a |
|
| 93 |
+// testing.T as the first argument, and the args to select should follow it. |
|
| 94 |
+func ArgsAfterT(args []ast.Expr) []ast.Expr {
|
|
| 95 |
+ if len(args) < 1 {
|
|
| 96 |
+ return nil |
|
| 97 |
+ } |
|
| 98 |
+ return args[1:] |
|
| 99 |
+} |
|
| 100 |
+ |
|
| 101 |
+// ArgsFromComparisonCall selects args from the CallExpression at position 1. |
|
| 102 |
+// Used when the caller has a testing.T as the first argument, and the args to |
|
| 103 |
+// select are passed to the cmp.Comparison at position 1. |
|
| 104 |
+func ArgsFromComparisonCall(args []ast.Expr) []ast.Expr {
|
|
| 105 |
+ if len(args) <= 1 {
|
|
| 106 |
+ return nil |
|
| 107 |
+ } |
|
| 108 |
+ if callExpr, ok := args[1].(*ast.CallExpr); ok {
|
|
| 109 |
+ return callExpr.Args |
|
| 110 |
+ } |
|
| 111 |
+ return nil |
|
| 112 |
+} |
|
| 113 |
+ |
|
| 114 |
+// ArgsAtZeroIndex selects args from the CallExpression at position 1. |
|
| 115 |
+// Used when the caller accepts a single cmp.Comparison argument. |
|
| 116 |
+func ArgsAtZeroIndex(args []ast.Expr) []ast.Expr {
|
|
| 117 |
+ if len(args) == 0 {
|
|
| 118 |
+ return nil |
|
| 119 |
+ } |
|
| 120 |
+ if callExpr, ok := args[0].(*ast.CallExpr); ok {
|
|
| 121 |
+ return callExpr.Args |
|
| 122 |
+ } |
|
| 123 |
+ return nil |
|
| 124 |
+} |
| ... | ... |
@@ -6,14 +6,17 @@ package cleanup |
| 6 | 6 |
import ( |
| 7 | 7 |
"os" |
| 8 | 8 |
"strings" |
| 9 |
- |
|
| 10 |
- "gotest.tools/v3/x/subtest" |
|
| 11 | 9 |
) |
| 12 | 10 |
|
| 13 | 11 |
type cleanupT interface {
|
| 14 | 12 |
Cleanup(f func()) |
| 15 | 13 |
} |
| 16 | 14 |
|
| 15 |
+// implemented by gotest.tools/x/subtest.TestContext |
|
| 16 |
+type addCleanupT interface {
|
|
| 17 |
+ AddCleanup(f func()) |
|
| 18 |
+} |
|
| 19 |
+ |
|
| 17 | 20 |
type logT interface {
|
| 18 | 21 |
Log(...interface{})
|
| 19 | 22 |
} |
| ... | ... |
@@ -39,7 +42,7 @@ func Cleanup(t logT, f func()) {
|
| 39 | 39 |
ct.Cleanup(f) |
| 40 | 40 |
return |
| 41 | 41 |
} |
| 42 |
- if tc, ok := t.(subtest.TestContext); ok {
|
|
| 42 |
+ if tc, ok := t.(addCleanupT); ok {
|
|
| 43 | 43 |
tc.AddCleanup(f) |
| 44 | 44 |
} |
| 45 | 45 |
} |
| ... | ... |
@@ -93,8 +93,9 @@ func nodePosition(fileset *token.FileSet, node ast.Node) token.Position {
|
| 93 | 93 |
} |
| 94 | 94 |
|
| 95 | 95 |
// GoVersionLessThan returns true if runtime.Version() is semantically less than |
| 96 |
-// version 1.minor. |
|
| 97 |
-func GoVersionLessThan(minor int64) bool {
|
|
| 96 |
+// version major.minor. Returns false if a release version can not be parsed from |
|
| 97 |
+// runtime.Version(). |
|
| 98 |
+func GoVersionLessThan(major, minor int64) bool {
|
|
| 98 | 99 |
version := runtime.Version() |
| 99 | 100 |
// not a release version |
| 100 | 101 |
if !strings.HasPrefix(version, "go") {
|
| ... | ... |
@@ -105,11 +106,21 @@ func GoVersionLessThan(minor int64) bool {
|
| 105 | 105 |
if len(parts) < 2 {
|
| 106 | 106 |
return false |
| 107 | 107 |
} |
| 108 |
- actual, err := strconv.ParseInt(parts[1], 10, 32) |
|
| 109 |
- return err == nil && parts[0] == "1" && actual < minor |
|
| 108 |
+ rMajor, err := strconv.ParseInt(parts[0], 10, 32) |
|
| 109 |
+ if err != nil {
|
|
| 110 |
+ return false |
|
| 111 |
+ } |
|
| 112 |
+ if rMajor != major {
|
|
| 113 |
+ return rMajor < major |
|
| 114 |
+ } |
|
| 115 |
+ rMinor, err := strconv.ParseInt(parts[1], 10, 32) |
|
| 116 |
+ if err != nil {
|
|
| 117 |
+ return false |
|
| 118 |
+ } |
|
| 119 |
+ return rMinor < minor |
|
| 110 | 120 |
} |
| 111 | 121 |
|
| 112 |
-var goVersionBefore19 = GoVersionLessThan(9) |
|
| 122 |
+var goVersionBefore19 = GoVersionLessThan(1, 9) |
|
| 113 | 123 |
|
| 114 | 124 |
func getCallExprArgs(node ast.Node) ([]ast.Expr, error) {
|
| 115 | 125 |
visitor := &callExprVisitor{}
|
| ... | ... |
@@ -4,7 +4,11 @@ package poll // import "gotest.tools/v3/poll" |
| 4 | 4 |
|
| 5 | 5 |
import ( |
| 6 | 6 |
"fmt" |
| 7 |
+ "strings" |
|
| 7 | 8 |
"time" |
| 9 |
+ |
|
| 10 |
+ "gotest.tools/v3/assert/cmp" |
|
| 11 |
+ "gotest.tools/v3/internal/assert" |
|
| 8 | 12 |
) |
| 9 | 13 |
|
| 10 | 14 |
// TestingT is the subset of testing.T used by WaitOn |
| ... | ... |
@@ -138,3 +142,30 @@ func WaitOn(t TestingT, check Check, pollOps ...SettingOp) {
|
| 138 | 138 |
} |
| 139 | 139 |
} |
| 140 | 140 |
} |
| 141 |
+ |
|
| 142 |
+// Compare values using the cmp.Comparison. If the comparison fails return a |
|
| 143 |
+// result which indicates to WaitOn that it should continue waiting. |
|
| 144 |
+// If the comparison is successful then WaitOn stops polling. |
|
| 145 |
+func Compare(compare cmp.Comparison) Result {
|
|
| 146 |
+ buf := new(logBuffer) |
|
| 147 |
+ if assert.RunComparison(buf, assert.ArgsAtZeroIndex, compare) {
|
|
| 148 |
+ return Success() |
|
| 149 |
+ } |
|
| 150 |
+ return Continue(buf.String()) |
|
| 151 |
+} |
|
| 152 |
+ |
|
| 153 |
+type logBuffer struct {
|
|
| 154 |
+ log [][]interface{}
|
|
| 155 |
+} |
|
| 156 |
+ |
|
| 157 |
+func (c *logBuffer) Log(args ...interface{}) {
|
|
| 158 |
+ c.log = append(c.log, args) |
|
| 159 |
+} |
|
| 160 |
+ |
|
| 161 |
+func (c *logBuffer) String() string {
|
|
| 162 |
+ b := new(strings.Builder) |
|
| 163 |
+ for _, item := range c.log {
|
|
| 164 |
+ b.WriteString(fmt.Sprint(item...) + " ") |
|
| 165 |
+ } |
|
| 166 |
+ return b.String() |
|
| 167 |
+} |
| 141 | 168 |
deleted file mode 100644 |
| ... | ... |
@@ -1,84 +0,0 @@ |
| 1 |
-/*Package subtest provides a TestContext to subtests which handles cleanup, and |
|
| 2 |
-provides a testing.TB, and context.Context. |
|
| 3 |
- |
|
| 4 |
-This package was inspired by github.com/frankban/quicktest. |
|
| 5 |
-*/ |
|
| 6 |
-package subtest // import "gotest.tools/v3/x/subtest" |
|
| 7 |
- |
|
| 8 |
-import ( |
|
| 9 |
- "context" |
|
| 10 |
- "testing" |
|
| 11 |
-) |
|
| 12 |
- |
|
| 13 |
-type testcase struct {
|
|
| 14 |
- testing.TB |
|
| 15 |
- ctx context.Context |
|
| 16 |
- cleanupFuncs []cleanupFunc |
|
| 17 |
-} |
|
| 18 |
- |
|
| 19 |
-type cleanupFunc func() |
|
| 20 |
- |
|
| 21 |
-func (tc *testcase) Ctx() context.Context {
|
|
| 22 |
- if tc.ctx == nil {
|
|
| 23 |
- var cancel func() |
|
| 24 |
- tc.ctx, cancel = context.WithCancel(context.Background()) |
|
| 25 |
- tc.AddCleanup(cancel) |
|
| 26 |
- } |
|
| 27 |
- return tc.ctx |
|
| 28 |
-} |
|
| 29 |
- |
|
| 30 |
-// cleanup runs all cleanup functions. Functions are run in the opposite order |
|
| 31 |
-// in which they were added. Cleanup is called automatically before Run exits. |
|
| 32 |
-func (tc *testcase) cleanup() {
|
|
| 33 |
- for _, f := range tc.cleanupFuncs {
|
|
| 34 |
- // Defer all cleanup functions so they all run even if one calls |
|
| 35 |
- // t.FailNow() or panics. Deferring them also runs them in reverse order. |
|
| 36 |
- defer f() |
|
| 37 |
- } |
|
| 38 |
- tc.cleanupFuncs = nil |
|
| 39 |
-} |
|
| 40 |
- |
|
| 41 |
-func (tc *testcase) AddCleanup(f func()) {
|
|
| 42 |
- tc.cleanupFuncs = append(tc.cleanupFuncs, f) |
|
| 43 |
-} |
|
| 44 |
- |
|
| 45 |
-func (tc *testcase) Parallel() {
|
|
| 46 |
- tp, ok := tc.TB.(parallel) |
|
| 47 |
- if !ok {
|
|
| 48 |
- panic("Parallel called with a testing.B")
|
|
| 49 |
- } |
|
| 50 |
- tp.Parallel() |
|
| 51 |
-} |
|
| 52 |
- |
|
| 53 |
-type parallel interface {
|
|
| 54 |
- Parallel() |
|
| 55 |
-} |
|
| 56 |
- |
|
| 57 |
-// Run a subtest. When subtest exits, every cleanup function added with |
|
| 58 |
-// TestContext.AddCleanup will be run. |
|
| 59 |
-func Run(t *testing.T, name string, subtest func(t TestContext)) bool {
|
|
| 60 |
- return t.Run(name, func(t *testing.T) {
|
|
| 61 |
- tc := &testcase{TB: t}
|
|
| 62 |
- defer tc.cleanup() |
|
| 63 |
- subtest(tc) |
|
| 64 |
- }) |
|
| 65 |
-} |
|
| 66 |
- |
|
| 67 |
-// TestContext provides a testing.TB and a context.Context for a test case. |
|
| 68 |
-type TestContext interface {
|
|
| 69 |
- testing.TB |
|
| 70 |
- // AddCleanup function which will be run when before Run returns. |
|
| 71 |
- // |
|
| 72 |
- // Deprecated: Go 1.14+ now includes a testing.TB.Cleanup(func()) which |
|
| 73 |
- // should be used instead. AddCleanup will be removed in a future release. |
|
| 74 |
- AddCleanup(f func()) |
|
| 75 |
- // Ctx returns a context for the test case. Multiple calls from the same subtest |
|
| 76 |
- // will return the same context. The context is cancelled when Run |
|
| 77 |
- // returns. |
|
| 78 |
- Ctx() context.Context |
|
| 79 |
- // Parallel calls t.Parallel on the testing.TB. Panics if testing.TB does |
|
| 80 |
- // not implement Parallel. |
|
| 81 |
- Parallel() |
|
| 82 |
-} |
|
| 83 |
- |
|
| 84 |
-var _ TestContext = &testcase{}
|