dc9c78b210
This fixes a bug where `make cover` was missing packages. The target now covers all code except for code placed in the top level package (such as main.go) and anything placed in the testutils directory. This also fixes minor issues with the Dockerfile and the coverage_check script Note that this commit also strives to increase code coverage beyond the 80% margin Change-Id: I9e1cbcf841cc869345a00f05e39774cb3da10065
123 lines
3.4 KiB
Go
123 lines
3.4 KiB
Go
package testutil
|
|
|
|
import (
|
|
"bytes"
|
|
"flag"
|
|
"io/ioutil"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/spf13/cobra"
|
|
)
|
|
|
|
// UpdateGolden writes out the golden files with the latest values, rather than failing the test.
|
|
var shouldUpdateGolden = flag.Bool("update", false, "update golden files")
|
|
|
|
const (
|
|
testdataDir = "testdata"
|
|
goldenDirSuffix = "GoldenOutput"
|
|
goldenFileSuffix = ".golden"
|
|
)
|
|
|
|
// CmdTest is a command to be run on the command line as a test
|
|
type CmdTest struct {
|
|
// The name of the test. This will be used when generating golden
|
|
// files
|
|
Name string
|
|
|
|
// The values that would be inputted to airshipctl as commands, flags,
|
|
// and arguments. The initial "airshipctl" is implied
|
|
CmdLine string
|
|
|
|
// The instatiated version of the root airshipctl command to test
|
|
Cmd *cobra.Command
|
|
|
|
// The expected error
|
|
Error error
|
|
}
|
|
|
|
// RunTest either asserts that a specific command's output matches the expected
|
|
// output from its golden file, or generates golden files if the -update flag
|
|
// is passed
|
|
func RunTest(t *testing.T, test *CmdTest) {
|
|
cmd := test.Cmd
|
|
|
|
actual := &bytes.Buffer{}
|
|
cmd.SetOutput(actual)
|
|
|
|
args := strings.Fields(test.CmdLine)
|
|
cmd.SetArgs(args)
|
|
|
|
err := cmd.Execute()
|
|
checkError(t, err, test.Error)
|
|
|
|
if *shouldUpdateGolden {
|
|
updateGolden(t, test, actual.Bytes())
|
|
} else {
|
|
assertEqualGolden(t, test, actual.Bytes())
|
|
}
|
|
}
|
|
|
|
// ReadFixtureBytes is a convenience function for opening a test fixture
|
|
func ReadFixtureBytes(t *testing.T, filename string) []byte {
|
|
fixtureData, err := ioutil.ReadFile(filename)
|
|
if err != nil {
|
|
t.Fatalf("Unexpected error while reading fixture at %s: %s", filename, err.Error())
|
|
}
|
|
return fixtureData
|
|
}
|
|
|
|
// ReadFixtureString is a convenience function for opening a test fixture
|
|
func ReadFixtureString(t *testing.T, filename string) string {
|
|
return string(ReadFixtureBytes(t, filename))
|
|
}
|
|
|
|
func updateGolden(t *testing.T, test *CmdTest, actual []byte) {
|
|
goldenDir := filepath.Join(testdataDir, t.Name()+goldenDirSuffix)
|
|
if err := os.MkdirAll(goldenDir, 0775); err != nil {
|
|
t.Fatalf("Failed to create golden directory %s: %s", goldenDir, err)
|
|
}
|
|
t.Logf("Created %s", goldenDir)
|
|
goldenFilePath := filepath.Join(goldenDir, test.Name+goldenFileSuffix)
|
|
t.Logf("Updating golden file: %s", goldenFilePath)
|
|
if err := ioutil.WriteFile(goldenFilePath, normalize(actual), 0666); err != nil {
|
|
t.Fatalf("Failed to update golden file: %s", err)
|
|
}
|
|
}
|
|
|
|
func assertEqualGolden(t *testing.T, test *CmdTest, actual []byte) {
|
|
goldenDir := filepath.Join(testdataDir, t.Name()+goldenDirSuffix)
|
|
goldenFilePath := filepath.Join(goldenDir, test.Name+goldenFileSuffix)
|
|
golden, err := ioutil.ReadFile(goldenFilePath)
|
|
if err != nil {
|
|
t.Fatalf("Failed while reading golden file: %s", err)
|
|
}
|
|
if !bytes.Equal(actual, golden) {
|
|
errFmt := "Output does not match golden file: %s\nEXPECTED:\n%s\nGOT:\n%s"
|
|
t.Errorf(errFmt, goldenFilePath, string(golden), string(actual))
|
|
}
|
|
}
|
|
|
|
func checkError(t *testing.T, actual, expected error) {
|
|
if expected == nil {
|
|
if actual == nil {
|
|
return
|
|
}
|
|
t.Fatalf("Unexpected error: %q", actual.Error())
|
|
}
|
|
|
|
if actual == nil {
|
|
t.Fatalf("Expected error %q, but got nil", expected.Error())
|
|
}
|
|
|
|
if actual.Error() != expected.Error() {
|
|
t.Fatalf("Expected error %q, but got %q", expected.Error(), actual.Error())
|
|
}
|
|
}
|
|
|
|
func normalize(in []byte) []byte {
|
|
return bytes.Replace(in, []byte("\r\n"), []byte("\n"), -1)
|
|
}
|