feat: show actual vs expected on fail
This commit is contained in:
+29
-1
@@ -2,6 +2,7 @@ package mire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/fs"
|
||||
@@ -38,6 +39,15 @@ type testFixtureFiles struct {
|
||||
outPath string
|
||||
}
|
||||
|
||||
type testMismatchError struct {
|
||||
expected []byte
|
||||
actual []byte
|
||||
}
|
||||
|
||||
func (e *testMismatchError) Error() string {
|
||||
return "output differed"
|
||||
}
|
||||
|
||||
// RunTests replays all scenarios under the configured test directory.
|
||||
func RunTests(path string) error {
|
||||
return runTests(path, testIO{
|
||||
@@ -89,6 +99,10 @@ func runTests(path string, tio testIO) error {
|
||||
elapsed := time.Since(start)
|
||||
summary.failed++
|
||||
output.Fprintf(tio.out, "%s %s (%s): %v\n", output.Label("FAIL", output.Fail), scenario.relPath, formatElapsed(elapsed), err)
|
||||
var mismatchErr *testMismatchError
|
||||
if errors.As(err, &mismatchErr) {
|
||||
writeScenarioMismatch(tio.out, mismatchErr)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -256,12 +270,26 @@ func replayScenario(scenario testScenario, shellPath string, _ testIO, sandboxCo
|
||||
}
|
||||
|
||||
if !bytes.Equal(got, want) {
|
||||
return fmt.Errorf("output differed")
|
||||
return &testMismatchError{
|
||||
expected: want,
|
||||
actual: got,
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func writeScenarioMismatch(w io.Writer, mismatch *testMismatchError) {
|
||||
output.Fprintf(w, "Expected:\n%s", string(mismatch.expected))
|
||||
if len(mismatch.expected) == 0 || mismatch.expected[len(mismatch.expected)-1] != '\n' {
|
||||
output.Fprintf(w, "\n")
|
||||
}
|
||||
output.Fprintf(w, "Actual:\n%s", string(mismatch.actual))
|
||||
if len(mismatch.actual) == 0 || mismatch.actual[len(mismatch.actual)-1] != '\n' {
|
||||
output.Fprintf(w, "\n")
|
||||
}
|
||||
}
|
||||
|
||||
func trimReplayOutputToMarker(data []byte, shellPath string) ([]byte, error) {
|
||||
idx := bytes.Index(data, []byte(compareOutputMarker))
|
||||
if idx == -1 {
|
||||
|
||||
@@ -157,6 +157,45 @@ func TestReplayScenarioFailsWhenCompareMarkerMissing(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunTestsShowsExpectedAndActualForMismatchedScenario(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
testDir := filepath.Join(root, "e2e")
|
||||
testutil.AddFakeRecordDependencies(t, "script")
|
||||
t.Setenv("FAKE_SCRIPT_ECHO_STDIN", "1")
|
||||
|
||||
testutil.WriteFile(t, filepath.Join(root, "mire.toml"), testutil.ValidConfigContent("e2e"))
|
||||
mustWriteRecordShell(t, testDir)
|
||||
testutil.WriteScenarioFixtures(t, filepath.Join(testDir, "suite", "spec"), "echo two\n", "echo one\n")
|
||||
|
||||
var stdout bytes.Buffer
|
||||
var stderr bytes.Buffer
|
||||
err := testutil.WithWorkingDir(t, root, func() error {
|
||||
return runTests("", testIO{
|
||||
out: &stdout,
|
||||
err: &stderr,
|
||||
})
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("runTests() error = %v", err)
|
||||
}
|
||||
if stderr.String() != "" {
|
||||
t.Fatalf("stderr = %q, want empty", stderr.String())
|
||||
}
|
||||
|
||||
for _, want := range []string{
|
||||
"RUN suite/spec",
|
||||
"FAIL suite/spec (",
|
||||
"output differed",
|
||||
"Expected:\necho one\n",
|
||||
"Actual:\necho two\n",
|
||||
"Summary: total=1 passed=0 failed=1",
|
||||
} {
|
||||
if !strings.Contains(stdout.String(), want) {
|
||||
t.Fatalf("stdout = %q, want substring %q", stdout.String(), want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDiscoverTestScenariosUsesDisplayRootForRelativePaths(t *testing.T) {
|
||||
testDir := filepath.Join(t.TempDir(), "e2e")
|
||||
scopedDir := filepath.Join(testDir, "nested")
|
||||
|
||||
Reference in New Issue
Block a user