Merge pull request #1739 from allenporter/flux-cmd-test-func

Make test harness more flexible with functions
pull/1740/head
Stefan Prodan 3 years ago committed by GitHub
commit 2bc64bf419
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -28,13 +28,11 @@ func TestCheckPre(t *testing.T) {
cmd := cmdTestCase{ cmd := cmdTestCase{
args: "check --pre", args: "check --pre",
wantError: false,
testClusterMode: ExistingClusterMode, testClusterMode: ExistingClusterMode,
templateValues: map[string]string{ assert: assertGoldenTemplateFile("testdata/check/check_pre.golden", map[string]string{
"clientVersion": clientVersion, "clientVersion": clientVersion,
"serverVersion": serverVersion, "serverVersion": serverVersion,
}, }),
goldenFile: "testdata/check/check_pre.golden",
} }
cmd.runTestCmd(t) cmd.runTestCmd(t)
} }

@ -49,7 +49,7 @@ func TestHelmReleaseFromGit(t *testing.T) {
for _, tc := range cases { for _, tc := range cases {
cmd := cmdTestCase{ cmd := cmdTestCase{
args: tc.args + " -n=" + namespace, args: tc.args + " -n=" + namespace,
goldenFile: tc.goldenFile, assert: assertGoldenFile(tc.goldenFile),
testClusterMode: ExistingClusterMode, testClusterMode: ExistingClusterMode,
} }
cmd.runTestCmd(t) cmd.runTestCmd(t)

@ -41,7 +41,7 @@ func TestImageScanning(t *testing.T) {
for _, tc := range cases { for _, tc := range cases {
cmd := cmdTestCase{ cmd := cmdTestCase{
args: tc.args + " -n=" + namespace, args: tc.args + " -n=" + namespace,
goldenFile: tc.goldenFile, assert: assertGoldenFile(tc.goldenFile),
testClusterMode: ExistingClusterMode, testClusterMode: ExistingClusterMode,
} }
cmd.runTestCmd(t) cmd.runTestCmd(t)

@ -49,7 +49,7 @@ func TestKustomizationFromGit(t *testing.T) {
for _, tc := range cases { for _, tc := range cases {
cmd := cmdTestCase{ cmd := cmdTestCase{
args: tc.args + " -n=" + namespace, args: tc.args + " -n=" + namespace,
goldenFile: tc.goldenFile, assert: assertGoldenFile(tc.goldenFile),
testClusterMode: ExistingClusterMode, testClusterMode: ExistingClusterMode,
} }
cmd.runTestCmd(t) cmd.runTestCmd(t)

@ -150,6 +150,87 @@ func NewTestEnvKubeManager(testClusterMode TestClusterMode) (*testEnvKubeManager
return nil, nil return nil, nil
} }
// Function that sets an expectation on the output of a command. Tests can
// either implement this directly or use a helper below.
type assertFunc func(output string, err error) error
// Assemble multiple assertFuncs into a single assertFunc
func assert(fns ...assertFunc) assertFunc {
return func(output string, err error) error {
for _, fn := range fns {
if assertErr := fn(output, err); assertErr != nil {
return assertErr
}
}
return nil
}
}
// Expect the command to run without error
func assertSuccess() assertFunc {
return func(output string, err error) error {
if err != nil {
return fmt.Errorf("Expected success but was error: %v", err)
}
return nil
}
}
// Expect the command to fail with the specified error
func assertError(expected string) assertFunc {
return func(output string, err error) error {
if err == nil {
return fmt.Errorf("Expected error but was success")
}
if expected != err.Error() {
return fmt.Errorf("Expected error '%v' but got '%v'", expected, err.Error())
}
return nil
}
}
// Expect the command to succeed with the expected test output.
func assertGoldenValue(expected string) assertFunc {
return assert(
assertSuccess(),
func(output string, err error) error {
diff := cmp.Diff(expected, output)
if diff != "" {
return fmt.Errorf("Mismatch from expected value (-want +got):\n%s", diff)
}
return nil
})
}
// Filename that contains the expected test output.
func assertGoldenFile(goldenFile string) assertFunc {
return assertGoldenTemplateFile(goldenFile, map[string]string{})
}
// Filename that contains the expected test output. The golden file is a template that
// is pre-processed with the specified templateValues.
func assertGoldenTemplateFile(goldenFile string, templateValues map[string]string) assertFunc {
goldenFileContents, fileErr := os.ReadFile(goldenFile)
return func(output string, err error) error {
if fileErr != nil {
return fmt.Errorf("Error reading golden file '%s': %s", goldenFile, fileErr)
}
var expectedOutput string
if len(templateValues) > 0 {
expectedOutput, err = executeGoldenTemplate(string(goldenFileContents), templateValues)
if err != nil {
return fmt.Errorf("Error executing golden template file '%s': %s", goldenFile, err)
}
} else {
expectedOutput = string(goldenFileContents)
}
if assertErr := assertGoldenValue(expectedOutput)(output, err); assertErr != nil {
return fmt.Errorf("Mismatch from golden file '%s': %v", goldenFile, assertErr)
}
return nil
}
}
type TestClusterMode int type TestClusterMode int
const ( const (
@ -162,18 +243,13 @@ const (
type cmdTestCase struct { type cmdTestCase struct {
// The command line arguments to test. // The command line arguments to test.
args string args string
// When true, the test expects the command to fail.
wantError bool
// String literal that contains the expected test output.
goldenValue string
// Filename that contains the expected test output.
goldenFile string
// Filename that contains yaml objects to load into Kubernetes
objectFile string
// TestClusterMode to bootstrap and testing, default to Fake // TestClusterMode to bootstrap and testing, default to Fake
testClusterMode TestClusterMode testClusterMode TestClusterMode
// TemplateValues enable template preprocessing for the golden file, or golden value // Tests use assertFunc to assert on an output, success or failure. This
templateValues map[string]string // can be a function defined by the test or existing function above.
assert assertFunc
// Filename that contains yaml objects to load into Kubernetes
objectFile string
} }
func (cmd *cmdTestCase) runTestCmd(t *testing.T) { func (cmd *cmdTestCase) runTestCmd(t *testing.T) {
@ -197,43 +273,9 @@ func (cmd *cmdTestCase) runTestCmd(t *testing.T) {
} }
} }
actual, err := executeCommand(cmd.args) actual, testErr := executeCommand(cmd.args)
if (err != nil) != cmd.wantError { if assertErr := cmd.assert(actual, testErr); assertErr != nil {
t.Fatalf("Expected error='%v', Got: %v", cmd.wantError, err) t.Error(assertErr)
}
if err != nil {
actual = err.Error()
}
var expected string
if cmd.goldenValue != "" {
if cmd.templateValues != nil {
expected, err = executeGoldenTemplate(cmd.goldenValue, cmd.templateValues)
if err != nil {
t.Fatalf("Error executing golden template: %s", err)
}
} else {
expected = cmd.goldenValue
}
}
if cmd.goldenFile != "" {
goldenFileContent, err := os.ReadFile(cmd.goldenFile)
if err != nil {
t.Fatalf("Error reading golden file: '%s'", err)
}
if cmd.templateValues != nil {
expected, err = executeGoldenTemplate(string(goldenFileContent), cmd.templateValues)
if err != nil {
t.Fatalf("Error executing golden template file '%s': %s", cmd.goldenFile, err)
}
} else {
expected = string(goldenFileContent)
}
}
diff := cmp.Diff(expected, actual)
if diff != "" {
t.Errorf("Mismatch from '%s' (-want +got):\n%s", cmd.goldenFile, diff)
} }
} }

@ -10,8 +10,7 @@ func TestTraceNoArgs(t *testing.T) {
cmd := cmdTestCase{ cmd := cmdTestCase{
args: "trace", args: "trace",
testClusterMode: TestEnvClusterMode, testClusterMode: TestEnvClusterMode,
wantError: true, assert: assertError("object name is required"),
goldenValue: "object name is required",
} }
cmd.runTestCmd(t) cmd.runTestCmd(t)
} }
@ -20,8 +19,7 @@ func TestTraceDeployment(t *testing.T) {
cmd := cmdTestCase{ cmd := cmdTestCase{
args: "trace podinfo -n podinfo --kind deployment --api-version=apps/v1", args: "trace podinfo -n podinfo --kind deployment --api-version=apps/v1",
testClusterMode: TestEnvClusterMode, testClusterMode: TestEnvClusterMode,
wantError: false, assert: assertGoldenFile("testdata/trace/deployment.txt"),
goldenFile: "testdata/trace/deployment.txt",
objectFile: "testdata/trace/deployment.yaml", objectFile: "testdata/trace/deployment.yaml",
} }
cmd.runTestCmd(t) cmd.runTestCmd(t)
@ -31,8 +29,7 @@ func TestTraceHelmRelease(t *testing.T) {
cmd := cmdTestCase{ cmd := cmdTestCase{
args: "trace podinfo -n podinfo --kind HelmRelease --api-version=helm.toolkit.fluxcd.io/v2beta1", args: "trace podinfo -n podinfo --kind HelmRelease --api-version=helm.toolkit.fluxcd.io/v2beta1",
testClusterMode: TestEnvClusterMode, testClusterMode: TestEnvClusterMode,
wantError: false, assert: assertGoldenFile("testdata/trace/helmrelease.txt"),
goldenFile: "testdata/trace/helmrelease.txt",
objectFile: "testdata/trace/helmrelease.yaml", objectFile: "testdata/trace/helmrelease.yaml",
} }
cmd.runTestCmd(t) cmd.runTestCmd(t)

@ -10,7 +10,7 @@ func TestVersion(t *testing.T) {
cmd := cmdTestCase{ cmd := cmdTestCase{
args: "--version", args: "--version",
testClusterMode: TestEnvClusterMode, testClusterMode: TestEnvClusterMode,
goldenValue: "flux version 0.0.0-dev.0\n", assert: assertGoldenValue("flux version 0.0.0-dev.0\n"),
} }
cmd.runTestCmd(t) cmd.runTestCmd(t)
} }

Loading…
Cancel
Save