mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-30 06:54:01 +00:00
ktesting: add Run
This is useful in Go unit tests because it directly replaces the corresponding testing.T/B.Run.
This commit is contained in:
parent
c2ad724e9a
commit
f9e7b15c00
@ -86,6 +86,10 @@ func (cCtx clientContext) ExpectNoError(err error, explain ...interface{}) {
|
||||
expectNoError(cCtx, err, explain...)
|
||||
}
|
||||
|
||||
func (cCtx clientContext) Run(name string, cb func(tCtx TContext)) bool {
|
||||
return run(cCtx, name, cb)
|
||||
}
|
||||
|
||||
func (cCtx clientContext) Logger() klog.Logger {
|
||||
return klog.FromContext(cCtx)
|
||||
}
|
||||
|
@ -149,6 +149,10 @@ func (eCtx *errorContext) ExpectNoError(err error, explain ...interface{}) {
|
||||
expectNoError(eCtx, err, explain...)
|
||||
}
|
||||
|
||||
func (cCtx *errorContext) Run(name string, cb func(tCtx TContext)) bool {
|
||||
return run(cCtx, name, cb)
|
||||
}
|
||||
|
||||
func (eCtx *errorContext) Logger() klog.Logger {
|
||||
return klog.FromContext(eCtx)
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/onsi/gomega"
|
||||
@ -84,6 +85,13 @@ type TContext interface {
|
||||
// a single test never run in parallel with each other.
|
||||
Parallel()
|
||||
|
||||
// Run runs f as a subtest of t called name. It blocks until f returns or
|
||||
// calls t.Parallel to become a parallel test.
|
||||
//
|
||||
// Only supported in Go unit tests or benchmarks. It fails the current
|
||||
// test when called elsewhere.
|
||||
Run(name string, f func(tCtx TContext)) bool
|
||||
|
||||
// Cancel can be invoked to cancel the context before the test is completed.
|
||||
// Tests which use the context to control goroutines and then wait for
|
||||
// termination of those goroutines must call Cancel to avoid a deadlock.
|
||||
@ -174,6 +182,7 @@ type TContext interface {
|
||||
// - CleanupCtx
|
||||
// - Expect
|
||||
// - ExpectNoError
|
||||
// - Run
|
||||
// - Logger
|
||||
//
|
||||
// Usually these methods would be stand-alone functions with a TContext
|
||||
@ -337,6 +346,9 @@ func InitCtx(ctx context.Context, tb TB, _ ...InitOption) TContext {
|
||||
// })
|
||||
//
|
||||
// WithTB sets up cancellation for the sub-test.
|
||||
//
|
||||
// A simpler API is to use TContext.Run as replacement
|
||||
// for [testing.T.Run].
|
||||
func WithTB(parentCtx TContext, tb TB) TContext {
|
||||
tCtx := InitCtx(parentCtx, tb)
|
||||
tCtx = WithCancel(tCtx)
|
||||
@ -350,6 +362,27 @@ func WithTB(parentCtx TContext, tb TB) TContext {
|
||||
return tCtx
|
||||
}
|
||||
|
||||
// run implements the different Run methods. It's not an exported
|
||||
// method because tCtx.Run is more discoverable (same usage as
|
||||
// with normal Go).
|
||||
func run(tCtx TContext, name string, cb func(tCtx TContext)) bool {
|
||||
tCtx.Helper()
|
||||
switch tb := tCtx.TB().(type) {
|
||||
case interface {
|
||||
Run(string, func(t *testing.T)) bool
|
||||
}:
|
||||
return tb.Run(name, func(t *testing.T) { cb(WithTB(tCtx, t)) })
|
||||
case interface {
|
||||
Run(string, func(t *testing.B)) bool
|
||||
}:
|
||||
return tb.Run(name, func(b *testing.B) { cb(WithTB(tCtx, b)) })
|
||||
default:
|
||||
tCtx.Fatalf("Run not implemented, underlying %T does not support it", tCtx.TB())
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// WithContext constructs a new TContext with a different Context instance.
|
||||
// This can be used in callbacks which receive a Context, for example
|
||||
// from Gomega:
|
||||
@ -439,6 +472,10 @@ func cleanupCtx(tCtx TContext, cb func(TContext)) {
|
||||
})
|
||||
}
|
||||
|
||||
func (cCtx tContext) Run(name string, cb func(tCtx TContext)) bool {
|
||||
return run(cCtx, name, cb)
|
||||
}
|
||||
|
||||
func (tCtx tContext) Logger() klog.Logger {
|
||||
return klog.FromContext(tCtx)
|
||||
}
|
||||
|
@ -123,6 +123,33 @@ func TestWithTB(t *testing.T) {
|
||||
assert.Equal(t, apiextensions, tCtx.APIExtensions(), "APIExtensions")
|
||||
|
||||
tCtx.Cancel("test is complete")
|
||||
<-tCtx.Done()
|
||||
})
|
||||
|
||||
if err := tCtx.Err(); err != nil {
|
||||
t.Errorf("parent TContext should not have been cancelled: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRun(t *testing.T) {
|
||||
tCtx := ktesting.Init(t)
|
||||
|
||||
cfg := new(rest.Config)
|
||||
mapper := new(restmapper.DeferredDiscoveryRESTMapper)
|
||||
client := clientset.New(nil)
|
||||
dynamic := dynamic.New(nil)
|
||||
apiextensions := apiextensions.New(nil)
|
||||
tCtx = ktesting.WithClients(tCtx, cfg, mapper, client, dynamic, apiextensions)
|
||||
|
||||
tCtx.Run("sub", func(tCtx ktesting.TContext) {
|
||||
assert.Equal(t, cfg, tCtx.RESTConfig(), "RESTConfig")
|
||||
assert.Equal(t, mapper, tCtx.RESTMapper(), "RESTMapper")
|
||||
assert.Equal(t, client, tCtx.Client(), "Client")
|
||||
assert.Equal(t, dynamic, tCtx.Dynamic(), "Dynamic")
|
||||
assert.Equal(t, apiextensions, tCtx.APIExtensions(), "APIExtensions")
|
||||
|
||||
tCtx.Cancel("test is complete")
|
||||
<-tCtx.Done()
|
||||
})
|
||||
|
||||
if err := tCtx.Err(); err != nil {
|
||||
|
@ -102,6 +102,10 @@ func (wCtx withContext) ExpectNoError(err error, explain ...interface{}) {
|
||||
expectNoError(wCtx, err, explain...)
|
||||
}
|
||||
|
||||
func (cCtx withContext) Run(name string, cb func(tCtx TContext)) bool {
|
||||
return run(cCtx, name, cb)
|
||||
}
|
||||
|
||||
func (wCtx withContext) Logger() klog.Logger {
|
||||
return klog.FromContext(wCtx)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user