|
1 | 1 | # FluentAssert |
2 | 2 |
|
3 | | -> Extensible fluent API for assertions. |
| 3 | +> Extensible, type-safe, fluent assertion Go library. |
4 | 4 |
|
5 | 5 | [](https://pkg.go.dev/github.com/pellared/fluentassert) |
6 | 6 | [](CHANGELOG.md) |
|
12 | 12 | [](https://goreportcard.com/report/github.com/pellared/fluentassert) |
13 | 13 | [](https://codecov.io/gh/pellared/fluentassert) |
14 | 14 |
|
15 | | -## Motivation |
| 15 | +Please ⭐ `Star` this repository if you find it valuable and worth maintaining. |
16 | 16 |
|
17 | | -I always had trouble what parameter should go first and which once second. |
18 | | -Having a Fluent API makes it more obvious and easier to use |
19 | | -([more](https://dave.cheney.net/2019/09/24/be-wary-of-functions-which-take-several-parameters-of-the-same-type)). |
| 17 | +## Description |
20 | 18 |
|
21 | | -**FluentAssert** encourages to add an additional |
22 | | -[assertion message](http://xunitpatterns.com/Assertion%20Message.html) |
23 | | -as suggested in |
24 | | -[Go Code Review Comments](https://github.com/golang/go/wiki/CodeReviewComments#useful-test-failures). |
| 19 | +The fluent API makes the assertion code easier |
| 20 | +to read and write ([more](https://dave.cheney.net/2019/09/24/be-wary-of-functions-which-take-several-parameters-of-the-same-type)). |
25 | 21 |
|
26 | | -The API takes advantage of generics to make the API more type-safe. |
| 22 | +The generics (type parameters) make the usage type-safe. |
27 | 23 |
|
28 | | -`Star` this repository if you find it valuable and worth maintaining. |
| 24 | +The library is [extensible](#custom-assertions). |
29 | 25 |
|
30 | 26 | ## Quick start |
31 | 27 |
|
32 | 28 | ```go |
33 | | -func TestFoo(t *testing.T) { |
34 | | - got, err := Foo() |
35 | | - f.ErrorRequire(t, err).Nil("should be no error") // works like t.Fatalf, stops execution if fails |
36 | | - |
37 | | - f.Assert(t, got).Eq(1.23, "should return proper value") // works like t.Errorf, continues execution if fails |
38 | | - f.OrderedAssert(t, got).Gt(1, "should be greater than 1") // this will fail |
39 | | -} |
40 | | - |
41 | | -func Foo() (float64, error) { |
42 | | - return 1.23, nil |
43 | | -} |
44 | | -``` |
45 | | - |
46 | | -```sh |
47 | | -$ go test |
48 | | ---- FAIL: TestFoo (0.00s) |
49 | | - assert_test.go:14: should be greater than 1 |
50 | | - got: 1.23 |
51 | | - want greater than: 2 |
52 | | -``` |
53 | | - |
54 | | -## Extensibility |
| 29 | +package test |
55 | 30 |
|
56 | | -### Using `Should` method |
| 31 | +import ( |
| 32 | + "testing" |
57 | 33 |
|
58 | | -```go |
59 | | -func Test(t *testing.T) { |
60 | | - got := errors.New("some error") |
61 | | - |
62 | | - f.Assert(t, got).Should(BeError(), "should return an error") |
63 | | -} |
| 34 | + "github.com/pellared/fluentassert/f" |
| 35 | +) |
64 | 36 |
|
65 | | -func BeError() func(got interface{}) string { |
66 | | - return func(got interface{}) string { |
67 | | - if _, ok := got.(error); ok { |
68 | | - return "" |
69 | | - } |
70 | | - return fmt.Sprintf("got: %+v\nshould be an error", got) |
71 | | - } |
| 37 | +type A struct { |
| 38 | + Str string |
| 39 | + Bool bool |
| 40 | + Slice []int |
72 | 41 | } |
73 | | -``` |
74 | 42 |
|
75 | | -### Using type embedding |
76 | | - |
77 | | -```go |
78 | | -func Test(t *testing.T) { |
79 | | - got := errors.New("some error") |
80 | | - |
81 | | - Assert(t, got).Eq("", "should return nothing") |
82 | | - Assert(t, err).IsError("", "should return an error") |
| 43 | +func Foo() (A, error) { |
| 44 | + return A{Str: "wrong", Slice: []int{1, 4}}, nil |
83 | 45 | } |
84 | 46 |
|
85 | | -type Assertion struct { |
86 | | - f.Assertion |
| 47 | +func TestFoo(t *testing.T) { |
| 48 | + got, err := Foo() |
| 49 | + f.Obj(err).Zero().Require(t, "should be no error") // uses t.Fatal, stops execution if fails |
| 50 | + f.Obj(got).DeepEqual( |
| 51 | + A{Str: "string", Bool: true, Slice: []int{1, 2}}, |
| 52 | + ).Assert(t) // uses t.Error, continues execution if fails |
87 | 53 | } |
| 54 | +``` |
88 | 55 |
|
89 | | -func Assert(t testing.TB, got interface{}) Assertion { |
90 | | - return Assertion{f.Assert(t, got)} |
91 | | -} |
| 56 | +```sh |
| 57 | +$ go test |
| 58 | +--- FAIL: TestFoo (0.00s) |
| 59 | + foo_test.go:24: |
| 60 | + mismatch (-want +got): |
| 61 | + test.A{ |
| 62 | + - Str: "string", |
| 63 | + + Str: "wrong", |
| 64 | + - Bool: true, |
| 65 | + + Bool: false, |
| 66 | + Slice: []int{ |
| 67 | + 1, |
| 68 | + - 2, |
| 69 | + + 4, |
| 70 | + }, |
| 71 | + } |
| 72 | +``` |
92 | 73 |
|
93 | | -func Require(t testing.TB, got interface{}) Assertion { |
94 | | - return Assertion{f.Require(t, got)} |
95 | | -} |
| 74 | +## Custom assertions |
96 | 75 |
|
97 | | -func (a Assertion) IsError(msg string, args ...interface{}) bool { |
98 | | - a.T.Helper() |
99 | | - return a.Should(beError(), msg, args...) |
100 | | -} |
| 76 | +You can take advantage of the `f.FailureMessage` and `f.Fluent*` types |
| 77 | +to create your own fluent assertions. |
101 | 78 |
|
102 | | -func beError() func(got interface{}) string { |
103 | | - return func(got interface{}) string { |
104 | | - if _, ok := got.(error); ok { |
105 | | - return "" |
106 | | - } |
107 | | - return fmt.Sprintf("got: %+v\nshould be an error", got) |
108 | | - } |
109 | | -} |
110 | | -``` |
| 79 | +For reference, take a look at the implementation |
| 80 | +of existing fluent assertions in this repository |
| 81 | +(for example [comparable.go](f/comparable.go)). |
111 | 82 |
|
112 | 83 | ## Contributing |
113 | 84 |
|
114 | | -I am open to any feedback and contribution. |
| 85 | +Feel free to create an issue or propose a pull request. |
| 86 | + |
| 87 | +### Developing |
115 | 88 |
|
116 | | -Use [Discussions](https://github.com/pellared/fluentassert/discussions) |
117 | | -or write to me: *Robert Pajak* @ [Gophers Slack](https://invite.slack.golangbridge.org/). |
| 89 | +Run `./goyek.sh` (Bash) or `.\goyek.ps1` (PowerShell) |
| 90 | +to execute the build pipeline. |
118 | 91 |
|
119 | | -You can also create an issue or a pull request. |
| 92 | +The repository contains confiugration for |
| 93 | +[Visual Studio Code](https://code.visualstudio.com/). |
0 commit comments