@@ -21,6 +21,7 @@ import (
21
21
"flag"
22
22
"fmt"
23
23
"strings"
24
+ "testing"
24
25
"time"
25
26
26
27
"github.com/onsi/gomega"
@@ -84,6 +85,13 @@ type TContext interface {
84
85
// a single test never run in parallel with each other.
85
86
Parallel ()
86
87
88
+ // Run runs f as a subtest of t called name. It blocks until f returns or
89
+ // calls t.Parallel to become a parallel test.
90
+ //
91
+ // Only supported in Go unit tests or benchmarks. It fails the current
92
+ // test when called elsewhere.
93
+ Run (name string , f func (tCtx TContext )) bool
94
+
87
95
// Cancel can be invoked to cancel the context before the test is completed.
88
96
// Tests which use the context to control goroutines and then wait for
89
97
// termination of those goroutines must call Cancel to avoid a deadlock.
@@ -174,6 +182,7 @@ type TContext interface {
174
182
// - CleanupCtx
175
183
// - Expect
176
184
// - ExpectNoError
185
+ // - Run
177
186
// - Logger
178
187
//
179
188
// Usually these methods would be stand-alone functions with a TContext
@@ -337,6 +346,9 @@ func InitCtx(ctx context.Context, tb TB, _ ...InitOption) TContext {
337
346
// })
338
347
//
339
348
// WithTB sets up cancellation for the sub-test.
349
+ //
350
+ // A simpler API is to use TContext.Run as replacement
351
+ // for [testing.T.Run].
340
352
func WithTB (parentCtx TContext , tb TB ) TContext {
341
353
tCtx := InitCtx (parentCtx , tb )
342
354
tCtx = WithCancel (tCtx )
@@ -350,6 +362,27 @@ func WithTB(parentCtx TContext, tb TB) TContext {
350
362
return tCtx
351
363
}
352
364
365
+ // run implements the different Run methods. It's not an exported
366
+ // method because tCtx.Run is more discoverable (same usage as
367
+ // with normal Go).
368
+ func run (tCtx TContext , name string , cb func (tCtx TContext )) bool {
369
+ tCtx .Helper ()
370
+ switch tb := tCtx .TB ().(type ) {
371
+ case interface {
372
+ Run (string , func (t * testing.T )) bool
373
+ }:
374
+ return tb .Run (name , func (t * testing.T ) { cb (WithTB (tCtx , t )) })
375
+ case interface {
376
+ Run (string , func (t * testing.B )) bool
377
+ }:
378
+ return tb .Run (name , func (b * testing.B ) { cb (WithTB (tCtx , b )) })
379
+ default :
380
+ tCtx .Fatalf ("Run not implemented, underlying %T does not support it" , tCtx .TB ())
381
+ }
382
+
383
+ return false
384
+ }
385
+
353
386
// WithContext constructs a new TContext with a different Context instance.
354
387
// This can be used in callbacks which receive a Context, for example
355
388
// from Gomega:
@@ -439,6 +472,10 @@ func cleanupCtx(tCtx TContext, cb func(TContext)) {
439
472
})
440
473
}
441
474
475
+ func (cCtx tContext ) Run (name string , cb func (tCtx TContext )) bool {
476
+ return run (cCtx , name , cb )
477
+ }
478
+
442
479
func (tCtx tContext ) Logger () klog.Logger {
443
480
return klog .FromContext (tCtx )
444
481
}
0 commit comments