Testify frequently sees requests for new assertions, and we are trying to make the API more consistent in v2.0.0. It's not always clear what should be included (as evidenced by some of the more clunky functions already in the API). I propose that we should write as a wiki page or maybe a markdown file somewhere; the agreed standards which an assertion should meet before it is included in the API.
I've written a draft. It is only my own opinions so please do critique it rigorously. I expect there are good assertions in the API now that contravene some of these ideas.
Proposed Assertion GuidelinesThis document is a set of guidelines for the inclusion of the existing and any new assertion functions in the v2.0.0 release.
LanguageThe function name and argument list should lead to use which documents the intended assertion in reasonably good but terse English.
Good ✅assert.Equal(t, got, 5) assert.Between(t, got, 2, 10)Unclear ❌
assert.InDelta(t, got, 6, 4)Argument order
As #399 states, the order of arguments should be:
TestingT
msgAndArgs ...interface{}
Equal(t TestingT, actual, expected interface{}, msgAndArgs ...interface{}) bool Contains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool Less(t TestingT, e1, e2 interface{}, msgAndArgs ...interface{}) bool
Format functions (Assertionf(t TestingT, actual, expected, msg string, args ...interface{})
) should not be accepted as they are equivalent to their "non-f" counterparts.
If there is a likely actual value and expected value; then actual
and expected
should be the argument names.
Equal(t TestingT, actual, expected interface{}, msgAndArgs ...interface{}) bool
If there is no obvious actual value and there are multiple values of the same type; then consistently use v1, v2, ...
to differentiate the v
s from any other arguments that might be present.
Less(t TestingT, v1, v2 interface{}, msgAndArgs ...interface{}) bool
If there is no obvious actual value and there is only one value, or values of different types; then take example from the standard library or use plain english. Be careful not to follow the stdlib examples if their argument type is descriptive but the assertion uses interface{}
.
// error is frequently called err NoError(t TestingT, err error, msgAndArgs ...interface{}) bool // sort.SearchInt(a []int, x int) uses a for the slice and x for the element, but the types are critical so this example is bad. // strings.Contains(s, substr string) is a better example, but s is short for string. // Just use English or well known abbreviated English for both arguments. Contains(t, container, val interface{}, msgAndArgs ...interface{}) boolMeta Assertions
A wrapper around an existing assertion should exist only if it improves on the readability of a pure Go implementation.
Useful ✅assert.ElementsMatch(t, got, expected)visited := make([]bool, len(got)) // - vs - visited := make([]bool, len(got)) for i := 0; i < len(expected); i++ { found := false for j := 0; j < len(got); j++ { if visited[j] { continue } if got[j] == expected[i] { visited[j] = true found = true break } } if !found { t.Error("Elements do not match") } } for j := 0; j < len(got); j++ { if visited[j] { continue } t.Error("Elements do not match") }Less valuable ❓
assert.InDeltaSlice(t, got, expected) // - vs - if assert.Equal(t, len(got), len(expected)) { for i := range got { assert.InDelta(t, got[i], expected[i], 5) } }Inverse Assertions
I don't know whether to do anything here, it's tempting to say that all inverted functions should be prefixed with "Not", eg: Equal()
and NotEqual
, But NoError()
is perhaps better Language than NotError()
and Less()
is definitely better than NotGreater()
.
IsNonDecreasing()
however is terrible, every assertion could be prefixed with "Is".
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4