Skip to content

Discussion: cmp.ErrorIs is not a full replacement for cmp.ErrorType, but is now deprecated #272

@thaJeztah

Description

@thaJeztah

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 at ErrorIs() 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 of errors.As). That said I found the ability to provide a check function also to be very convenient (in Moby, we have the errdefs 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:

type customError struct {
	Name  string
	Value []string
}

func (e *customError) Error() string {
	return fmt.Sprintf("invalid name: %s (%s)", e.Name, e.Value)
}

func (e *customError) InvalidParameter() {}

type invalidParameter interface {
	InvalidParameter()
}

func isInvalidParameter(err error) bool {
	_, ok := err.(invalidParameter)
	return ok
}

func TestErrorIsVsErrorType(t *testing.T) {
	var expectedType *customError
	expectedErr := &customError{Name: "hello", Value: []string{"world"}}

	actualErr := &customError{Name: "hello", Value: []string{"world"}}
	wrapped := fmt.Errorf("something went wrong: %w", expectedErr)

	if result := ErrorType(actualErr, expectedErr)(); !result.Success() {
		t.Error(result.(StringResult).FailureMessage())
	}
	if result := ErrorType(actualErr, isInvalidParameter)(); !result.Success() {
		t.Error(result.(StringResult).FailureMessage())
	}

	if !errors.As(actualErr, &expectedType) {
		t.Error("type compare failed")
	}

	if result := ErrorIs(wrapped, expectedErr)(); !result.Success() {
		t.Error(result.(templatedResult).FailureMessage(nil))
	}
	if result := ErrorIs(actualErr, expectedErr)(); !result.Success() {
		t.Error(result.(templatedResult).FailureMessage(nil))
	}
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions