wire: add error string assertions in tests (google/go-cloud#149)
out.txts that start with "ERROR" can now include substrings to assert exist in the error messages, one per line. This gives a very coarse-grained way of testing for error message quality. It is not a substitute for manual verification, but gives a "good enough" sanity check that relevant details are reported. Updates google/go-cloud#5
This commit is contained in:
1
internal/wire/testdata/Cycle/out.txt
vendored
1
internal/wire/testdata/Cycle/out.txt
vendored
@@ -1 +1,2 @@
|
|||||||
ERROR
|
ERROR
|
||||||
|
cycle
|
||||||
|
|||||||
1
internal/wire/testdata/EmptyVar/out.txt
vendored
1
internal/wire/testdata/EmptyVar/out.txt
vendored
@@ -1 +1,2 @@
|
|||||||
ERROR
|
ERROR
|
||||||
|
not a provider
|
||||||
|
|||||||
@@ -1 +1,3 @@
|
|||||||
ERROR
|
ERROR
|
||||||
|
foo.Foo
|
||||||
|
conflicts with provider
|
||||||
|
|||||||
@@ -1 +1,3 @@
|
|||||||
ERROR
|
ERROR
|
||||||
|
no provider found
|
||||||
|
Fooer
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
ERROR
|
ERROR
|
||||||
|
unexported identifier privateMsg
|
||||||
|
|||||||
@@ -74,8 +74,16 @@ func TestWire(t *testing.T) {
|
|||||||
defer t.Logf("wire_gen.go:\n%s", gen)
|
defer t.Logf("wire_gen.go:\n%s", gen)
|
||||||
}
|
}
|
||||||
if len(errs) > 0 {
|
if len(errs) > 0 {
|
||||||
|
for _, e := range errs {
|
||||||
|
t.Log(e)
|
||||||
|
}
|
||||||
if !test.wantError {
|
if !test.wantError {
|
||||||
t.Fatalf("wirego: %v", errs)
|
t.Fatal("Did not expect errors.")
|
||||||
|
}
|
||||||
|
for _, s := range test.wantErrorStrings {
|
||||||
|
if !errorListContains(errs, s) {
|
||||||
|
t.Errorf("Errors did not contain %q", s)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -269,7 +277,9 @@ type testCase struct {
|
|||||||
pkg string
|
pkg string
|
||||||
goFiles map[string][]byte
|
goFiles map[string][]byte
|
||||||
wantOutput []byte
|
wantOutput []byte
|
||||||
|
|
||||||
wantError bool
|
wantError bool
|
||||||
|
wantErrorStrings []string
|
||||||
}
|
}
|
||||||
|
|
||||||
// loadTestCase reads a test case from a directory.
|
// loadTestCase reads a test case from a directory.
|
||||||
@@ -279,8 +289,10 @@ type testCase struct {
|
|||||||
// root/
|
// root/
|
||||||
// pkg file containing the package name containing the inject function
|
// pkg file containing the package name containing the inject function
|
||||||
// (must also be package main)
|
// (must also be package main)
|
||||||
// out.txt file containing the expected output, or the magic string "ERROR"
|
// out.txt file containing the expected output, or starting with the
|
||||||
// if this test should cause generation to fail
|
// magic line "ERROR" if this test should cause generation to
|
||||||
|
// fail (any subsequent lines are substrings that should
|
||||||
|
// appear in the errors).
|
||||||
// ... any Go files found recursively placed under GOPATH/src/...
|
// ... any Go files found recursively placed under GOPATH/src/...
|
||||||
func loadTestCase(root string, wireGoSrc []byte) (*testCase, error) {
|
func loadTestCase(root string, wireGoSrc []byte) (*testCase, error) {
|
||||||
name := filepath.Base(root)
|
name := filepath.Base(root)
|
||||||
@@ -292,9 +304,8 @@ func loadTestCase(root string, wireGoSrc []byte) (*testCase, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("load test case %s: %v", name, err)
|
return nil, fmt.Errorf("load test case %s: %v", name, err)
|
||||||
}
|
}
|
||||||
wantError := false
|
wantErrorStrings, wantError := parseGoldenOutput(out)
|
||||||
if bytes.Equal(bytes.TrimSpace(out), []byte("ERROR")) {
|
if wantError {
|
||||||
wantError = true
|
|
||||||
out = nil
|
out = nil
|
||||||
}
|
}
|
||||||
goFiles := map[string][]byte{
|
goFiles := map[string][]byte{
|
||||||
@@ -327,6 +338,7 @@ func loadTestCase(root string, wireGoSrc []byte) (*testCase, error) {
|
|||||||
goFiles: goFiles,
|
goFiles: goFiles,
|
||||||
wantOutput: out,
|
wantOutput: out,
|
||||||
wantError: wantError,
|
wantError: wantError,
|
||||||
|
wantErrorStrings: wantErrorStrings,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -576,3 +588,25 @@ func runDiff(a, b []byte) ([]byte, error) {
|
|||||||
out, err := c.Output()
|
out, err := c.Output()
|
||||||
return out, err
|
return out, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func parseGoldenOutput(out []byte) (errorStrings []string, wantError bool) {
|
||||||
|
const errorPrefix = "ERROR\n"
|
||||||
|
if !bytes.HasPrefix(out, []byte(errorPrefix)) {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
// Skip past first line.
|
||||||
|
out = out[len(errorPrefix):]
|
||||||
|
// Remove any leading or trailing blank lines.
|
||||||
|
out = bytes.Trim(out[len(errorPrefix):], "\n")
|
||||||
|
// Split lines.
|
||||||
|
return strings.Split(string(out), "\n"), true
|
||||||
|
}
|
||||||
|
|
||||||
|
func errorListContains(errs []error, substr string) bool {
|
||||||
|
for _, e := range errs {
|
||||||
|
if strings.Contains(e.Error(), substr) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user