Skip to content

[go-fan] Go Module Review: stretchr/testify #31461

@github-actions

Description

@github-actions

🐹 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.NotZerocmd/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)

  1. Sweep the 5 assert.NoError spots that deref afterward → flip to require.NoError (low risk, removes nil-panic foot-guns).
  2. Sweep assert.True(t, strings.Contains(...)) (7 occurrences) → assert.Contains for better failure output.
  3. Sweep assert.Equal(t, true/false, x) and assert.Equal(t, len(x), n) anti-patterns (~15 occurrences total).
  4. Add t.Helper() to project test helpers as part of any test refactor.
  5. 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 ·

  • expires on May 12, 2026, 8:58 AM UTC

Metadata

Metadata

Labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions