* Rename VK to chewong for development purpose * Rename basic_test.go to basic.go * Add e2e.go and suite.go * Disable tests in node.go * End to end tests are now importable as a testing suite * Remove 'test' from test files * Add documentations * Rename chewong back to virtual-kubelet * Change 'Testing Suite' to 'Test Suite' * Add the ability to skip certain testss * Add unit tests for suite.go * Add README.md for importable e2e test suite * VK implementation has to be based on VK v1.0.0 * Stricter checks on validating test functions * Move certain files back to internal folder * Add WatchTimeout as a config field * Add slight modifications
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()
|
|
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()
|
|
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
|
|
}
|