Skip to content

Commit 487172e

Browse files
authored
settings: support for supplying cmp.Option to some assertions (#92)
* settings: introduce concept of settings * settings: support for supplying cmp.Option settings * maps: bring back mapeq func * settings: rename files * readme: update readme with options * docs: add doc strings for settings
1 parent 6219c20 commit 487172e

23 files changed

Lines changed: 1009 additions & 733 deletions

README.md

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@ There are four key packages,
1818

1919
### Changes
2020

21+
:crown: v0.6.0 adds support for custom `cmp.Option` values
22+
23+
- Adds ability to customize cmp.Equal behavior via cmp.Option arguments
24+
- Adds assertions for existence of single map key
25+
- Fixes some error outputs
26+
2127
:rocket: v0.5.0 contains new packages `wait` and `portal`
2228

2329
- Package for waiting on conditionals
@@ -85,7 +91,8 @@ Functions like `Eq` and `Contains` work on any type, using the `cmp.Equal` or `r
8591
functions to determine equivalence. Although this is the easiest / most compatible way
8692
to "just compare stuff", it the least deterministic way of comparing instances of a type.
8793
Changes to the underlying types may cause unexpected changes in their equivalence (e.g.
88-
the addition of unexported fields, function field types, etc.).
94+
the addition of unexported fields, function field types, etc.). Assertions that make
95+
use of `cmp.Equal` configured with custom `cmp.Option` values.
8996

9097
#### output
9198

@@ -103,6 +110,25 @@ a failure. Sometimes it is helpful for a test case to continue running even thou
103110
occurred (e.g. contains cleanup logic not captured via a `t.Cleanup` function). Other times it
104111
make sense to fail immediately and stop the test case execution.
105112

113+
### go-cmp Options
114+
115+
The test assertions that rely on `cmp.Equal` can be customized in how objects
116+
are compared by [specifying custom](https://github.com/google/go-cmp/blob/master/cmp/options.go#L16)
117+
`cmp.Option` values. These can be configured through `test.Cmp` and `must.Cmp` helpers.
118+
Google provides some common custom behaviors in the [cmdopts](https://github.com/google/go-cmp/tree/master/cmp/cmpopts)
119+
package.
120+
121+
Here is an example of comparing two slices, but using a custom Option to sort
122+
the slices so that the order of elements does not matter.
123+
124+
```go
125+
a := []int{3, 5, 1, 6, 7}
126+
b := []int{1, 7, 6, 3, 5}
127+
must.Eq(t, a, b, must.Cmp(cmpopts.SortSlices(func(i, j int) bool {
128+
return i < j
129+
})))
130+
```
131+
106132
### PostScripts
107133

108134
Some tests are large and complex (like e2e testing). It can be helpful to provide more context

assert.go

Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,12 @@
1-
// Package test provides a modern generic testing assertions library.
21
package test
32

4-
import (
5-
"strings"
6-
7-
"github.com/shoenig/test/internal/assertions"
8-
)
9-
103
// T is the minimal set of functions to be implemented by any testing framework
114
// compatible with the test package.
125
type T interface {
136
Helper()
147
Errorf(string, ...any)
158
}
169

17-
func passing(result string) bool {
18-
return result == ""
19-
}
20-
21-
func fail(t T, msg string, scripts ...PostScript) {
22-
c := assertions.Caller()
23-
s := c + msg + "\n" + run(scripts...)
24-
t.Errorf("\n" + strings.TrimSpace(s) + "\n")
25-
}
26-
27-
func invoke(t T, result string, scripts ...PostScript) {
28-
result = strings.TrimSpace(result)
29-
if !passing(result) {
30-
fail(t, result, scripts...)
31-
}
10+
func errorf(t T, msg string, args ...any) {
11+
t.Errorf(msg, args...)
3212
}

assert_test.go

Lines changed: 0 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -3,41 +3,8 @@ package test
33
import (
44
"fmt"
55
"strings"
6-
"testing"
76
)
87

9-
type testScript struct {
10-
label string
11-
content string
12-
}
13-
14-
func (ts *testScript) Label() string {
15-
return ts.label
16-
}
17-
18-
func (ts *testScript) Content() string {
19-
return ts.content
20-
}
21-
22-
type internalTest struct {
23-
t *testing.T
24-
trigger bool
25-
helper bool
26-
exp string
27-
capture string
28-
}
29-
30-
func (it *internalTest) PS(s string) PostScript {
31-
return &testScript{
32-
label: "label: " + s,
33-
content: "content: " + s,
34-
}
35-
}
36-
37-
func (it *internalTest) Helper() {
38-
it.helper = true
39-
}
40-
418
func (it *internalTest) Errorf(s string, args ...any) {
429
if !it.trigger {
4310
it.trigger = true
@@ -46,35 +13,3 @@ func (it *internalTest) Errorf(s string, args ...any) {
4613
it.capture = msg
4714
fmt.Println(msg)
4815
}
49-
50-
func (it *internalTest) assert() {
51-
if !it.helper {
52-
it.t.Fatal("should be marked as helper")
53-
}
54-
if !it.trigger {
55-
it.t.Fatalf("condition expected to trigger; did not")
56-
}
57-
if !strings.Contains(it.capture, it.exp) {
58-
it.t.Fatalf("expected message %q in output, got %q", it.exp, it.capture)
59-
}
60-
}
61-
62-
func (it *internalTest) post() {
63-
if !strings.Contains(it.capture, "PostScript |") {
64-
it.t.Fatal("expected post-script output")
65-
}
66-
}
67-
68-
func newCase(t *testing.T, msg string) *internalTest {
69-
return &internalTest{
70-
t: t,
71-
trigger: false,
72-
exp: msg,
73-
}
74-
}
75-
76-
func newCapture(t *testing.T) *internalTest {
77-
return &internalTest{
78-
t: t,
79-
}
80-
}

0 commit comments

Comments
 (0)