Go testing framework with extra sugar
This Go testing framework has the following goals:
- Play nice with
go test
- Provide a fluent API for making assertions
- Provide a succinct yet informative error information on failures
- Make testing easier to read and write
This library is heavily inspired by Gomega and Ginkgo, two excellent Go testing libraries that I've used extensively in the past. If you need a full standalone (see below) BDD testing framework, those are highly recommended.
The reason Justest was created is because Gomega and Ginkgo do not play great with go test
(though Gomega does have a
go test
integration, it's still primarily meant to be used with Ginkgo) whereas Justest is meant all along to be used
with go test
.
package my_test
import (
"fmt"
"regexp"
"testing"
"time"
. "github.com/arikkfir/justest"
)
func TestSomething(t *testing.T) {
// Simple assertions
With(t).VerifyThat(1).Will(BeBetween(0, 2)).Now()
With(t).VerifyThat("").Will(BeEmpty()).Now()
With(t).VerifyThat([]int{1, 2, 3}).Will(BeEmpty()).Now() // <-- This will fail!
With(t).VerifyThat(1).Will(BeGreaterThan(0)).Now()
With(t).VerifyThat(1).Will(BeLessThan(2)).Now()
With(t).VerifyThat("abc").Will(BeNil()).Now() // <-- This will fail!
With(t).VerifyThat(1).Will(EqualTo(1)).Now()
With(t).VerifyThat("abc").Will(EqualTo("def")).Now() // <-- This will fail!
// Assert success or failure of a function (functions can have any set of return values or none at all)
succeedingFunc := func() (string, error) { return "abc", nil }
With(t).VerifyThat(succeedingFunc).Will(Succeed()).Now() // <-- Will succeed since error return value is nil
With(t).VerifyThat(succeedingFunc).Will(Fail()).Now() // <-- Will fail since it expects error return value to be non-nil
failingFunc := func() (string, error) { return "", fmt.Errorf("error") }
With(t).VerifyThat(failingFunc).Will(Succeed()).Now() // <-- Will fail since error return value is not nil
With(t).VerifyThat(failingFunc).Will(Fail()).Now() // <-- Will succeed since it expects error return value to be non-nil
// Assert negation of another assertion
With(t).VerifyThat(1).Will(Not(EqualTo(2))).Now()
// Assert something will **eventually** match
// It will stop when the function succeeds (no assertion failure) or when time runs out
With(t).VerifyThat(func(t T) {
// Will be invoked every 100ms until either it no longer fails or until time runs out (10s)
With(t).VerifyThat(2).Will(EqualTo(2)).Now()
}).Will(Succeed()).Within(10*time.Second, 100*time.Millisecond)
// Assert something will **repeatedly** match for a certain amount of time
// It will stop on the first time the function fails
With(t).VerifyThat(func(t T) {
// Will be invoked every 100ms until either it fails or until time runs out (10s)
With(t).VerifyThat(2).Will(EqualTo(2)).Now()
}).Will(Succeed()).For(10*time.Second, 100*time.Millisecond)
// Assert on text patterns
With(t).VerifyThat("abc").Will(Say("^a*c$")).Now()
With(t).VerifyThat("abc").Will(Say(regexp.MustCompile("^a*c$"))).Now()
With(t).VerifyThat([]byte("abc")).Will(Say("^a*c$")).Now()
}
You can easily create your own matchers by implementing the Matcher
interface:
package my_test
import (
"reflect"
. "github.com/arikkfir/justest"
)
var (
myValueExtractor = NewValueExtractor(ExtractSameValue)
)
// BeSuperDuper returns a matcher that will ensure that each actual value passed to "With(t).VerifyThat(...)" will be either
// "super duper" or "extra super duper", depending on the value of the `extraDuper` parameter.
func BeSuperDuper(extraDuper bool) Matcher {
return MatcherFunc(func(t T, actuals ...any) {
GetHelper(t).Helper()
for _, actual := range actuals {
v := myValueExtractor.MustExtractValue(t, actual) // This is optional, but recommended, see value extraction below
if extraDuper {
// Fail if it's not EXTRA super-duper
if v.(string) != "extra super duper" {
t.Fatalf("Value '%s' is not extra super-duper!", v)
}
} else {
// Fail if it's not super-duper
if v.(string) != "super duper" {
t.Fatalf("Value '%s' is not super-duper!", v)
}
}
}
})
}
Matcher Name | Description |
---|---|
BeBetween(min, max) |
Checks that all given values are between a minimum and maximum value |
BeEmpty() |
Checks that all given values are empty |
BeGreaterThan(min) |
Checks that all given values are greater than a minimum value |
BeLessThan(max) |
Checks that all given values are less than a maximum value |
BeNil() |
Checks that all given values are nil |
EqualTo(expected) |
Checks that all given values are equal to their corresponding expected value |
Fail() |
Checks that the last given value is a non-nil error instance |
Not() |
Checks that the given matcher fails |
Say() |
Checks that all given values match the given regular expression |
Succeed() |
Checks that the last given value is either nil or not an error instance |
Please do 👌 💪 !
See CONTRIBUTING.md for more information 🙏