The most popular Go dependency is…
27 points by thiht
27 points by thiht
Doesn't surprise me that it's testify. It does surprise me that the Go team don't see the value in a set of one-line assertion helpers. Makes tests much cleaner and easier to read IMO.
Agree on this, even though I find testify a bit "bulky". In my side projects I've come to write this helper a lot:
func Err(tb testing.TB, got error, want any)
used like this:
assert.Err(t, err, nil) // want err nil
assert.Err(t, err, true) // want err
assert.Err(t, err, "message") // want err.Error() to contain "message"
assert.Err(t, err, ErrExample) // want errors.Is(err, ErrExample)
assert.Err(t, err, &ErrExample{}) // want errors.As(err, &ErrExample{}) ok
With the addition of:
func Equal(tb testing.TB, want, got any) // uses reflect.DeepEqual
func True(tb testing.TB, got bool)
it covers 99% of what I normally use testify for
Edit: I just realized I could name this lib ass, I would then use it like ass.Err(t, ... and it writes "assert"
the Go team don't see the value in a set of one-line assertion helpers
Came here to bring this up too. Back when I was learning Go at the mothership, I attempted to write tests using testify and was quickly "scolded" by the readability reviewers because assertions weren't idiomatic and "omg assertions are bad". Instead, I had to litter my code with if ... { t.Fatal(...) } constructs, which made tests overly verbose and difficult for readers to extract the essence of the test scenario.
In any case... it doesn't surprise me at all that testify would be a really popular package.
Edit: Oops, I wanted to reply to the parent, not this subcomment. Oh well.
My issue with testify is that it is too heavyweight -- there are 157 top-level functions, including helper functions that specifically target JSON, YAML, and HTTP -- in my view, those should not be placed within a testing library, but should be decoupled (ie, something like assert.True(JsonEquals(stra, strb)))
Personally, my favorite testing library is https://github.com/earthboundkid/be which "does one thing", ie, makes tests cleaner and easier to read. But does nothing else.
Shameless plug: https://code.pfad.fr/check/
Story behind this lib: https://log.pfad.fr/2024/reinventing-the-assertion-wheel/ (spoiler: it started with a lobster submission :)
Come for the title, stay for a cool use of graph databases!
github.com/pkg/errors@v0.9.1 because it's a module that was deprecated long ago, I find it interesting to know how much it's still used in the wild.
I suspect that part of the reason might be that it offered a way to store a stack trace with an error, unlike the new errors module that is the official replacement.
Speaking of testify is there a good alternative that have less dependencies? Testify's indirect dependencies is more than half of my modules deps.
https://github.com/earthboundkid/be
But these are not widely used at all.
Honestly just writing the assert helpers you need in an internal assert package can be enough, for example:
func Equal(tb testing.TB, want, got any) {
tb.Helper()
if !reflect.DeepEqual(got, want) {
tb.Fatalf("got %v, want %v", got, want)
}
}
It’s easy to maintain, easy to extend, and if at some point you need testify because of something more complex, you’ll know why :)
I noticed that Testify pulls in a large number of dependencies as well, and many of these are outdated or unmaintained.
I just wrote my own small assert package with the handful of assertions that were actually used in my project. For my assert.Equal I used https://github.com/google/go-cmp to get nice diffs, which are actually better than what Testify produces.
I normally use https://pkg.go.dev/gotest.tools/v3/assert, which only has a few top-level functions and only one dependency (go-cmp).
The module it's a part of has a few other packages I've had good experiences writing tests with.
I am one of the maintainers of https://google.github.io/styleguide/go/.
If you are curious on my thoughts on why I am not particularly bullish on assertion frameworks AND having multiple of them at once, you might find this useful: https://matttproud.com/blog/posts/testing-frameworks-and-mini-languages.html.
I found your blog post quite weak in terms of reasoning. Even in this Lobsters thread itself, we have:
Back when I was learning Go at the mothership, I attempted to write tests using testify and was quickly "scolded" by the readability reviewers because assertions weren't idiomatic and "omg assertions are bad". Instead, I had to litter my code with if ... { t.Fatal(...) } constructs, which made tests overly verbose and difficult for readers to extract the essence of the test scenario
Your post is chiefly arguing from the POV of someone doing large-scale changes. But the burden of doing large-scale changes is on fewer people, whereas the burden of reading code in basically every person touching the tests.
I've seen test files reduce by 20%+ in volume on switching from if-based checks to specific functions which handles checks in a consistent fashion.
Moreover, using if-based checks itself doesn't magically buy you consistency. I've migrated 50K+ lines of test code to more compact helper functions, and you see all sorts of inconsistencies in terms of debug output that's display when a test fails (in the Fatalf line), unlike what a specific test helper would buy you, where at least it will consistently display the LHS vs RHS all the time.
Overall, I think if your point was "there should be one way to do common operations in the codebase" (this makes large-scale refactoring easier) then I think it would be a stronger one (TBF, you did say "AND having multiple of them at once", which I would say is the main problem, really). Such uniformity doesn't require that "the one way ought to be the most primitive way of doing things."