Skip to content
This repository was archived by the owner on Feb 17, 2025. It is now read-only.

Folders and files

NameName
Last commit message
Last commit date

Latest commit

History

193 Commits

Repository files navigation

fluentassert

Caution

Avoid using assertion libraries. Instead, use go-cmp and write custom test helpers. Using the popular testify may be also an acceptable choice, especially together with testifylint to avoid common mistakes. Use this library if you still want to. Consider yourself warned.

Go ReferenceKeep a ChangelogGitHub Releasego.modLICENSE

Build StatusGo Report CardCodecov

Description

The fluent API makes the assertion code easier to read and write (more).

The generics (type parameters) make the usage type-safe.

The library is extensible by design.

Quick start

package test
import (
"testing""github.com/fluentassert/verify"
)
funcFoo() (string, error) {
return"wrong", nil
}
funcTestFoo(t*testing.T) {
got, err:=Foo()
verify.NoError(err).Require(t) // Require(f) uses t.Fatal(f), stops execution if failsverify.String(got).Equal("ok").Assert(t) // Assert(f) uses t.Error(f), continues execution if fails
}
$ go test
--- FAIL: TestFoo (0.00s)
basic_test.go:17:
the objects are not equal
got: "wrong"
want: "ok"

⚠ Do not forget calling Assert(t) or Require(t) which executes the actual assertion.

Supported types

Out-of-the-box the package provides fluent assertions for the following types. The more specific function you use, the more assertions you get.

Go typeAssertion entry point
interface{} (any)verify.Any()
comparableverify.Obj()
constraints.Orderedverify.Ordered()
constraints.Numberverify.Number()
stringverify.String()
errorverify.Error()
[]T (slice)verify.Slice()
map[K]V (map)verify.Map()

Below you can find some convenience functions.

Deep equality

For testing deep equality use DeepEqual() or NotDeepEqual().

package test
import (
"testing""github.com/fluentassert/verify"
)
typeAstruct {
StrstringBoolboolSlice []int
}
funcTestDeepEqual(t*testing.T) {
got:=A{Str: "wrong", Slice: []int{1, 4}}
verify.Any(got).DeepEqual(
A{Str: "string", Bool: true, Slice: []int{1, 2}},
).Assert(t)
}
$ go test
--- FAIL: TestDeepEqual (0.00s)
deepeq_test.go:20:
mismatch (-want +got):
test.A{
- Str: "string",
+ Str: "wrong",
- Bool: true,
+ Bool: false,
Slice: []int{
1,
- 2,
+ 4,
},
}

Collection assertions

The library contains many collection assertions. Below is an example of checking unordered equality.

package test
import (
"testing""github.com/fluentassert/verify"
)
funcTestSlice(t*testing.T) {
got:= []int { 3, 1, 2 }
verify.Slice(got).Equivalent([]int { 2, 3, 4 }).Assert(t)
}
$ go test
--- FAIL: TestSlice (0.00s)
slice_test.go:12:
not equivalent
got: [3 1 2]
want: [2 3 4]
extra got: [1]
extra want: [4]

Periodic polling

For asynchronous testing you can use verify.Eventually() or verify.EventuallyChan().

package test
import (
"net/http""testing""time""github.com/fluentassert/verify"
)
funcTestPeriodic(t*testing.T) {
verify.Eventually(10*time.Second, time.Second, func() verify.FailureMessage {
client:= http.Client{Timeout: time.Second}
resp, err:=client.Get("http://not-existing:1234")
iferr!=nil {
returnverify.NoError(err)
}
returnverify.Number(resp.StatusCode).Lesser(300)
}).Assert(t)
}
$ go test
--- FAIL: TestPeriodic (10.00s)
async_test.go:19:
functionnever passed, last failure message:
Get "http://not-existing:1234": context deadline exceeded (Client.Timeout exceeded while awaiting headers)

Custom predicates

For the most basic scenarios, you can use one of the Check(), Should(), ShouldNot() assertions.

package test
import (
"strings""testing""github.com/fluentassert/verify"
)
funcTestShould(t*testing.T) {
got:="wrong"chars:="abc"verify.Any(got).Should(func(gotstring) bool {
returnstrings.ContainsAny(got, chars)
}).Assertf(t, "does not contain any of: %s", chars)
}
$ go test
--- FAIL: TestShould (0.00s)
should_test.go:16: does not contain any of: abc
object does not meet the predicate criteria
got: "wrong"

Panics

For testing panics use verify.Panics() and verify.NotPanics().

Custom assertion function

You can create a function that returns FailureMessage. Use verify.And() and verify.Or() functions together with Prefix() method to create complex assertions.

package test
import (
"testing""github.com/fluentassert/verify"
)
typeAstruct {
StrstringOkbool
}
funcTestCustom(t*testing.T) {
got:=A{Str: "something was wrong"}
verifyA(got).Assert(t)
}
funcverifyA(gotA) verify.FailureMessage {
returnverify.And(
verify.String(got.Str).Contain("ok").Prefix("got.String: "),
verify.True(got.Ok).Prefix("got.Ok: "),
)
}
$ go test
--- FAIL: TestCustom (0.00s)
custom_test.go:17:
got.String: the value does not contain the substring
got: "something was wrong"
substr: "ok"
got.Ok: the value is false

Extensibility

You can take advantage of the FailureMessage and Fluent* types to create your own fluent assertions for a given type.

For reference, take a look at the implementation of existing fluent assertions in this repository (for example comparable.go).

Supported Go versions

Minimal supported Go version is 1.18.

Contributing

See CONTRIBUTING.md if you want to help.

License

fluentassert is licensed under the terms of the MIT license.

github.com/google/go-cmp (license: BSD-3-Clause) is the only third-party dependency.

About

Extensible, type-safe, fluent assertion Go library. Do NOT use it (sic!).

Topics

Resources

Code of conduct

Contributing

Stars

44 stars

Watchers

1 watching

Forks

Releases

Used by

Contributors

Languages