This allows the use of a built-in provider to do things like mark a node as ready once all the controllers are spun up. The e2e tests now use this instead of waiting on the pod that the vk provider is deployed in to be marked ready (this was waiting on /stats/summary to be serving, which is racey).
86 lines
2.2 KiB
Go
86 lines
2.2 KiB
Go
package suite
|
|
|
|
import (
|
|
"reflect"
|
|
"runtime/debug"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
// TestFunc defines the test function in a test case
|
|
type TestFunc func(*testing.T)
|
|
|
|
// SetUpFunc sets up provider-specific resource in the test suite
|
|
type SetUpFunc func() error
|
|
|
|
// TeardownFunc tears down provider-specific resources from the test suite
|
|
type TeardownFunc func() error
|
|
|
|
// ShouldSkipTestFunc determines whether the test suite should skip certain tests
|
|
type ShouldSkipTestFunc func(string) bool
|
|
|
|
// TestSuite contains methods that defines the lifecycle of a test suite
|
|
type TestSuite interface {
|
|
Setup(t *testing.T)
|
|
Teardown()
|
|
}
|
|
|
|
// TestSkipper allows providers to skip certain tests
|
|
type TestSkipper interface {
|
|
ShouldSkipTest(string) bool
|
|
}
|
|
|
|
type testCase struct {
|
|
name string
|
|
f TestFunc
|
|
}
|
|
|
|
// Run runs tests registered in the test suite
|
|
func Run(t *testing.T, ts TestSuite) {
|
|
defer failOnPanic(t)
|
|
|
|
ts.Setup(t)
|
|
defer ts.Teardown()
|
|
|
|
// The implementation below is based on https://github.com/stretchr/testify
|
|
testFinder := reflect.TypeOf(ts)
|
|
tests := []testCase{}
|
|
for i := 0; i < testFinder.NumMethod(); i++ {
|
|
method := testFinder.Method(i)
|
|
if !isValidTestFunc(method) {
|
|
continue
|
|
}
|
|
|
|
test := testCase{
|
|
name: method.Name,
|
|
f: func(t *testing.T) {
|
|
defer failOnPanic(t)
|
|
if tSkipper, ok := ts.(TestSkipper); ok && tSkipper.ShouldSkipTest(method.Name) {
|
|
t.Skipf("Skipped due to shouldSkipTest()")
|
|
}
|
|
method.Func.Call([]reflect.Value{reflect.ValueOf(ts), reflect.ValueOf(t)})
|
|
},
|
|
}
|
|
tests = append(tests, test)
|
|
}
|
|
|
|
for _, test := range tests {
|
|
t.Run(test.name, test.f)
|
|
}
|
|
}
|
|
|
|
// failOnPanic recovers panic occurred in the test suite and marks the test / test suite as failed
|
|
func failOnPanic(t *testing.T) {
|
|
if r := recover(); r != nil {
|
|
t.Fatalf("%v\n%s", r, debug.Stack())
|
|
}
|
|
}
|
|
|
|
// isValidTestFunc determines whether or not a given method is a valid test function
|
|
func isValidTestFunc(method reflect.Method) bool {
|
|
return strings.HasPrefix(method.Name, "Test") && // Test function name must start with "Test",
|
|
method.Type.NumIn() == 2 && // the number of function input should be 2 (*TestSuite ts and t *testing.T),
|
|
method.Type.In(1) == reflect.TypeOf(&testing.T{}) &&
|
|
method.Type.NumOut() == 0 // and the number of function output should be 0
|
|
}
|