feat: add ErrorAsType assertions for Go 1.27 - #1937
Conversation
Go 1.27 makes it possible to expose generic assertions through the same function and method surfaces as existing assertions. Teach the generator to preserve that API shape so generic additions remain generated and maintainable rather than becoming handwritten exceptions. Inspecting and rendering generic signatures relies on go/types APIs added in Go 1.18. The codegen module therefore declares Go 1.18 as its actual minimum; this does not change the Go 1.17 minimum of the main Testify module.
Provide a typed alternative to ErrorAs that returns the matched error without requiring callers to declare a target variable, while retaining Testify's useful failure diagnostics. Go 1.27 generic methods allow the API to remain consistent across package functions and Assertions objects.
As stable and oldstable advance to Go 1.27 and Go 1.26, retain explicit Go 1.25 coverage so every supported release remains tested. Run language-level formatting validation with the stable toolchain because Go 1.26 cannot parse generic methods, even in files excluded by build constraints. Several CI helpers could previously report success when their underlying commands, generation checks, or action-pin validation failed. Ensure those failures are propagated and newly generated files are detected so a green build means the checks actually completed successfully.
8b5b3d8 to
0852043
Compare
|
While reviewing the CI run, I noticed that the Go 1.26 I updated the CI changes to:
The updated checks now fail when their underlying validation fails, rather than producing error annotations within an otherwise successful job. |
|
Please move the CI changes to a separate PR. |
Done in #1941. I'll rebase this PR after it's merged. Thanks. |
The August sweep of stretchr/testify turned up four reports describing bugs we had inherited. Each now has a row in the implemented table saying what we adopted and what we left alone, and stretchr#1942 joins stretchr#1940 as the PR behind ErrorNotContains. stretchr#1776 goes in as informational: upstream's generated require documentation lists a bool return that the functions do not have, the same defect our own API pages carried until the signature tables were corrected. Nothing to adopt, but worth recording that both projects found it independently. Two more bugs surfaced while checking those four, neither of them reported upstream, so neither gets a row: InDeltaSlice named expected and actual the wrong way round in its failures, and EqualValues compared a negative signed integer equal to a large unsigned one. Also in this file: the review-frequency line was three months stale, [stretchr#1937] was referenced with no link definition and rendered as literal text, three definitions were duplicated, and the summary counts are recounted from the tables. reference: github.com/stretchr#1776 reference: github.com/stretchr#1874 reference: github.com/stretchr#1875 reference: github.com/stretchr#1898 reference: github.com/stretchr#1899 reference: github.com/stretchr#1908 reference: github.com/stretchr#1931 reference: github.com/stretchr#1940 reference: github.com/stretchr#1942 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Frederic BIDON <fredbi@yahoo.com>
|
The issue I see here, is the fact I feel like it break the logic of assert.Whatever returns true/false |
Summary
Add generic
ErrorAsTypeandNotErrorAsTypeassertions for Go 1.27 consumers.The underlying
errors.AsTypefunction arrived in Go 1.26, but Testify could not expose an equivalent API consistently because Go did not yet support generic methods. Go 1.27 removes that restriction, allowing these assertions to be generated as both package functions and methods onAssertions.These assertions return the matched error with its concrete type while preserving Testify's failure diagnostics.
Closes #1860.
Motivation
Previously, checking and then using a specific error type required a separate target variable:
With this change:
The
assertvariant also returns whether the assertion succeeded:This avoids the target variable and subsequent cast without losing Testify's error-chain diagnostics.
Added API
For Go 1.27 and later, package
assertadds:The same assertions are available as generic methods:
Package
requireadds corresponding functions:These are also available as methods on
require.Assertions:The
require.ErrorAsTypevariants return the matched error directly after terminating the test on failure.Code Generation
The code generator now supports:
bool.requirefunctions that return typed values.This keeps the new functions and methods generated consistently with Testify's existing API rather than introducing handwritten exceptions.
The
_codegenmodule now requires Go 1.18 because generic signature inspection usesgo/typesAPIs introduced in that release. This does not change Testify's Go 1.17 minimum._codegenis a separate module used only during generation.Compatibility
All new API and generated files use:
//go:build go1.27The main module remains compatible with Go 1.17. Existing generated output remains stable when generation is run under Go 1.26.
The CI matrix also adds explicit Go 1.25 coverage. Go 1.26 and Go 1.27 are covered by
oldstableandstable.Testing
The tests cover:
Assertionsmethods.assertandrequirebehavior.Potential Future Work
The following APIs are suggestions for separate future changes. They are not included in this PR.
The generic code-generation support introduced here could enable a small number of additional assertions whose implementations genuinely rely on generic operations.
AsTypeThis could perform a type assertion against a type parameter:
It could validate and return either a concrete type or an interface implementation.
PanicsAsTypeThis could apply a generic type assertion to the recovered panic value and return the typed payload for further inspection.
Typed channel assertions
Arbitrary typed channels cannot be converted to
<-chan any, so assertions that accept and return their element type could also use generics directly:This PR intentionally remains focused on
ErrorAsType; these APIs are listed only to show where the new generator support could be useful.