-
Notifications
You must be signed in to change notification settings - Fork 50
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
Discussion: cmp.ErrorIs is not a full replacement for cmp.ErrorType, but is now deprecated #272
Comments
👋 @dnephin happy to hear your thoughts (or perhaps I overlooked an approach 😂) |
Hi @thaJeztah ! Thanks for raising this issue. The way I would generally check error types would be: // using func(err) bool
assert.Assert(t, IsNotFound(err), "err=%v", err
// using errors.As
typedErr, ok := errors.As(t, err)
assert.Assert(t, ok, "err (%T) = %v", err, err) But I do realize these forms are a bit difficult to discover right now because the examples are only in the package godoc, and not in the godoc for I've been thinking a bit about how to reduce the interface of the // True fails the test with [t.FailNow] if the value of expr is false.
// True uses the Go source and comments in the test function to print a
// helpful failure message. Extra values can be passed to provide
// the full context for the message.
// If True fails and there are no extra values, it will rewrite the test
// Go source to add any variables that were found in the Go source that
// created expr.
//
// Error is a type (error.As)
//
// err := ScheduleWork()
// errV := &CustomErrorType{}
// assert.True(t, errors.As(err, &errV), err)
// // main_test.go:17: We wanted err := DoSomeWork() to be &CustomErrorType,
// // but it was fs.PathError with a value of: file not found.
//
// Error is a value
//
// fi, err := os.Stat("./output")
// assert.True(t, errors.Is(err, fs.ErrNotfound), err)
// // main_test.go:23: We wanted err := os.Stat("./output") to be fs.ErrNotFound,
// // but it was nil.
//
// Error contains a message
//
// err := GetAccount()
// contains := "account id"
// assert.True(t, err != nil && strings.Contains(err, contains), err)
// // main_test.go:28: We wanted err := GetAccount() to contain
// // "account id", but it was "connection failed".
//
// Map contains a value
//
// v, ok := settings["max"]
// assert.True(t, ok, settings)
// // main_test.go:32: We wanted settings to have the key "max", but it did not.
// // settings=map[min: 34].
//
// Fail with t.Fail instead of t.FailNow
//
// assert.True(assert.AndContinue(t), false)
func True(t TestingT, expr bool, values ...any) bool { ... } If the function is able to rewrite the test to add the extra assert.True(t, IsNotFound(err))
// main_test.go:45: We wanted IsNotFound(err) to be true, but it was false.
// Successfully updated the test to include the value of err! Run the test again
// for a better error message. Run the test once to show it is testing what you expect and fails when the behaviour isn't implement (generally good practice anyway), and then end up with: assert.True(t, IsNotFound(err), err)
// main_test.go:45: We wanted IsNotFound(err) to be true, but err was *errors.errorString with value: "something else" I'm really hoping to be able to lean into a much smaller interface (maybe even just 4 functions |
Oh boy, for some reason I missed your reply 🙈 🙈 🙈, thanks!!
Yes, I was considering variations thereof. I guess we were lucky that the To be really honest;
Yes, big nod there, and also something I ("we") should look at contributing.
Need to take a deeper look at your proposal. I definitely like simplifying things further. That said; discoverability is important, and yes, documentation may be key there, so more examples would be a good thing to have. Some of those examples could be basic principles, such as "when to use |
I noticed the
ErrorType
compare was deprecated, and when updating gotest.tools, I found quite some checks in our codebase that depend on it. Looking atErrorIs()
I feel like that's not a full replacement.While
ErrorIs()
works to match an exact error (or an error wrapped by another error), it does not provide ways to check for an error type. (I guess some equivalent oferrors.As
). That said I found the ability to provide a check function also to be very convenient (in Moby, we have theerrdefs
package, which has functions to match each of the type).I'm probably able to craft my own way around this, but wondering if there's something missing in gotest's comparers.
For some quick comparison / example:
The text was updated successfully, but these errors were encountered: