assert

package
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 20, 2024 License: MIT Imports: 12 Imported by: 58

Documentation

Overview

Package assert includes runtime assertion helpers both for normal execution as well as a assertion package for Go's testing. What makes solution unique is its capable to support both modes with the same API. Only thing you need to do is to add a PushTester line at the beginning of your unit tests and its sub-gouroutines:

func TestInvite(t *testing.T) {
     defer assert.PushTester(t)() // push testing variable t beginning of any test

     //                 v-----v Invite's control flow includes assertions
     alice.Node = root1.Invite(alice.Node, root1.Key, alice.PubKey, 1)
     assert.Equal(alice.Len(), 1) // assert anything normally
     ...
     go func() {
          assert.PushTester(t) // <-- Needs to do again for a new goroutine

Merge Runtime And Unit Test Assertions

The next block is the actual Invite function's first two lines. Even if the assertion line is written more from a runtime detection point of view, it catches all assert violations in the unit tests as well:

func (c Chain) Invite(...) {
     assert.That(c.isLeaf(invitersKey), "only leaf can invite")

If some assertion violation occurs in the deep call stack, they are still reported as a test failure. See the above code blocks. If assertion failure happens somewhere inside the Invite function's call stack, it's still reported correctly as a test failure of the TestInvite unit test. It doesn't matter how deep the recursion is or if parallel test runs are performed. The failure report includes all the locations of the meaningful call stack steps. See the next chapter.

Call Stack Traversal During Tests

The Assert package allows us to track assertion violations over the package and even module boundaries. When an assertion fails during the unit testing, the whole call stack is brought to unit test logs. And some help with your IDE, such as transferring output to a location list, for example, in Neovim/Vim. For example, you can find a proper test result parser like nvim-go (fork)

With a sizeable multi-repo environment, this has proven to be valuable.

Why Runtime Asserts Are So Important?

Instead of mocking or other mechanisms we can integrate our preconditions and raise up quality of our software.

"Assertions are active comments"

The assert package offers a convenient way to set preconditions to code which allow us detect programming errors and API violations faster. Still allowing production-time error handling if needed. And everything is automatic. You can set asserter with SetDefault function or --asserter flag if Go's flag package is in use. This allows developer, operator and every-day user share the exact same binary but get the error messages and diagnostic they need.

// Production asserter adds formatted caller info to normal errors.
// Information is transported thru error values when err2.Handle is in use.
assert.SetDefault(assert.Production)

Please see the code examples for more information.

Flag Package Support

The assert package supports Go's flags. All you need to do is to call flag.Parse. And the following flags are supported (="default-value"):

-asserter="Prod"
    A name of the asserter Plain, Prod, Dev, Debug
    See more information from constants: Plain, Production, Development, Debug

And assert package's configuration flags are inserted.

Performance

assert.That's performance is equal to the if-statement thanks for inlining. And the most of the generics-based versions are about the equally fast. Practice has thought that we should prefer other than assert.That because by using detailed version like assert.Shorter we get precise error messages automatically. Some also prefer readability of specific asserters.

If your algorithm is performance-critical please run `make bench` in the err2 repo and decide case by case. Also you can make an issue or even PR if you would like to have something similar like [glog.V] function.

Naming

Because performance has been number one requirement and Go's generics cannot discrete slices, maps and channels we have used naming prefixes accordingly: S = slice, M = map, C = channel. No prefix is (currently) for the string type.

Index

Examples

Constants

View Source
const (
	Plain defInd = 0 + iota
	Production
	Development
	Test
	TestFull
	Debug
)

Asserters are the way to set what kind of messages assert package outputs if assertion is violated.

Plain converts asserts just plain K&D error messages without extra information. That's useful for apps that want to use assert package to validate e.g. command fields:

assert.NotEmpty(c.PoolName, "pool name cannot be empty")

Note that Plain is only asserter that override auto-generated assertion messages with given arguments like 'pool name cannot be empty'. Others add given arguments at the end of the auto-generated assert message.

Production (pkg's default) is the best asserter for most cases. The assertion violations are treated as Go error values. And only a pragmatic caller info is included into the error values like source filename, line number, and caller function, all in one line:

copy file: main.go:37: CopyFile(): assertion violation: string shouldn't be empty

Development is the best asserter for development use. The assertion violations are treated as Go error values. And a formatted caller info is included to the error message like source filename , line number, and caller function. Everything in a noticeable multi-line message:

--------------------------------
Assertion Fault at:
main.go:37 CopyFile():
assertion violation: string shouldn't be empty
--------------------------------

Test minimalistic asserter for unit test use. More pragmatic is the TestFull asserter (test default).

Use this asserter if your IDE/editor doesn't support full file names and it relies a relative path (Go standard). You can use this also if you need temporary problem solving for your programming environment.

TestFull asserter (test default). The TestFull asserter includes the caller info and the call stack for unit testing, similarly like err2's error traces. Note that PushTester set's TestFull if it's not yet set.

The call stack produced by the test asserts can be used over Go module boundaries. For example, if your app and it's sub packages both use err2/assert for unit testing and runtime checks, the runtime assertions will be automatically converted to test asserts. If any of the runtime asserts of the sub packages fails during the app tests, the app test fails as well.

Note that the cross-module assertions produce long file names (path included), and some of the Go test result parsers cannot handle that. A proper test result parser like nvim-go (fork) works very well. Also most of the make result parsers can process the output properly and allow traverse of locations of the error trace.

Debug asserter transforms assertion violations to panic calls where panic object's type is string, i.e., err2 package treats it as a normal panic, not an error.

For example, the pattern that e.g. Go's standard library uses:

if p == nil {
     panic("pkg: ptr cannot be nil")
}

is equal to:

assert.NotNil(p)

Variables

This section is empty.

Functions

func CLen added in v0.9.52

func CLen[C ~chan T, T any](obj C, length int, a ...any)

CLen asserts that the length of the chan is equal to the given. If not it panics/errors (according the current Asserter) with the auto-generated message. You can append the generated got-want message by using optional message arguments.

Note that when Plain asserter is used (SetDefault), optional arguments are used to override the auto-generated assert violation message.

Note! This is reasonably fast but not as fast as That because of lacking inlining for the current implementation of Go's type parametric functions.

func CLonger added in v0.9.52

func CLonger[C ~chan T, T any](obj C, length int, a ...any)

CLonger asserts that the length of the chan is longer to the given. If not it panics/errors (according the current Asserter) with the auto-generated message. You can append the generated got-want message by using optional message arguments.

Note that when Plain asserter is used (SetDefault), optional arguments are used to override the auto-generated assert violation message.

Note! This is reasonably fast but not as fast as That because of lacking inlining for the current implementation of Go's type parametric functions.

func CNotNil added in v0.8.0

func CNotNil[C ~chan T, T any](c C, a ...any)

CNotNil asserts that the channel is not nil. If it is it panics/errors (default Asserter) the auto-generated (args appended) message.

Note that when Plain asserter is used (SetDefault), optional arguments are used to override the auto-generated assert violation message.

Example
package main

import (
	"fmt"

	"github.com/lainio/err2"
	"github.com/lainio/err2/assert"
)

func main() {
	sample := func(c chan byte) (err error) {
		defer err2.Handle(&err, "sample")

		assert.CNotNil(c)
		return err
	}
	var c chan byte
	err := sample(c)
	fmt.Printf("%v", err)
}
Output:

sample: assert_test.go:54: ExampleCNotNil.func1(): assertion violation: channel shouldn't be nil

func CShorter added in v0.9.52

func CShorter[C ~chan T, T any](obj C, length int, a ...any)

CShorter asserts that the length of the chan is shorter to the given. If not it panics/errors (according the current Asserter) with the auto-generated message. You can append the generated got-want message by using optional message arguments.

Note that when Plain asserter is used (SetDefault), optional arguments are used to override the auto-generated assert violation message.

Note! This is reasonably fast but not as fast as That because of lacking inlining for the current implementation of Go's type parametric functions.

func DeepEqual added in v0.8.9

func DeepEqual(val, want any, a ...any)

DeepEqual asserts that the (whatever) values are equal. If not it panics/errors (according the current Asserter) with the auto-generated message. You can append the generated got-want message by using optional message arguments.

Note that when Plain asserter is used (SetDefault), optional arguments are used to override the auto-generated assert violation message.

func Empty added in v0.8.9

func Empty(obj string, a ...any)

Empty asserts that the string is empty. If it is NOT, it panics/errors (according the current Asserter) with the auto-generated message. You can append the generated got-want message by using optional message arguments.

Note that when Plain asserter is used (SetDefault), optional arguments are used to override the auto-generated assert violation message.

func Equal added in v0.8.0

func Equal[T comparable](val, want T, a ...any)

Equal asserts that the values are equal. If not it panics/errors (according the current Asserter) with the auto-generated message. You can append the generated got-want message by using optional message arguments.

Note that when Plain asserter is used (SetDefault), optional arguments are used to override the auto-generated assert violation message.

Example
package main

import (
	"fmt"

	"github.com/lainio/err2"
	"github.com/lainio/err2/assert"
)

func main() {
	sample := func(b []byte) (err error) {
		defer err2.Handle(&err, "sample")

		assert.Equal(len(b), 3)
		return err
	}
	err := sample([]byte{1, 2})
	fmt.Printf("%v", err)
}
Output:

sample: assert_test.go:80: ExampleEqual.func1(): assertion violation: got '2', want '3'

func Error added in v0.8.8

func Error(err error, a ...any)

Error asserts that the err is not nil. If it is it panics and builds a violation message. Thanks to inlining, the performance penalty is equal to a single 'if-statement' that is almost nothing.

Note that when Plain asserter is used (SetDefault), optional arguments are used to override the auto-generated assert violation message.

func INil added in v0.8.10

func INil(i any, a ...any)

INil asserts that the interface value IS nil. If it is it panics/errors (default Asserter) the auto-generated (args appended) message.

Note that when Plain asserter is used (SetDefault), optional arguments are used to override the auto-generated assert violation message.

Note, use this only for real interface types. Go's interface's has two values so this won't work e.g. slices! Read more information about the interface type.

func INotNil added in v0.8.9

func INotNil(i any, a ...any)

INotNil asserts that the interface value is NOT nil. If it is it panics/errors (default Asserter) the auto-generated (args appended) message.

Note that when Plain asserter is used (SetDefault), optional arguments are used to override the auto-generated assert violation message.

Note, use this only for real interface types. Go's interface's has two values so this won't work e.g. slices! Read more information about the interface type.

func Len added in v0.8.14

func Len(obj string, length int, a ...any)

Len asserts that the length of the string is equal to the given. If not it panics/errors (according the current Asserter) with the auto-generated message. You can append the generated got-want message by using optional message arguments.

Note that when Plain asserter is used (SetDefault), optional arguments are used to override the auto-generated assert violation message.

Note! This is reasonably fast but not as fast as That because of lacking inlining for the current implementation of Go's type parametric functions.

func Longer added in v0.9.52

func Longer(s string, length int, a ...any)

Longer asserts that the length of the string is longer to the given. If not it panics/errors (according the current Asserter) with the auto-generated message. You can append the generated got-want message by using optional message arguments.

Note that when Plain asserter is used (SetDefault), optional arguments are used to override the auto-generated assert violation message.

Note! This is reasonably fast but not as fast as That because of lacking inlining for the current implementation of Go's type parametric functions.

func MKeyExists added in v0.8.10

func MKeyExists[M ~map[T]U, T comparable, U any](obj M, key T, a ...any) (val U)

MKeyExists asserts that the map key exists. If not it panics/errors (current Asserter) the auto-generated (args appended) message.

Note that when Plain asserter is used (SetDefault), optional arguments are used to override the auto-generated assert violation message.

Example
package main

import (
	"fmt"

	"github.com/lainio/err2"
	"github.com/lainio/err2/assert"
)

func main() {
	sample := func(b string) (err error) {
		defer err2.Handle(&err, "sample")

		m := map[string]string{
			"1": "one",
		}
		v := assert.MKeyExists(m, "1")
		assert.Equal(v, "one")
		_ = assert.MKeyExists(m, b)
		return err
	}
	err := sample("2")
	fmt.Printf("%v", err)
}
Output:

sample: assert_test.go:134: ExampleMKeyExists.func1(): assertion violation: key '2' doesn't exist

func MLen added in v0.8.0

func MLen[M ~map[T]U, T comparable, U any](obj M, length int, a ...any)

MLen asserts that the length of the map is equal to the given. If not it panics/errors (according the current Asserter) with the auto-generated message. You can append the generated got-want message by using optional message arguments.

Note that when Plain asserter is used (SetDefault), optional arguments are used to override the auto-generated assert violation message.

Note! This is reasonably fast but not as fast as That because of lacking inlining for the current implementation of Go's type parametric functions.

func MLonger added in v0.9.52

func MLonger[M ~map[T]U, T comparable, U any](obj M, length int, a ...any)

MLonger asserts that the length of the map is longer to the given. If not it panics/errors (according the current Asserter) with the auto-generated message. You can append the generated got-want message by using optional message arguments.

Note that when Plain asserter is used (SetDefault), optional arguments are used to override the auto-generated assert violation message.

Note! This is reasonably fast but not as fast as That because of lacking inlining for the current implementation of Go's type parametric functions.

func MNotEmpty added in v0.8.3

func MNotEmpty[M ~map[T]U, T comparable, U any](obj M, a ...any)

MNotEmpty asserts that the map is not empty. If it is, it panics/errors (according the current Asserter) with the auto-generated message. You can append the generated got-want message by using optional message arguments. You can append the generated got-want message by using optional message arguments.

Note that when Plain asserter is used (SetDefault), optional arguments are used to override the auto-generated assert violation message.

Note! This is reasonably fast but not as fast as That because of lacking inlining for the current implementation of Go's type parametric functions.

func MNotNil added in v0.8.0

func MNotNil[M ~map[T]U, T comparable, U any](m M, a ...any)

MNotNil asserts that the map is not nil. If it is it panics/errors (default Asserter) the auto-generated (args appended) message.

Note that when Plain asserter is used (SetDefault), optional arguments are used to override the auto-generated assert violation message.

Example
package main

import (
	"fmt"

	"github.com/lainio/err2"
	"github.com/lainio/err2/assert"
)

func main() {
	sample := func(b map[string]byte) (err error) {
		defer err2.Handle(&err, "sample")

		assert.MNotNil(b)
		return err
	}
	var b map[string]byte
	err := sample(b)
	fmt.Printf("%v", err)
}
Output:

sample: assert_test.go:41: ExampleMNotNil.func1(): assertion violation: map shouldn't be nil

func MShorter added in v0.9.52

func MShorter[M ~map[T]U, T comparable, U any](obj M, length int, a ...any)

MShorter asserts that the length of the map is shorter to the given. If not it panics/errors (according the current Asserter) with the auto-generated message. You can append the generated got-want message by using optional message arguments.

Note that when Plain asserter is used (SetDefault), optional arguments are used to override the auto-generated assert violation message.

Note! This is reasonably fast but not as fast as That because of lacking inlining for the current implementation of Go's type parametric functions.

Example
package main

import (
	"fmt"

	"github.com/lainio/err2"
	"github.com/lainio/err2/assert"
)

func main() {
	sample := func(b map[byte]byte) (err error) {
		defer err2.Handle(&err, "sample")

		assert.MShorter(b, 1) // ok
		assert.MShorter(b, 0) // not ok
		return err
	}
	err := sample(map[byte]byte{01: 01}) // len = 1
	fmt.Printf("%v", err)
}
Output:

sample: assert_test.go:172: ExampleMShorter.func1(): assertion violation: got '1', should be shorter than '1'

func Nil added in v0.8.14

func Nil[T any](p *T, a ...any)

Nil asserts that the pointer IS nil. If it is not it panics/errors (default Asserter) the auto-generated (args appended) message.

Note that when Plain asserter is used (SetDefault), optional arguments are used to override the auto-generated assert violation message.

func NoError added in v0.8.8

func NoError(err error, a ...any)

NoError asserts that the error is nil. If is not it panics with the given formatting string. Thanks to inlining, the performance penalty is equal to a single 'if-statement' that is almost nothing.

Note. We recommend that you prefer github.com/lainio/err2/try.To. They work exactly the same during the test runs and you can use the same code for both: runtime and tests. However, there are cases that you want assert that there is no error in cases where fast fail and immediate stop of execution is wanted at runtime. With asserts (Production, Development, Debug) you get the file location as well.

func NotDeepEqual added in v0.8.10

func NotDeepEqual(val, want any, a ...any)

NotDeepEqual asserts that the (whatever) values are equal. If not it panics/errors (according the current Asserter) with the auto-generated message. You can append the generated got-want message by using optional message arguments.

Note that when Plain asserter is used (SetDefault), optional arguments are used to override the auto-generated assert violation message.

Note, it uses reflect.DeepEqual which means that also the types must be the same:

assert.DeepEqual(pubKey, ed25519.PublicKey(pubKeyBytes))

func NotEmpty added in v0.8.3

func NotEmpty(obj string, a ...any)

NotEmpty asserts that the string is not empty. If it is, it panics/errors (according the current Asserter) with the auto-generated message. You can append the generated got-want message by using optional message arguments.

Note that when Plain asserter is used (SetDefault), optional arguments are used to override the auto-generated assert violation message.

Example
package main

import (
	"fmt"

	"github.com/lainio/err2"
	"github.com/lainio/err2/assert"
)

func main() {
	sample := func(b string) (err error) {
		defer err2.Handle(&err, "sample")

		assert.Empty(b)
		assert.NotEmpty(b)
		return err
	}
	err := sample("")
	fmt.Printf("%v", err)
}
Output:

sample: assert_test.go:117: ExampleNotEmpty.func1(): assertion violation: string shouldn't be empty

func NotEqual added in v0.8.0

func NotEqual[T comparable](val, want T, a ...any)

NotEqual asserts that the values aren't equal. If they are it panics/errors (according the current Asserter) with the auto-generated message. You can append the generated got-want message by using optional message arguments.

Note that when Plain asserter is used (SetDefault), optional arguments are used to override the auto-generated assert violation message.

Note, when asserter is Plain, optional arguments are used to build a new assert violation message.

func NotImplemented added in v0.8.3

func NotImplemented(a ...any)

NotImplemented always panics with 'not implemented' assertion message.

Note that when Plain asserter is used (SetDefault), optional arguments are used to override the auto-generated assert violation message.

func NotNil added in v0.8.0

func NotNil[P ~*T, T any](p P, a ...any)

NotNil asserts that the pointer IS NOT nil. If it is it panics/errors (default Asserter) the auto-generated (args appended) message.

Note that when Plain asserter is used (SetDefault), optional arguments are used to override the auto-generated assert violation message.

Example
package main

import (
	"fmt"

	"github.com/lainio/err2"
	"github.com/lainio/err2/assert"
)

func main() {
	sample := func(b *byte) (err error) {
		defer err2.Handle(&err, "sample")

		assert.NotNil(b)
		return err
	}
	var b *byte
	err := sample(b)
	fmt.Printf("%v", err)
}
Output:

sample: assert_test.go:28: ExampleNotNil.func1(): assertion violation: pointer shouldn't be nil

func NotZero added in v0.9.0

func NotZero[T Number](val T, a ...any)

NotZero asserts that the value != 0. If it is not it panics and builds a violation message. Thanks to inlining, the performance penalty is equal to a single 'if-statement' that is almost nothing.

Note that when Plain asserter is used (SetDefault), optional arguments are used to override the auto-generated assert violation message.

func PopTester added in v0.8.8

func PopTester()

PopTester pops the testing context reference from the memory. This is for memory cleanup and adding similar to err2.Catch error/panic safety for tests. By using PopTester you get error logs tuned for unit testing.

You have two ways to call PopTester. With defer right after PushTester:

for _, tt := range tests {
     t.Run(tt.name, func(t *testing.T) {
          assert.PushTester(t) // <- important!
          defer assert.PopTester() // <- for good girls and not so bad boys
          ...
          assert.That(something, "test won't work")
     })
}

If you want, you can combine PushTester and PopTester to one-liner:

defer assert.PushTester(t)()

func PushTester added in v0.8.8

func PushTester(t testing.TB, a ...defInd) function

PushTester sets the current testing context for default asserter. This must be called at the beginning of every test. There is two way of doing it:

for _, tt := range tests {
     t.Run(tt.name, func(t *testing.T) { // Shorter way, litle magic
          defer assert.PushTester(t)() // <- IMPORTANT! NOTE! (t)()
          ...
          assert.That(something, "test won't work")
     })
     t.Run(tt.name, func(t *testing.T) { // Longer, explicit way, 2 lines
          assert.PushTester(t) // <- IMPORTANT!
          defer assert.PopTester()
          ...
          assert.That(something, "test won't work")
     })
}

Because PushTester returns PopTester it allows us to merge these two calls to one line. See the first t.Run call above. See more information in PopTester.

PushTester allows you to change the current default asserter by accepting it as a second argument.

Note that you MUST call PushTester for sub-goroutines:

defer assert.PushTester(t)() // does the cleanup
...
go func() {
     assert.PushTester(t) // left cleanup out! Leave it for the test, see ^
     ...

Note that the second argument, if given, changes the default asserter for whole package. The argument is mainly for temporary development use and isn't not preferred API usage.

func SLen added in v0.8.0

func SLen[S ~[]T, T any](obj S, length int, a ...any)

SLen asserts that the length of the slice is equal to the given. If not it panics/errors (according the current Asserter) with the auto-generated message. You can append the generated got-want message by using optional message arguments.

Note that when Plain asserter is used (SetDefault), optional arguments are used to override the auto-generated assert violation message.

Note! This is reasonably fast but not as fast as That because of lacking inlining for the current implementation of Go's type parametric functions.

Example
package main

import (
	"fmt"

	"github.com/lainio/err2"
	"github.com/lainio/err2/assert"
)

func main() {
	sample := func(b []byte) (err error) {
		defer err2.Handle(&err, "sample")

		assert.SLen(b, 3)
		return err
	}
	err := sample([]byte{1, 2})
	fmt.Printf("%v", err)
}
Output:

sample: assert_test.go:92: ExampleSLen.func1(): assertion violation: got '2', want '3'

func SLonger added in v0.9.52

func SLonger[S ~[]T, T any](obj S, length int, a ...any)

SLonger asserts that the length of the slice is equal to the given. If not it panics/errors (according the current Asserter) with the auto-generated message. You can append the generated got-want message by using optional message arguments.

Note that when Plain asserter is used (SetDefault), optional arguments are used to override the auto-generated assert violation message.

Note! This is reasonably fast but not as fast as That because of lacking inlining for the current implementation of Go's type parametric functions.

Example
package main

import (
	"fmt"

	"github.com/lainio/err2"
	"github.com/lainio/err2/assert"
)

func main() {
	sample := func(b []byte) (err error) {
		defer err2.Handle(&err, "sample")

		assert.SLonger(b, 0) // ok
		assert.SLonger(b, 1) // not ok
		return err
	}
	err := sample([]byte{01}) // len = 1
	fmt.Printf("%v", err)
}
Output:

sample: assert_test.go:160: ExampleSLonger.func1(): assertion violation: got '1', should be longer than '1'

func SNil added in v0.8.8

func SNil[S ~[]T, T any](s S, a ...any)

SNil asserts that the slice IS nil. If it is it panics/errors (default Asserter) the auto-generated (args appended) message.

Note that when Plain asserter is used (SetDefault), optional arguments are used to override the auto-generated assert violation message.

func SNotEmpty added in v0.8.3

func SNotEmpty[S ~[]T, T any](obj S, a ...any)

SNotEmpty asserts that the slice is not empty. If it is, it panics/errors (according the current Asserter) with the auto-generated message. You can append the generated got-want message by using optional message arguments.

Note that when Plain asserter is used (SetDefault), optional arguments are used to override the auto-generated assert violation message.

Note! This is reasonably fast but not as fast as That because of lacking inlining for the current implementation of Go's type parametric functions.

Example
package main

import (
	"fmt"

	"github.com/lainio/err2"
	"github.com/lainio/err2/assert"
)

func main() {
	sample := func(b []byte) (err error) {
		defer err2.Handle(&err, "sample")

		assert.SNotEmpty(b)
		return err
	}
	err := sample([]byte{})
	fmt.Printf("%v", err)
}
Output:

sample: assert_test.go:104: ExampleSNotEmpty.func1(): assertion violation: slice shouldn't be empty

func SNotNil added in v0.8.0

func SNotNil[S ~[]T, T any](s S, a ...any)

SNotNil asserts that the slice is not nil. If it is it panics/errors (default Asserter) the auto-generated (args appended) message.

Note that when Plain asserter is used (SetDefault), optional arguments are used to override the auto-generated assert violation message.

Example
package main

import (
	"fmt"

	"github.com/lainio/err2"
	"github.com/lainio/err2/assert"
)

func main() {
	sample := func(b []byte) (err error) {
		defer err2.Handle(&err, "sample")

		assert.SNotNil(b)
		return err
	}
	var b []byte
	err := sample(b)
	fmt.Printf("%v", err)
}
Output:

sample: assert_test.go:67: ExampleSNotNil.func1(): assertion violation: slice shouldn't be nil

func SShorter added in v0.9.52

func SShorter[S ~[]T, T any](obj S, length int, a ...any)

SShorter asserts that the length of the slice is equal to the given. If not it panics/errors (according the current Asserter) with the auto-generated message. You can append the generated got-want message by using optional message arguments.

Note that when Plain asserter is used (SetDefault), optional arguments are used to override the auto-generated assert violation message.

Note! This is reasonably fast but not as fast as That because of lacking inlining for the current implementation of Go's type parametric functions.

Example
package main

import (
	"fmt"

	"github.com/lainio/err2"
	"github.com/lainio/err2/assert"
)

func main() {
	sample := func(b []byte) (err error) {
		defer err2.Handle(&err, "sample")

		assert.SShorter(b, 2)                                      // ok
		assert.SShorter(b, 0, "optional message (%s)", "test_str") // not ok
		return err
	}
	err := sample([]byte{01}) // len = 1
	fmt.Printf("%v", err)
}
Output:

sample: assert_test.go:186: ExampleSShorter.func1(): assertion violation: got '1', should be shorter than '0': optional message (test_str)

func SetDefault added in v0.9.1

func SetDefault(i defInd) (old defInd)

SetDefault sets the current default asserter for assert pkg. It also returns the previous asserter.

Note that you should use this in TestMain function, and use flag package to set it for the app. For the tests you can set it to panic about every assertion fault, or to throw an error, or/and print the call stack immediately when assert occurs. The err2 package helps you to catch and report all types of the asserts.

Note that if you are using tracers you might get two call stacks, so test what's best for your case.

Tip. If our own packages (client packages for assert) have lots of parallel testing and race detection, please try to use same asserter for all of them and set asserter only one in TestMain, or in init.

func TestMain(m *testing.M) {
     SetDefault(assert.TestFull)

func Shorter added in v0.9.52

func Shorter(str string, length int, a ...any)

Shorter asserts that the length of the string is shorter to the given. If not it panics/errors (according the current Asserter) with the auto-generated message. You can append the generated got-want message by using optional message arguments.

Note that when Plain asserter is used (SetDefault), optional arguments are used to override the auto-generated assert violation message.

Note! This is reasonably fast but not as fast as That because of lacking inlining for the current implementation of Go's type parametric functions.

func That added in v0.8.0

func That(term bool, a ...any)

That asserts that the term is true. If not it panics with the given formatting string. Thanks to inlining, the performance penalty is equal to a single 'if-statement' that is almost nothing.

Note that when Plain asserter is used (SetDefault), optional arguments are used to override the auto-generated assert violation message.

Example
package main

import (
	"fmt"

	"github.com/lainio/err2"
	"github.com/lainio/err2/assert"
)

func main() {
	sample := func() (err error) {
		defer err2.Handle(&err)

		assert.That(false, "optional message")
		return err
	}
	err := sample()
	fmt.Printf("%v", err)
}
Output:

testing: run example: assert_test.go:16: ExampleThat.func1(): assertion violation: optional message

func ThatNot added in v0.8.8

func ThatNot(term bool, a ...any)

ThatNot asserts that the term is NOT true. If is it panics with the given formatting string. Thanks to inlining, the performance penalty is equal to a single 'if-statement' that is almost nothing.

Note that when Plain asserter is used (SetDefault), optional arguments are used to override the auto-generated assert violation message.

func Zero added in v0.8.14

func Zero[T Number](val T, a ...any)

Zero asserts that the value is 0. If it is not it panics and builds a violation message. Thanks to inlining, the performance penalty is equal to a single 'if-statement' that is almost nothing.

Note that when Plain asserter is used (SetDefault), optional arguments are used to override the auto-generated assert violation message.

Example
package main

import (
	"fmt"

	"github.com/lainio/err2"
	"github.com/lainio/err2/assert"
)

func main() {
	sample := func(b int8) (err error) {
		defer err2.Handle(&err, "sample")

		assert.Zero(b)
		return err
	}
	var b int8 = 1 // we want sample to assert the violation.
	err := sample(b)
	fmt.Printf("%v", err)
}
Output:

sample: assert_test.go:146: ExampleZero.func1(): assertion violation: got '1', want (== '0')

Types

type Number added in v0.8.14

type Number interface {
	constraints.Float | constraints.Integer
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL