Testify require and assert: Difference between revisions
Line 11: | Line 11: | ||
The major difference between <code>require</code> and <code>assert</code> is that <code>assert</code> means '''continue on error'''. If an assertion fails, the test reports it and the goroutine the asserting failure happened on '''continues execution'''. In the end, the overall test is counted as "failed", but while executing, the test keeps going on failed assertions. This is different from the behavior of <code>assert</code> in other languages and frameworks, where the first failed assertion stops the current test. This does not make too much sense - if an assertion is broken, I am not that interested in what comes after that, they are likely to be broken too, or at least, not to be trusted. | The major difference between <code>require</code> and <code>assert</code> is that <code>assert</code> means '''continue on error'''. If an assertion fails, the test reports it and the goroutine the asserting failure happened on '''continues execution'''. In the end, the overall test is counted as "failed", but while executing, the test keeps going on failed assertions. This is different from the behavior of <code>assert</code> in other languages and frameworks, where the first failed assertion stops the current test. This does not make too much sense - if an assertion is broken, I am not that interested in what comes after that, they are likely to be broken too, or at least, not to be trusted. | ||
If you want the test to exit the '''current goroutine''' after the first failed assertion, use <code>require</code>. <code>require</code> means '''exit the goroutine on | If you want the test to exit the '''current goroutine''' after the first failed assertion, use <code>require</code>. <code>require</code> means '''exit the goroutine on failed assertion'''. However, <code>require</code> does not exit the test. If the test is multi-threaded, you need to account for what other goroutines are doing. | ||
Internally, this is implemented by assert <code>calling</code> <code>Fail()</code> and <code>require</code> calling <code>FailNow()</code>. | Internally, this is implemented by assert <code>calling</code> <code>Fail()</code> and <code>require</code> calling <code>FailNow()</code>. |
Revision as of 18:16, 12 March 2024
External
Internal
Overview
require
and assert
packages provide functions to evaluate arguments and establish whether the test passes or fails.
Calling assert and require from Goroutines
The major difference between require
and assert
is that assert
means continue on error. If an assertion fails, the test reports it and the goroutine the asserting failure happened on continues execution. In the end, the overall test is counted as "failed", but while executing, the test keeps going on failed assertions. This is different from the behavior of assert
in other languages and frameworks, where the first failed assertion stops the current test. This does not make too much sense - if an assertion is broken, I am not that interested in what comes after that, they are likely to be broken too, or at least, not to be trusted.
If you want the test to exit the current goroutine after the first failed assertion, use require
. require
means exit the goroutine on failed assertion. However, require
does not exit the test. If the test is multi-threaded, you need to account for what other goroutines are doing.
Internally, this is implemented by assert calling
Fail()
and require
calling FailNow()
.
What happens when an assert
fails? How is the test state impacted? Debug and find out.
Equality and Non-Equality
In case the result is failure, Equal()
and NotEqual()
delegate to Fail()
.
package somepkg
import (
"testing"
testifyassert "github.com/stretchr/testify/assert"
testifyrequire "github.com/stretchr/testify/require"
)
func TestSomething(t *testing.T) {
assert := testifyassert.New(t)
require := testifyrequire.New(t)
assert.Equal(123, 123, "this message is displayed when the assertion fails, but the test continues %s", "because of inequality")
require.Equal(123, 123, "this message is displayed when the test fails and exists %s", "because of inequality")
assert.NotEqual(123, 321, "this message is displayed when the test fails %s", "because of equality")
require.NotEqual(123, 321, "this message is displayed when the test fails and exists %s", "because of inequality")
}
Nil and Non-Nil
In case the result is failure, Nil()
and NotNil()
delegate to Fail()
.
package somepkg
import (
"testing"
testifyassert "github.com/stretchr/testify/assert"
testifyrequire "github.com/stretchr/testify/require"
)
func TestSomething(t *testing.T) {
assert := testifyassert.New(t)
require := testifyrequire.New(t)
someObj := &struct{}{}
assert.NotNil(someObj, "someObj should not have been nil but it is %v, and the test continues", someObj)
require.NotNil(someObj, "someObj should not have been nil but it is %v, and the test exits", someObj)
someObj = nil
assert.Nil(someObj, "someObj should have been nil but it is %v, and the test continues", someObj)
require.Nil(someObj, "someObj should have been nil but it is %v, and the test exits", someObj)
}
Failing the Test
Fail()
Does not stop the test. It annotates its internal state that there was a failure, and let the test continue.
Failf()
FailNow()
Checking that an Error Has Expected Message
err := ...
assert.NotNil(err)
assert.Equal(err.Error(), "expected message")