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{
args: "check --pre",
wantError: false,
testClusterMode: ExistingClusterMode,
templateValues: map[string]string{
assert: assertGoldenTemplateFile("testdata/check/check_pre.golden", map[string]string{
"clientVersion": clientVersion,
"serverVersion": serverVersion,
},
goldenFile: "testdata/check/check_pre.golden",
}),
}
cmd.runTestCmd(t)
}

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

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

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

@ -150,6 +150,87 @@ func NewTestEnvKubeManager(testClusterMode TestClusterMode) (*testEnvKubeManager
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
const (
@ -162,18 +243,13 @@ const (
type cmdTestCase struct {
// The command line arguments to test.
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 TestClusterMode
// TemplateValues enable template preprocessing for the golden file, or golden value
templateValues map[string]string
// Tests use assertFunc to assert on an output, success or failure. This
// 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) {
@ -197,43 +273,9 @@ func (cmd *cmdTestCase) runTestCmd(t *testing.T) {
}
}
actual, err := executeCommand(cmd.args)
if (err != nil) != cmd.wantError {
t.Fatalf("Expected error='%v', Got: %v", cmd.wantError, err)
}
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)
actual, testErr := executeCommand(cmd.args)
if assertErr := cmd.assert(actual, testErr); assertErr != nil {
t.Error(assertErr)
}
}

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

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

Loading…
Cancel
Save