-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Initial implementation of the expect package #1
Conversation
.github/workflows/ci.yml
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Based on https://github.com/nicheinc/pgsql/blob/main/.github/workflows/ci.yml, as is much of the library boilerplate.
[![Build Status](https://github.com/nicheinc/expect/actions/workflows/ci.yml/badge.svg)](https://github.com/nicheinc/expect/actions/workflows/ci.yml) | ||
[![Go Report Card](https://goreportcard.com/badge/github.com/nicheinc/expect)](https://goreportcard.com/report/github.com/nicheinc/expect) | ||
[![Godoc](https://godoc.org/github.com/nicheinc/expect?status.svg)](https://godoc.org/github.com/nicheinc/expect) | ||
[![license](https://img.shields.io/github/license/nicheinc/expect.svg?cacheSeconds=2592000)](LICENSE) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
None of these badges will work unless we decide to open-source this. (Not sure if that's something we'd want to do, but I also don't see a reason why we couldn't.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd be good with feeding the OSS machine
[![Build Status](https://github.com/nicheinc/expect/actions/workflows/ci.yml/badge.svg)](https://github.com/nicheinc/expect/actions/workflows/ci.yml) | ||
[![Go Report Card](https://goreportcard.com/badge/github.com/nicheinc/expect)](https://goreportcard.com/report/github.com/nicheinc/expect) | ||
[![Godoc](https://godoc.org/github.com/nicheinc/expect?status.svg)](https://godoc.org/github.com/nicheinc/expect) | ||
[![license](https://img.shields.io/github/license/nicheinc/expect.svg?cacheSeconds=2592000)](LICENSE) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd be good with feeding the OSS machine
errors.go
Outdated
// } | ||
// | ||
// [test helper function]: https://pkg.go.dev/testing#T.Helper | ||
type ErrorCheck func(*testing.T, error) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thoughts on an signature/usage pattern more like
func CheckError(t *testing.T, check ErrorCheck, err error) {
if check == nil {
check = ErrorNil
}
check(t, err)
}
s.t. the zero value for ErrorCheck is equivalent to ErrorNil?
Might save a bunch of boilerplate, but we could add it after the initial release
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess callers could do this as well
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I definitely want to minimize boilerplate if possible. (That is this library's raison d'etre after all.) This approach sounds pretty similar to option 2 in the "Nil Errors" part of the PR writeup (the difference being whether the guarded function is standalone or a method on ErrorCheck
) - right? I've been leaning slightly towards either option 1 or option 3 to avoid inconsistencies/foot-guns, but I could be swayed in any direction. 🤷♂️
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I definitely missed that section. If you're feeling hesitant, let's keep option 3 - we can always add functionality like this in the future. I don't love option 1 purely on the basis of it feeling clunky to add a custom check.
Dependencies
dev
)dev
)Documentation
Description
Initial implementation of the
expect
package, which provides a few simple test functions to reduce boilerplate in our unit tests. I've experimented with this inmap@x/expect
) andfact@x/expect
(no plans to merge those branches for the time being).Nil Errors
Currently in our unit tests we usually store an expected
error
in our test case struct, and we often omit that field from test cases where the error is expected to benil
, relying on the zero value oferror
. @wmarshall floated the idea at BENG of making the zero value ofErrorCheck
useful (checking thaterr == nil
by default) so that we can continue that pattern. I can think of a couple ways to do this:ErrorCheck
into a struct containing a function. GiveErrorCheck
a method that skips calling this function field if it'snil
and instead callsErrorNil
.ErrorCheck
a function type but add a method similar to option 1:ErrorNil
if you want that check. Worth noting that for test tables that all useexpect.ErrorIs
, we can keep theerror
field in the test case struct and continue to (implicitly) passnil
, if we want. (I also don't think it's necessarily bad having to be explicit about expected errors.)Option 1 is safe but adds a little noise to test bodies since we have to call a method now instead of just using
()
. Option 2 keeps the shorter syntax available but also makes it easy to do the wrong thing, and it means we have two ways to do essentially the same thing. The existing version has consistent and brief test body syntax but requires initialization. Pick your poison? 🤔More Specific Equal Checks
Perhaps controversially, I haven't included special functions for checking stub call counts, expected arguments, etc. In my opinion, these don't provide much value over the generic
expect.Equal
.expect.Equal
is a helper (i.e. callst.Helper
), so if the check fails, thetesting
package will print not only the name of the failed test but also the line number of the call. Checking the line where the check failed should typically give enough context for its purpose.cmpopts
WrappersThe
cmpopts
package already provides options for things like approximate comparisons (EquateApprox
,EquateApproxTime
), etc.I did include
EqualUnordered
, which is a kind of wrapper for theSortSlices
option because I find that one a little verbose in the common case where we just want to use<
for thelessFunc
. We should keep an eye out for other commonly used options to see if they're worth baking intoexpect
. That said, the disadvantage of named wrappers is that we can't compose them as easily ascmp.Option
s.Test Error Values
Instead of or in addition to
ErrTest
, I considered a function that's just likeerrors.New
except that it returns the exact same error for the same input. For example, two different calls toexpect.NewTestError("foo")
would be==
-equal - and would therefore also beerrors.Is
-equal. (Implementation-wise, we could store the errors in an unexported package-scope map keyed by error message.) This would allow tests to use multiple different errors - as many as necessary - without having to pre-declare them. I think there are few if any real use cases for this though, so I left this out for now.Versioning
Version 0.1.0. This is somewhat experimental and probably not ready for v1.