diff options
| author | Stefan Majewsky <majewsky@gmx.net> | 2026-06-22 11:37:02 +0200 |
|---|---|---|
| committer | Stefan Majewsky <majewsky@gmx.net> | 2026-06-22 11:38:31 +0200 |
| commit | 8804729561d8e5edd7179f494d89c620459d319f (patch) | |
| tree | a6d2979a13c04dff42c3d9874c171531dd30b081 | |
| parent | 99fd6c3185e810eb8b18c5f3fe582a3e91463608 (diff) | |
| download | go-gg-8804729561d8e5edd7179f494d89c620459d319f.tar.gz | |
assert: represent string literals with backticks when appropriate
| -rw-r--r-- | CHANGELOG.md | 6 | ||||
| -rw-r--r-- | assert/equal.go | 35 | ||||
| -rw-r--r-- | assert/equal_test.go | 13 |
3 files changed, 43 insertions, 11 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 592bbae..391cadb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,12 @@ SPDX-FileCopyrightText: 2026 Stefan Majewsky <majewsky@gmx.net> SPDX-License-Identifier: Apache-2.0 --> +# v1.10.2 (TBD) + +Changes: + +- In assert.Equal output, present string literals with backticks instead of quotes when it makes the output more readable. + # v1.10.1 (2026-06-20) Changes: diff --git a/assert/equal.go b/assert/equal.go index 2cafb44..1c8004c 100644 --- a/assert/equal.go +++ b/assert/equal.go @@ -8,6 +8,7 @@ import ( "reflect" "slices" "strings" + "unicode" "unicode/utf8" "go.xyrillian.de/gg/internal/path" @@ -76,6 +77,18 @@ func formatValue(v reflect.Value) string { return fmt.Sprintf("%#v", v) } +func formatString(str string) string { + if strings.ContainsRune(str, '"') && !strings.ContainsRune(str, '`') && !strings.ContainsFunc(str, isControlCharacter) { + return fmt.Sprintf("`%s`", str) + } else { + return fmt.Sprintf("%q", str) + } +} + +func isControlCharacter(r rune) bool { + return unicode.Is(unicode.C, r) +} + func findInequalities(p path.Path, actual, expected reflect.Value) (result []inequality) { // try to recurse into structured type to find the specific location of the inequality // (thus producing a more succinct error message esp. with large and deeply nested structures) @@ -98,6 +111,15 @@ func findInequalities(p path.Path, actual, expected reflect.Value) (result []ine result = findInequalities(subpath, actualElem, expectedElem) } } + case reflect.String: + // string types do not allow structured recursion, but they have a special case for formatting + actualStr := actual.Convert(reflect.TypeFor[string]()).Interface().(string) + expectedStr := expected.Convert(reflect.TypeFor[string]()).Interface().(string) + return []inequality{{ + Pointer: p.AsGoExpression("actual"), + Actual: formatString(actualStr), + Expected: formatString(expectedStr), + }} } // if we do not have a recursion method for the type in question, @@ -118,8 +140,8 @@ func findInequalitiesInArrayOrSlice(p path.Path, actual, expected reflect.Value) if utf8.Valid(actualPayload) && utf8.Valid(expectedPayload) { return []inequality{{ Pointer: p.AsGoExpression("actual"), - Actual: formatByteSliceViaString(actualPayload), - Expected: formatByteSliceViaString(expectedPayload), + Actual: fmt.Sprintf(`[]byte(%s)`, formatString(string(actualPayload))), + Expected: fmt.Sprintf(`[]byte(%s)`, formatString(string(expectedPayload))), }} } } @@ -166,15 +188,6 @@ func findInequalitiesInArrayOrSlice(p path.Path, actual, expected reflect.Value) return result } -func formatByteSliceViaString(buf []byte) string { - str := string(buf) - if strings.Contains(str, `"`) && !strings.Contains(str, "`") { - return fmt.Sprintf("[]byte(`%s`)", str) - } else { - return fmt.Sprintf("[]byte(%q)", str) - } -} - func buildSingleInequalityForArrayOrSlice(p path.Path, actual, expected reflect.Value) inequality { // This is a helper for findInequalitiesInArrayOrSlice() that reports only a single inequality for the entire thing. // But it still tries to be clever, and will omit the longest common prefix and suffix to shorten the output. diff --git a/assert/equal_test.go b/assert/equal_test.go index df6fd70..3872ab7 100644 --- a/assert/equal_test.go +++ b/assert/equal_test.go @@ -31,6 +31,19 @@ func TestEqual(t *testing.T) { assert.Equal(t, false, true) }, `expected true, but got false`) + // scalars: check that string values are formatted with backticks when it makes the output nicer + expectErrors(t, func(t assert.TestingTB) { + assert.Equal(t, "bar", "foo") + assert.Equal(t, "Please run `rm -rf /`.", "Please run `echo hello`.") + assert.Equal(t, `{"foo":1,"bar":3}`, `{"foo":1,"bar":2}`) + assert.Equal(t, "\x1B[1;31mError\x1B[0m", "\x1B[1;32mSuccess\x1B[0m") + }, strings.Join([]string{ + `expected "foo", but got "bar"`, + "expected \"Please run `echo hello`.\", but got \"Please run `rm -rf /`.\"", + "expected `{\"foo\":1,\"bar\":2}`, but got `{\"foo\":1,\"bar\":3}`", + `expected "\x1b[1;32mSuccess\x1b[0m", but got "\x1b[1;31mError\x1b[0m"`, + }, "\n")) + // basic test for slices correctSlice := []int{1, 2, 3} wrongSlice := []int{1, 42, 3} |
