Skip to content

Commit da09caf

Browse files
committed
feature: string equal by line transformers
1 parent a08cfac commit da09caf

File tree

3 files changed

+36
-2
lines changed

3 files changed

+36
-2
lines changed

README.md

+12
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,18 @@ chain. In addition, `is.Error` also supports the target error to be `nil`. In th
114114
behaves identical to `is.Error(v)`. This allows an easy and convenient way of writing table based tests that
115115
expect both error and non-error conditions.
116116

117+
### `EqualToStringByLines`
118+
119+
The `EqualToStringByLines` expectation effectively works like `EqualTo` on strings. The difference arises when
120+
the two strings are _not_ equal. If both strings are longer, multiline strings, catching a small difference
121+
can be hard to do. In those situations `EqualToStringByLines` helps by reporting differences on a per-line
122+
basis. This makes locating the differences and fixing code/adjusting the tests much easier. In addition,
123+
`EqualToStringByLines` supports _transformers_ - simple functions that preprocess each line - before the
124+
transformation results are compared. This makes it much easisier to place expected string values in code as
125+
multiline raw string literals. Those string literal's lines usually follow the current indentation depth
126+
which makes them unequal to a (flat) given value. Using the `Dedent` transformer can easily compensate for
127+
this keeping the expectation indented "correcly" (which regards to code formatting) but the test won't fail.
128+
117129
### Deep equality
118130

119131
The `is.DeepEqualTo` expectation is special as compared to the other ones. It uses a recursive algorithm to

is/string.go

+23-2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package is
22

33
import (
44
"strings"
5+
"unicode"
56

67
"github.com/halimath/expect"
78
)
@@ -51,10 +52,22 @@ func StringWithSuffix(got, want string) expect.Expectation {
5152
})
5253
}
5354

55+
// Dedent is intended to be used as a transformer passed to [EqualToStringByLines].
56+
// It removes any prefix whitespace from s thus dedenting each line. This is
57+
// especially usefull if the expected value for a test is written in code as an
58+
// indented multiline raw string literal but the actual lines are not indented.
59+
func DedentLines(s string) string {
60+
return strings.TrimLeftFunc(s, unicode.IsSpace)
61+
}
62+
5463
// EqualToStringByLines compares got and want line by line and reports different
5564
// lines one at a time. This makes it easiert to understand failed expectations
5665
// when comparing large strings.
57-
func EqualToStringByLines(got, want string) expect.Expectation {
66+
//
67+
// transformers are applied to all lines, both those obtained from got and want.
68+
// transformers are applied in order (iteratively) and the final transformation
69+
// result is used for comparison.
70+
func EqualToStringByLines(got, want string, transformers ...func(string) string) expect.Expectation {
5871
return expect.ExpectFunc(func(t expect.TB) {
5972
t.Helper()
6073

@@ -70,7 +83,15 @@ func EqualToStringByLines(got, want string) expect.Expectation {
7083
limit := min(len(gotLines), len(wantLines))
7184

7285
for i := 0; i < limit; i++ {
73-
if wantLines[i] != gotLines[i] {
86+
gotLine := gotLines[i]
87+
wantLine := wantLines[i]
88+
89+
for _, transformer := range transformers {
90+
gotLine = transformer(gotLine)
91+
wantLine = transformer(wantLine)
92+
}
93+
94+
if gotLine != wantLine {
7495
t.Errorf("at line %d: wanted\n%q\nbut got\n%q", i, wantLines[i], gotLines[i])
7596
if lenghtsDiffer {
7697
return

is/string_test.go

+1
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ func TestEqualToStringByLines(t *testing.T) {
7979
EqualToStringByLines("foo\nbar", "foo").Expect(&tb)
8080
EqualToStringByLines("foo", "foo\nbar").Expect(&tb)
8181
EqualToStringByLines("foo\nbar", "foo\nspam").Expect(&tb)
82+
EqualToStringByLines("foo\n bar", "foo\n\tbar", DedentLines).Expect(&tb)
8283

8384
if !reflect.DeepEqual(tb, testhelper.TB{
8485
ErrFlag: true,

0 commit comments

Comments
 (0)