🐹 Go Fan Report: stretchr/testify
Module Overview
testify is the de-facto Go testing toolkit, providing rich assertions (assert), fail-fast preconditions (require), mocks (mock), and test suites (suite). gh-aw uses only assert and require — the two sub-packages that compose with the standard testing package without changing the test runner.
Current Usage in gh-aw
- Version:
v1.11.1 (latest stable, released 2025-08-27) — fully up to date ✅
- Files: 491 Go files import testify
- Sub-packages:
assert (480 imports), require (438 imports). mock, suite, and http are not used.
- Top APIs:
require.NoError (3,873), assert.Equal (3,467), assert.Contains (3,303), require.NotNil (1,016), assert.True (768)
Research Findings
Recent Updates (v1.11.0 / v1.11.1)
- Performance: lazy mock diff rendering, faster
isEmpty via reflect.Value.IsZero, short-circuits for JSONEq / YAMLEq when the input strings are equal, and an optimized CallerInfo stack walk.
- New API:
assert.IsNotType (complement to IsType).
- Better failure messages for
ErrorAs, ErrorIs, Subset, Positive, Negative, AssertNumberOfCalls.
Helper() adoption: testify's own CollectT and internal mocks now mark themselves as helpers so failures point at the test, not the framework.
- v1.11.1 hotfix: restored pre-v1.11.0 mock argument matching for stringers that mutate state inside
String() (#1788).
Best Practices Reinforced by Recent Releases
- Use
require for preconditions that make later assertions meaningless on failure.
- Use
assert.Contains / assert.ErrorIs / assert.ErrorAs instead of wrapping strings.Contains / errors.Is in assert.True — the helpers produce far better diagnostics.
- Mark custom test helpers with
t.Helper() so failures point at the call site.
Improvement Opportunities
🏃 Quick Wins
assert.Equal(t, true|false, x) → assert.True/False(t, x) — ~10 occurrences in pkg/workflow/safe_outputs_config_generation_test.go and pkg/parser/frontmatter_helpers_test.go. Yields cleaner failure messages.
assert.Equal(t, len(x), y) → assert.Len(t, x, y) — 5 occurrences (pkg/workflow/codex_logs_test.go:95-96, pkg/cli/workflows_count_test.go:81, pkg/cli/health_metrics_test.go:81, pkg/cli/audit_expanded_test.go:617). Also fixes the swapped expected/actual order.
assert.True(t, strings.Contains(s, sub)) → assert.Contains(t, s, sub) — 7 occurrences across pkg/workflow/* and pkg/console/verbose_test.go:68. Better diff on failure.
assert.NotEqual(t, 0, exitCode) → assert.NotZero — cmd/gh-aw/main_entry_test.go:275.
✨ Feature Opportunities
assert.IsNotType (new in v1.11.0) — currently unused; consider when negative type checks come up.
require.EventuallyWithT / assert.EventuallyWithT — 0 uses today, 3 uses of plain require.Eventually. v1.11.0 added early-condition-check, making them cheap. Worth using instead of hand-rolled poll loops in any future flaky-by-design tests (watcher integration, fs event tests).
assert.ErrorIs / assert.ErrorAs — only ~10 uses; broader adoption would replace ad-hoc assert.True(t, errors.Is(...)) patterns and surface unwrap chains on failure.
📐 Best Practice Alignment
require.NoError for error-then-deref patterns: 207 assert.NoError calls across the codebase. Most are fine (table tests inside if err == nil { ... }), but at least 5 spots continue to use the result without guarding and should switch to require.NoError to avoid panics that mask the real failure:
pkg/agentdrain/miner_test.go:299
pkg/parser/import_cache_test.go:291
pkg/parser/import_conflict_test.go:128, :169
pkg/workflow/lock_schema_test.go:217
t.Helper() is underused: 73 calls across ~1,117 test functions. Mark project-local helpers (validators, fixture builders, lockfile constructors) with t.Helper() so the failure line points at the test, mirroring what testify itself adopted in v1.11.
🔧 General Improvements
- The project consistently uses
require for preconditions and assert for diagnostics — the inconsistencies above are isolated cleanups, not a systemic pattern issue.
- No use of
mock/suite. Given the project's strong table-driven testing style, that's a deliberate, idiomatic choice — no change recommended.
Recommendations (Prioritized)
- Sweep the 5
assert.NoError spots that deref afterward → flip to require.NoError (low risk, removes nil-panic foot-guns).
- Sweep
assert.True(t, strings.Contains(...)) (7 occurrences) → assert.Contains for better failure output.
- Sweep
assert.Equal(t, true/false, x) and assert.Equal(t, len(x), n) anti-patterns (~15 occurrences total).
- Add
t.Helper() to project test helpers as part of any test refactor.
- No version bump needed — already on v1.11.1.
Next Steps
- Open follow-up PRs per category above. Each is mechanical and low-risk.
- Consider adding a
staticcheck / go vet lint config that flags the assert.True(strings.Contains) and assert.Equal(len(...)) anti-patterns automatically.
Generated by Go Fan 🐹
Module summary saved to: scratchpad/mods/testify.md
Workflow run: §25660106559
Generated by Go Fan · ● 7M · ◷
🐹 Go Fan Report: stretchr/testify
Module Overview
testify is the de-facto Go testing toolkit, providing rich assertions (
assert), fail-fast preconditions (require), mocks (mock), and test suites (suite). gh-aw uses onlyassertandrequire— the two sub-packages that compose with the standardtestingpackage without changing the test runner.Current Usage in gh-aw
v1.11.1(latest stable, released 2025-08-27) — fully up to date ✅assert(480 imports),require(438 imports).mock,suite, andhttpare not used.require.NoError(3,873),assert.Equal(3,467),assert.Contains(3,303),require.NotNil(1,016),assert.True(768)Research Findings
Recent Updates (v1.11.0 / v1.11.1)
isEmptyviareflect.Value.IsZero, short-circuits forJSONEq/YAMLEqwhen the input strings are equal, and an optimizedCallerInfostack walk.assert.IsNotType(complement toIsType).ErrorAs,ErrorIs,Subset,Positive,Negative,AssertNumberOfCalls.Helper()adoption: testify's ownCollectTand internal mocks now mark themselves as helpers so failures point at the test, not the framework.String()(#1788).Best Practices Reinforced by Recent Releases
requirefor preconditions that make later assertions meaningless on failure.assert.Contains/assert.ErrorIs/assert.ErrorAsinstead of wrappingstrings.Contains/errors.Isinassert.True— the helpers produce far better diagnostics.t.Helper()so failures point at the call site.Improvement Opportunities
🏃 Quick Wins
assert.Equal(t, true|false, x)→assert.True/False(t, x)— ~10 occurrences inpkg/workflow/safe_outputs_config_generation_test.goandpkg/parser/frontmatter_helpers_test.go. Yields cleaner failure messages.assert.Equal(t, len(x), y)→assert.Len(t, x, y)— 5 occurrences (pkg/workflow/codex_logs_test.go:95-96,pkg/cli/workflows_count_test.go:81,pkg/cli/health_metrics_test.go:81,pkg/cli/audit_expanded_test.go:617). Also fixes the swapped expected/actual order.assert.True(t, strings.Contains(s, sub))→assert.Contains(t, s, sub)— 7 occurrences acrosspkg/workflow/*andpkg/console/verbose_test.go:68. Better diff on failure.assert.NotEqual(t, 0, exitCode)→assert.NotZero—cmd/gh-aw/main_entry_test.go:275.✨ Feature Opportunities
assert.IsNotType(new in v1.11.0) — currently unused; consider when negative type checks come up.require.EventuallyWithT/assert.EventuallyWithT— 0 uses today, 3 uses of plainrequire.Eventually. v1.11.0 added early-condition-check, making them cheap. Worth using instead of hand-rolled poll loops in any future flaky-by-design tests (watcher integration, fs event tests).assert.ErrorIs/assert.ErrorAs— only ~10 uses; broader adoption would replace ad-hocassert.True(t, errors.Is(...))patterns and surface unwrap chains on failure.📐 Best Practice Alignment
require.NoErrorfor error-then-deref patterns: 207assert.NoErrorcalls across the codebase. Most are fine (table tests insideif err == nil { ... }), but at least 5 spots continue to use the result without guarding and should switch torequire.NoErrorto avoid panics that mask the real failure:pkg/agentdrain/miner_test.go:299pkg/parser/import_cache_test.go:291pkg/parser/import_conflict_test.go:128,:169pkg/workflow/lock_schema_test.go:217t.Helper()is underused: 73 calls across ~1,117 test functions. Mark project-local helpers (validators, fixture builders, lockfile constructors) witht.Helper()so the failure line points at the test, mirroring what testify itself adopted in v1.11.🔧 General Improvements
requirefor preconditions andassertfor diagnostics — the inconsistencies above are isolated cleanups, not a systemic pattern issue.mock/suite. Given the project's strong table-driven testing style, that's a deliberate, idiomatic choice — no change recommended.Recommendations (Prioritized)
assert.NoErrorspots that deref afterward → flip torequire.NoError(low risk, removes nil-panic foot-guns).assert.True(t, strings.Contains(...))(7 occurrences) →assert.Containsfor better failure output.assert.Equal(t, true/false, x)andassert.Equal(t, len(x), n)anti-patterns (~15 occurrences total).t.Helper()to project test helpers as part of any test refactor.Next Steps
staticcheck/go vetlint config that flags theassert.True(strings.Contains)andassert.Equal(len(...))anti-patterns automatically.Generated by Go Fan 🐹
Module summary saved to:
scratchpad/mods/testify.mdWorkflow run: §25660106559