@@ -1161,6 +1161,39 @@ func formatListDiff(listA, listB interface{}, extraA, extraB []interface{}) stri
11611161 return msg .String ()
11621162}
11631163
1164+ // NotElementsMatch asserts that the specified listA(array, slice...) is NOT equal to specified
1165+ // listB(array, slice...) ignoring the order of the elements. If there are duplicate elements,
1166+ // the number of appearances of each of them in both lists should not match.
1167+ // This is an inverse of ElementsMatch.
1168+ //
1169+ // assert.NotElementsMatch(t, [1, 1, 2, 3], [1, 1, 2, 3]) -> false
1170+ //
1171+ // assert.NotElementsMatch(t, [1, 1, 2, 3], [1, 2, 3]) -> true
1172+ //
1173+ // assert.NotElementsMatch(t, [1, 2, 3], [1, 2, 4]) -> true
1174+ func NotElementsMatch (t TestingT , listA , listB interface {}, msgAndArgs ... interface {}) (ok bool ) {
1175+ if h , ok := t .(tHelper ); ok {
1176+ h .Helper ()
1177+ }
1178+ if isEmpty (listA ) && isEmpty (listB ) {
1179+ return Fail (t , "listA and listB contain the same elements" , msgAndArgs )
1180+ }
1181+
1182+ if ! isList (t , listA , msgAndArgs ... ) {
1183+ return Fail (t , "listA is not a list type" , msgAndArgs ... )
1184+ }
1185+ if ! isList (t , listB , msgAndArgs ... ) {
1186+ return Fail (t , "listB is not a list type" , msgAndArgs ... )
1187+ }
1188+
1189+ extraA , extraB := diffLists (listA , listB )
1190+ if len (extraA ) == 0 && len (extraB ) == 0 {
1191+ return Fail (t , "listA and listB contain the same elements" , msgAndArgs )
1192+ }
1193+
1194+ return true
1195+ }
1196+
11641197// Condition uses a Comparison to assert a complex condition.
11651198func Condition (t TestingT , comp Comparison , msgAndArgs ... interface {}) bool {
11661199 if h , ok := t .(tHelper ); ok {
@@ -1908,6 +1941,9 @@ func Eventually(t TestingT, condition func() bool, waitFor time.Duration, tick t
19081941
19091942// CollectT implements the TestingT interface and collects all errors.
19101943type CollectT struct {
1944+ // A slice of errors. Non-nil slice denotes a failure.
1945+ // If it's non-nil but len(c.errors) == 0, this is also a failure
1946+ // obtained by direct c.FailNow() call.
19111947 errors []error
19121948}
19131949
@@ -1916,9 +1952,10 @@ func (c *CollectT) Errorf(format string, args ...interface{}) {
19161952 c .errors = append (c .errors , fmt .Errorf (format , args ... ))
19171953}
19181954
1919- // FailNow panics.
1920- func (* CollectT ) FailNow () {
1921- panic ("Assertion failed" )
1955+ // FailNow stops execution by calling runtime.Goexit.
1956+ func (c * CollectT ) FailNow () {
1957+ c .fail ()
1958+ runtime .Goexit ()
19221959}
19231960
19241961// Deprecated: That was a method for internal usage that should not have been published. Now just panics.
@@ -1931,6 +1968,16 @@ func (*CollectT) Copy(TestingT) {
19311968 panic ("Copy() is deprecated" )
19321969}
19331970
1971+ func (c * CollectT ) fail () {
1972+ if ! c .failed () {
1973+ c .errors = []error {} // Make it non-nil to mark a failure.
1974+ }
1975+ }
1976+
1977+ func (c * CollectT ) failed () bool {
1978+ return c .errors != nil
1979+ }
1980+
19341981// EventuallyWithT asserts that given condition will be met in waitFor time,
19351982// periodically checking target function each tick. In contrast to Eventually,
19361983// it supplies a CollectT to the condition function, so that the condition
@@ -1955,7 +2002,7 @@ func EventuallyWithT(t TestingT, condition func(collect *CollectT), waitFor time
19552002 }
19562003
19572004 var lastFinishedTickErrs []error
1958- ch := make (chan [] error , 1 )
2005+ ch := make (chan * CollectT , 1 )
19592006
19602007 timer := time .NewTimer (waitFor )
19612008 defer timer .Stop ()
@@ -1975,16 +2022,16 @@ func EventuallyWithT(t TestingT, condition func(collect *CollectT), waitFor time
19752022 go func () {
19762023 collect := new (CollectT )
19772024 defer func () {
1978- ch <- collect . errors
2025+ ch <- collect
19792026 }()
19802027 condition (collect )
19812028 }()
1982- case errs := <- ch :
1983- if len ( errs ) == 0 {
2029+ case collect := <- ch :
2030+ if ! collect . failed () {
19842031 return true
19852032 }
19862033 // Keep the errors from the last ended condition, so that they can be copied to t if timeout is reached.
1987- lastFinishedTickErrs = errs
2034+ lastFinishedTickErrs = collect . errors
19882035 tick = ticker .C
19892036 }
19902037 }
@@ -2046,7 +2093,7 @@ func ErrorIs(t TestingT, err, target error, msgAndArgs ...interface{}) bool {
20462093 ), msgAndArgs ... )
20472094}
20482095
2049- // NotErrorIs asserts that at none of the errors in err's chain matches target.
2096+ // NotErrorIs asserts that none of the errors in err's chain matches target.
20502097// This is a wrapper for errors.Is.
20512098func NotErrorIs (t TestingT , err , target error , msgAndArgs ... interface {}) bool {
20522099 if h , ok := t .(tHelper ); ok {
@@ -2087,6 +2134,24 @@ func ErrorAs(t TestingT, err error, target interface{}, msgAndArgs ...interface{
20872134 ), msgAndArgs ... )
20882135}
20892136
2137+ // NotErrorAs asserts that none of the errors in err's chain matches target,
2138+ // but if so, sets target to that error value.
2139+ func NotErrorAs (t TestingT , err error , target interface {}, msgAndArgs ... interface {}) bool {
2140+ if h , ok := t .(tHelper ); ok {
2141+ h .Helper ()
2142+ }
2143+ if ! errors .As (err , target ) {
2144+ return true
2145+ }
2146+
2147+ chain := buildErrorChainString (err )
2148+
2149+ return Fail (t , fmt .Sprintf ("Target error should not be in err chain:\n " +
2150+ "found: %q\n " +
2151+ "in chain: %s" , target , chain ,
2152+ ), msgAndArgs ... )
2153+ }
2154+
20902155func buildErrorChainString (err error ) string {
20912156 if err == nil {
20922157 return ""
0 commit comments