Skip to content

Conversation

@amery
Copy link
Contributor

@amery amery commented Aug 4, 2025

User description

feat: Add Testing Infrastructure Enhancements and Generic Type Utilities

Summary

This PR adds comprehensive testing infrastructure enhancements with Fatal/
FailNow support and introduces new generic type conversion utilities. The
changes focus on improving test reliability through early abort mechanisms
and providing robust type conversion patterns.

Key Changes

Testing Infrastructure Enhancements

  • Fatal/FailNow Support: Added comprehensive Fatal and FailNow support to
    the T interface with thread-safe MockT implementation using panic recovery.
  • AssertMustFoo Variants: Added 14 new assertion functions that call
    t.FailNow() on failure, providing cleaner alternatives to manual error
    handling patterns.
  • Early Abort Tests: Enhanced testing patterns that terminate immediately
    on assertion failure rather than continuing with invalid state.
  • MockT.Run() Method: Added panic recovery method for testing assertion
    functions that may call Fatal/FailNow methods.

Generic Type Conversion Utilities

  • MustT/MaybeT Pattern: Added generic type conversion utilities using
    direct type assertions for consistent error handling.
  • MustT Function: Panics on type conversion failure with descriptive error
    messages including source and target type information.
  • MaybeT Function: Returns zero value on type conversion failure, providing
    graceful degradation for non-critical conversions.
  • Single Generic Parameter: Clean interface requiring only target type
    specification, accepting any value as input.

Technical Details

Testing Framework Improvements

The enhanced testing infrastructure provides:

  • Complete testing.T compatibility with Fatal, Fatalf, and FailNow methods.
  • Thread-safe MockT implementation with optimised mutex usage.
  • Special errMockTFailNow error for proper panic recovery.
  • Early abort patterns for critical test failures.

Type Conversion Design

The MustT/MaybeT utilities provide:

  • Equivalent to MustOK(As[any, T]) and MaybeOK(As[any, T]) compositions.
  • Type conversion across basic types, interfaces, and complex scenarios.
  • Descriptive panic messages with type information for debugging.
  • Building blocks for custom conversion failure handling.

Coverage and Documentation

  • Comprehensive test coverage with 97.0-97.1% coverage across modules.
  • Updated README.md with clear Error vs Fatal pattern explanations.
  • Enhanced TESTING.md and TESTING_core.md with new capabilities.
  • Complete usage examples demonstrating composability patterns.

Breaking Changes

None. All changes are additive and maintain backward compatibility.

Files Modified

Core Functionality

  • panic.go: Added MustT/MaybeT generic type conversion utilities.
  • testing.go: Enhanced with Fatal/FailNow support and AssertMustFoo variants.

Documentation

  • README.md: Updated with new utility explanations and usage examples.
  • TESTING.md: Enhanced with Fatal/FailNow testing patterns.
  • TESTING_core.md: Updated with comprehensive testing guidelines.

Test Coverage

  • panic_test.go: Comprehensive tests for type conversion utilities.
  • testing_test.go: Enhanced tests for Fatal/FailNow functionality.
  • internal/build/cspell.json: Updated dictionary for technical terms.

PR Type

Enhancement, Tests


Description

  • Add comprehensive Fatal/FailNow support to testing infrastructure

  • Introduce MustT/MaybeT generic type conversion utilities

  • Add 14 AssertMustFoo functions for early test termination

  • Enhance MockT with panic recovery capabilities


Diagram Walkthrough

flowchart LR
  A["panic.go"] --> B["MustT/MaybeT functions"]
  C["testing.go"] --> D["Fatal/FailNow support"]
  C --> E["AssertMustFoo functions"]
  D --> F["MockT.Run() method"]
  G["Documentation"] --> H["README.md updates"]
  G --> I["TESTING.md updates"]
  B --> J["Type conversion utilities"]
  E --> K["Early abort patterns"]
Loading

File Walkthrough

Relevant files
Enhancement
panic.go
Add generic type conversion utilities                                       

panic.go

  • Add MustT[T](value any) T function for type conversion with panic on
    failure
  • Add MaybeT[T](value any) T function for type conversion with zero
    value fallback
  • Include comprehensive documentation and examples for both functions
+37/-0   
testing.go
Add Fatal/FailNow support and early abort assertions         

testing.go

  • Add Fatal, Fatalf, and FailNow methods to T interface
  • Implement Fatal/FailNow support in MockT with panic recovery
  • Add Run() method to MockT for testing functions that call
    Fatal/FailNow
  • Add 14 AssertMustFoo functions that call FailNow() on assertion
    failure
  • Optimize MockT performance by pre-formatting messages before mutex
    locks
+283/-4 
Tests
panic_test.go
Add comprehensive tests for type conversion utilities       

panic_test.go

  • Add comprehensive test cases for MustT success and panic scenarios
  • Add test cases for MaybeT with successful and failed conversions
  • Include helper mockStringer type for interface testing
  • Add test case type declarations and factory functions
+239/-0 
testing_test.go
Add comprehensive tests for Fatal/FailNow functionality   

testing_test.go

  • Add comprehensive tests for MockT Fatal, Fatalf, and FailNow methods
  • Add tests for MockT.Run() method with panic recovery
  • Add extensive tests for early abort patterns and AssertMustFoo
    functions
  • Include tests for concurrent scenarios and edge cases
+549/-0 
Documentation
README.md
Update documentation for new utilities                                     

README.md

  • Update panic utilities section with MustT/MaybeT documentation
  • Add examples showing type conversion patterns and usage
  • Update testing section with Fatal assertion documentation
  • Add explanation of Error vs Fatal assertion patterns
+88/-13 
TESTING.md
Add Fatal assertion documentation and patterns                     

TESTING.md

  • Add Fatal Assertions section explaining AssertMustFoo functions
  • Add documentation for testing Fatal/FailNow scenarios with MockT.Run()
  • Update assertion hierarchy guidelines and examples
  • Convert bullet points to consistent markdown formatting
+72/-29 
TESTING_core.md
Update core testing documentation                                               

TESTING_core.md

  • Add documentation for MockT Fatal/FailNow support and panic recovery
  • Add comprehensive examples for testing fatal assertion scenarios
  • Update MockT capabilities section with new features
+47/-0   
Configuration changes
cspell.json
Update spell check dictionary                                                       

internal/build/cspell.json

  • Add "Fatalf" to dictionary for spell checking
+1/-0     

Summary by CodeRabbit

  • New Features

    • Introduced new generic type conversion utilities that panic or return zero values on failure.
    • Added a comprehensive set of fatal assertion helper functions for immediate test termination on failure.
    • Enhanced the testing mock to fully support fatal failure behaviour and panic recovery.
  • Documentation

    • Expanded documentation to clarify error-handling and type conversion utilities.
    • Added detailed guides and examples for fatal assertions and testing fatal scenarios.
    • Improved formatting and consistency in documentation.
  • Tests

    • Added extensive test coverage for new type conversion utilities and fatal assertion helpers.
    • Introduced tests for fatal behaviour, early abort patterns, and mock testing enhancements.
  • Chores

    • Updated spell checker dictionary with new terminology.

@coderabbitai
Copy link

coderabbitai bot commented Aug 4, 2025

Walkthrough

This update introduces new generic type conversion helpers (MustT, MaybeT), expands fatal assertion utilities (AssertMust*), and enhances the MockT testing mock with full fatal/fail-now support and panic recovery via a Run() method. Documentation is updated to clarify assertion behaviours, usage examples, and testing of fatal assertion scenarios. Comprehensive tests for these features are added.

Changes

Cohort / File(s) Change Summary
Generic Type Conversion Utilities
panic.go, panic_test.go
Introduced MustT[T] and MaybeT[T] generic functions for type assertion with panic or zero-value fallback. Added thorough tests for successful conversions, panics, and fallback behaviour, including interface conversions.
Fatal Assertion Helpers & MockT Enhancements
testing.go, testing_test.go
Added Fatal, Fatalf, FailNow, and Run to the T interface and MockT. Implemented a suite of AssertMust* fatal assertion helpers that abort test execution on failure. Added extensive tests for fatal assertion behaviour, fail-now execution, and assertion helpers.
Documentation: Error Handling & Assertions
README.md
Expanded documentation on error-handling, clarified Maybe/MaybeOK behaviour, introduced and documented MustT/MaybeT. Added detailed explanation and examples for fatal assertion helpers and updated MockT description to reflect fatal/fail-now support. Minor formatting and wording improvements.
Documentation: Testing Patterns & Fatal Scenarios
TESTING.md, TESTING_core.md
Added sections explaining the difference between non-fatal and fatal assertions, usage of AssertMust* helpers, and how to test fatal/fail-now scenarios using MockT.Run(). Provided code examples and improved formatting for consistency.
Spell Checker Update
internal/build/cspell.json
Added "Fatalf" to the spell checker dictionary to recognise the term in codebase.

Sequence Diagram(s)

sequenceDiagram
    participant Test as Test Function
    participant MockT as MockT
    participant Assert as AssertMustFoo

    Test->>MockT: Run(testFn)
    MockT->>Test: Call testFn(MockT)
    Test->>Assert: AssertMustEqual(MockT, expected, actual)
    Assert->>MockT: (on failure) FailNow()
    MockT-->>Assert: Panic (errMockTFailNow)
    Assert-->>Test: Panic propagates
    MockT->>MockT: Recover panic, return failure
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~40 minutes

Possibly related PRs

Suggested labels

enhancement, tests

Suggested reviewers

  • karasz

Poem

In the warren of code, new helpers appear,
MustT and MaybeT—type safety is here!
Fatal assertions now hop with great might,
MockT recovers from panics in flight.
With thorough new tests and docs shining bright,
The rabbits rejoice—our code feels just right!
🐇✨

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch pr-amery-testing

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@deepsource-io
Copy link

deepsource-io bot commented Aug 4, 2025

Here's the code health analysis summary for commits b3ec005..566fa13. View details on DeepSource ↗.

Analysis Summary

AnalyzerStatusSummaryLink
DeepSource Shell LogoShell✅ SuccessView Check ↗
DeepSource Go LogoGo✅ SuccessView Check ↗

💡 If you’re a repository administrator, you can configure the quality gates from the settings.

@codecov
Copy link

codecov bot commented Aug 4, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@qodo-code-review
Copy link

PR Reviewer Guide 🔍

Here are some key observations to aid the review process:

⏱️ Estimated effort to review: 4 🔵🔵🔵🔵⚪
🧪 PR contains tests
🔒 No security concerns identified
⚡ Recommended focus areas for review

Type Safety

The MustT and MaybeT functions use type assertions without additional validation. Consider edge cases where type T might be an interface that the value partially implements, or where nil values might cause unexpected behavior with certain target types.

func MustT[T any](value any) T {
	result, ok := value.(T)
	if !ok {
		panic(NewPanicErrorf(1, "core.MustT: failed to convert %T to %T", value, result))
	}
	return result
}

// MaybeT returns the converted value if type conversion succeeds, otherwise
// returns the zero value of the target type. This is useful when you want to
// proceed with a default value regardless of whether the type conversion
// succeeded. Unlike MustT, it never panics.
//
// Example usage:
//
//	// Use zero value if conversion fails
//	str := MaybeT[string](value)  // empty string if value is not a string
//	num := MaybeT[int](value)     // zero if value is not an int
//	reader := MaybeT[io.Reader](value)  // nil if value doesn't implement io.Reader
func MaybeT[T any](value any) T {
	// revive:disable-next-line:unchecked-type-assertion
	result, _ := value.(T)
	return result
}
Performance Impact

The MockT methods now format messages before acquiring mutex locks, which could impact performance in high-concurrency scenarios. The pre-formatting approach trades memory allocation outside locks for potential increased allocation overhead.

	msg := fmt.Sprint(args...)
	m.mu.Lock()
	defer m.mu.Unlock()
	m.Errors = append(m.Errors, msg)
	m.failed = true
}

// Errorf implements the T interface and collects formatted error messages.
// It also marks the test as failed.
func (m *MockT) Errorf(format string, args ...any) {
	msg := fmt.Sprintf(format, args...)
	m.mu.Lock()
	defer m.mu.Unlock()
	m.Errors = append(m.Errors, msg)
	m.failed = true
}

// Log implements the T interface and collects log messages.
func (m *MockT) Log(args ...any) {
	msg := fmt.Sprint(args...)
	m.mu.Lock()
	defer m.mu.Unlock()
	m.Logs = append(m.Logs, msg)
}

// Logf implements the T interface and collects formatted log messages.
func (m *MockT) Logf(format string, args ...any) {
	msg := fmt.Sprintf(format, args...)
	m.mu.Lock()
	defer m.mu.Unlock()
	m.Logs = append(m.Logs, msg)
}

// Fatal implements the T interface and collects error messages, then panics.
// It combines Error and FailNow functionality.
func (m *MockT) Fatal(args ...any) {
	msg := fmt.Sprint(args...)
	m.mu.Lock()
	defer m.mu.Unlock()
	m.Errors = append(m.Errors, msg)
	m.failed = true
	panic(errMockTFailNow)
}

// Fatalf implements the T interface and collects formatted error messages, then panics.
// It combines Errorf and FailNow functionality.
func (m *MockT) Fatalf(format string, args ...any) {
	msg := fmt.Sprintf(format, args...)
	m.mu.Lock()
	defer m.mu.Unlock()
	m.Errors = append(m.Errors, msg)
	m.failed = true
	panic(errMockTFailNow)
}
Error Handling

The Run method only catches errMockTFailNow panics but re-throws all others. This design assumes that any non-FailNow panic should terminate the test runner, which may not always be the desired behavior for testing scenarios.

defer func() {
	if r := recover(); r != nil && r != errMockTFailNow {
		// Re-panic if it's not our FailNow error
		panic(r)
	}
}()

@qodo-code-review
Copy link

qodo-code-review bot commented Aug 4, 2025

PR Code Suggestions ✨

No code suggestions found for the PR.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
TESTING.md (1)

968-968: Fix grammar issue.

Consider using "to" with "prefer" for better grammar.

-* Prefer table-driven tests over individual test functions.
+* Prefer to use table-driven tests over individual test functions.
testing.go (1)

615-816: Comprehensive set of fatal assertion helpers!

The AssertMust* functions provide a clean, consistent API for fail-fast testing scenarios. Each function:

  • Properly delegates to its non-fatal counterpart
  • Calls FailNow only on assertion failure
  • Includes clear documentation with examples
  • Maintains consistent naming and behavior

Consider reducing code duplication in the future by generating these functions or using a common helper pattern, as they all follow the same structure:

func AssertMustFoo(...) {
    t.Helper()
    if !AssertFoo(...) {
        t.FailNow()
    }
}

This could be addressed in a future PR to keep this one focused.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 638ca64 and dcfb6fe.

📒 Files selected for processing (8)
  • README.md (4 hunks)
  • TESTING.md (7 hunks)
  • TESTING_core.md (2 hunks)
  • internal/build/cspell.json (1 hunks)
  • panic.go (1 hunks)
  • panic_test.go (2 hunks)
  • testing.go (6 hunks)
  • testing_test.go (1 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
**/*.md

📄 CodeRabbit Inference Engine (AGENT.md)

**/*.md: Enforce Markdown formatting rules, including 80-character line limits and strict formatting, using markdownlint with configuration in internal/build/markdownlint.json.
Check Markdown files for grammar and style issues using LanguageTool with configuration in internal/build/languagetool.cfg.
When editing Markdown files, ensure compliance with LanguageTool, CSpell, and Markdownlint.
End all bullet points in Markdown files with periods for consistency.
Capitalize proper nouns correctly (JavaScript, TypeScript, Markdown) in documentation.
Use consistent punctuation in examples and lists in documentation.
Provide context and 'why' explanations in documentation, not just 'what' descriptions.
Add examples for complex concepts or common pitfalls in documentation.
Update documentation when adding new tools or changing workflows.
Keep the pre-commit checklist current with project practices.
Review documentation changes for missing articles, punctuation, and compound modifiers.

Files:

  • TESTING_core.md
  • TESTING.md
  • README.md
**/*.{md,go}

📄 CodeRabbit Inference Engine (AGENT.md)

Check spelling in both Markdown and Go source files using CSpell with configuration in internal/build/cspell.json.

Files:

  • TESTING_core.md
  • panic.go
  • TESTING.md
  • panic_test.go
  • testing.go
  • testing_test.go
  • README.md
**/*.go

📄 CodeRabbit Inference Engine (AGENT.md)

**/*.go: Use Go 1.23+ generics for type-safe utilities.
Enforce strict linting rules via revive as configured in internal/build/revive.toml: max function length 40 lines, max function results 3, max arguments 5, cognitive complexity 7, cyclomatic complexity 10.
Enforce struct field alignment optimization for memory efficiency using the fieldalignment tool.
Use golangci-lint with configuration in .golangci.yml for comprehensive Go code linting.

Files:

  • panic.go
  • panic_test.go
  • testing.go
  • testing_test.go
**/*_test.go

📄 CodeRabbit Inference Engine (AGENT.md)

**/*_test.go: Prefer table-driven tests for Go code.
Use helper functions like ST, AssertEqualT, AssertSliceEqualT, AssertError(), AssertBool(), AssertPanic(), AssertNoPanic(), RunConcurrentTest(), RunBenchmark(), and RunTestCases() in testutils_test.go to reduce boilerplate and improve test consistency.
Provide comprehensive coverage for generic functions.

Files:

  • panic_test.go
  • testing_test.go
README.md

📄 CodeRabbit Inference Engine (AGENT.md)

Update README.md to reflect significant changes in functionality or API.

Files:

  • README.md
🧠 Learnings (18)
📓 Common learnings
Learnt from: CR
PR: darvaza-proxy/core#0
File: AGENT.md:0-0
Timestamp: 2025-08-04T16:07:42.106Z
Learning: Applies to **/*_test.go : Use helper functions like S[T](), AssertEqual[T](), AssertSliceEqual[T](), AssertError(), AssertBool(), AssertPanic(), AssertNoPanic(), RunConcurrentTest(), RunBenchmark(), and RunTestCases() in testutils_test.go to reduce boilerplate and improve test consistency.
Learnt from: CR
PR: darvaza-proxy/core#0
File: AGENT.md:0-0
Timestamp: 2025-08-04T16:07:42.106Z
Learning: Applies to **/*_test.go : Provide comprehensive coverage for generic functions.
Learnt from: CR
PR: darvaza-proxy/core#0
File: AGENT.md:0-0
Timestamp: 2025-08-04T16:07:42.106Z
Learning: Applies to **/*.go : Use Go 1.23+ generics for type-safe utilities.
Learnt from: CR
PR: darvaza-proxy/core#0
File: AGENT.md:0-0
Timestamp: 2025-08-04T16:07:42.106Z
Learning: Applies to **/*_test.go : Prefer table-driven tests for Go code.
📚 Learning: add technical terms to internal/build/cspell.json for spelling and grammar tools....
Learnt from: CR
PR: darvaza-proxy/core#0
File: AGENT.md:0-0
Timestamp: 2025-08-04T16:07:42.107Z
Learning: Add technical terms to internal/build/cspell.json for spelling and grammar tools.

Applied to files:

  • internal/build/cspell.json
📚 Learning: applies to **/*.{md,go} : check spelling in both markdown and go source files using cspell with conf...
Learnt from: CR
PR: darvaza-proxy/core#0
File: AGENT.md:0-0
Timestamp: 2025-08-04T16:07:42.106Z
Learning: Applies to **/*.{md,go} : Check spelling in both Markdown and Go source files using CSpell with configuration in internal/build/cspell.json.

Applied to files:

  • internal/build/cspell.json
📚 Learning: use only the go standard library and minimal golang.org/x packages; zero external dependencies....
Learnt from: CR
PR: darvaza-proxy/core#0
File: AGENT.md:0-0
Timestamp: 2025-08-04T16:07:42.107Z
Learning: Use only the Go standard library and minimal golang.org/x packages; zero external dependencies.

Applied to files:

  • internal/build/cspell.json
  • TESTING.md
📚 Learning: applies to **/*_test.go : provide comprehensive coverage for generic functions....
Learnt from: CR
PR: darvaza-proxy/core#0
File: AGENT.md:0-0
Timestamp: 2025-08-04T16:07:42.106Z
Learning: Applies to **/*_test.go : Provide comprehensive coverage for generic functions.

Applied to files:

  • internal/build/cspell.json
  • TESTING_core.md
  • panic.go
  • TESTING.md
  • panic_test.go
  • testing.go
  • testing_test.go
  • README.md
📚 Learning: applies to **/*.go : enforce struct field alignment optimization for memory efficiency using the fie...
Learnt from: CR
PR: darvaza-proxy/core#0
File: AGENT.md:0-0
Timestamp: 2025-08-04T16:07:42.106Z
Learning: Applies to **/*.go : Enforce struct field alignment optimization for memory efficiency using the fieldalignment tool.

Applied to files:

  • internal/build/cspell.json
📚 Learning: applies to **/*_test.go : use helper functions like s[t](), assertequal[t](), assertsliceequal[t](),...
Learnt from: CR
PR: darvaza-proxy/core#0
File: AGENT.md:0-0
Timestamp: 2025-08-04T16:07:42.106Z
Learning: Applies to **/*_test.go : Use helper functions like S[T](), AssertEqual[T](), AssertSliceEqual[T](), AssertError(), AssertBool(), AssertPanic(), AssertNoPanic(), RunConcurrentTest(), RunBenchmark(), and RunTestCases() in testutils_test.go to reduce boilerplate and improve test consistency.

Applied to files:

  • internal/build/cspell.json
  • TESTING_core.md
  • panic.go
  • TESTING.md
  • panic_test.go
  • testing.go
  • testing_test.go
  • README.md
📚 Learning: applies to **/*.go : max function results: 3....
Learnt from: CR
PR: darvaza-proxy/core#0
File: AGENT.md:0-0
Timestamp: 2025-07-18T16:39:19.390Z
Learning: Applies to **/*.go : Max function results: 3.

Applied to files:

  • internal/build/cspell.json
  • TESTING.md
📚 Learning: applies to **/*.go : use go 1.23+ generics for type-safe utilities....
Learnt from: CR
PR: darvaza-proxy/core#0
File: AGENT.md:0-0
Timestamp: 2025-08-04T16:07:42.106Z
Learning: Applies to **/*.go : Use Go 1.23+ generics for type-safe utilities.

Applied to files:

  • internal/build/cspell.json
  • panic.go
  • panic_test.go
  • README.md
📚 Learning: applies to readme.md : update readme.md to reflect significant changes in functionality or api....
Learnt from: CR
PR: darvaza-proxy/core#0
File: AGENT.md:0-0
Timestamp: 2025-08-04T16:07:42.107Z
Learning: Applies to README.md : Update README.md to reflect significant changes in functionality or API.

Applied to files:

  • TESTING_core.md
  • TESTING.md
  • README.md
📚 Learning: applies to **/*_test.go : prefer table-driven tests for go code....
Learnt from: CR
PR: darvaza-proxy/core#0
File: AGENT.md:0-0
Timestamp: 2025-08-04T16:07:42.106Z
Learning: Applies to **/*_test.go : Prefer table-driven tests for Go code.

Applied to files:

  • TESTING_core.md
  • TESTING.md
  • panic_test.go
  • testing.go
  • testing_test.go
  • README.md
📚 Learning: applies to **/*.md : review documentation changes for missing articles, punctuation, and compound mo...
Learnt from: CR
PR: darvaza-proxy/core#0
File: AGENT.md:0-0
Timestamp: 2025-08-04T16:07:42.107Z
Learning: Applies to **/*.md : Review documentation changes for missing articles, punctuation, and compound modifiers.

Applied to files:

  • TESTING.md
📚 Learning: always run make tidy first before committing: go code formatting and whitespace clean-up, markdown f...
Learnt from: CR
PR: darvaza-proxy/core#0
File: AGENT.md:0-0
Timestamp: 2025-08-04T16:07:42.107Z
Learning: ALWAYS run make tidy first before committing: Go code formatting and whitespace clean-up, Markdown files checked with CSpell and markdownlint, Shell scripts checked with shellcheck.

Applied to files:

  • TESTING.md
📚 Learning: always run make tidy which includes golangci-lint checks....
Learnt from: CR
PR: darvaza-proxy/core#0
File: AGENT.md:0-0
Timestamp: 2025-08-04T16:07:42.107Z
Learning: Always run make tidy which includes golangci-lint checks.

Applied to files:

  • TESTING.md
📚 Learning: verify all tests pass with make test before committing....
Learnt from: CR
PR: darvaza-proxy/core#0
File: AGENT.md:0-0
Timestamp: 2025-08-04T16:07:42.107Z
Learning: Verify all tests pass with make test before committing.

Applied to files:

  • TESTING.md
📚 Learning: always run `make tidy` first before committing: fix all issues (go formatting, whitespace, cspell, m...
Learnt from: CR
PR: darvaza-proxy/core#0
File: AGENT.md:0-0
Timestamp: 2025-07-18T16:39:19.390Z
Learning: ALWAYS run `make tidy` first before committing: fix all issues (Go formatting, whitespace, CSpell, markdownlint, shellcheck).

Applied to files:

  • TESTING.md
📚 Learning: applies to agent.md : update `agent.md` to reflect any changes in development workflow or standards....
Learnt from: CR
PR: darvaza-proxy/core#0
File: AGENT.md:0-0
Timestamp: 2025-07-18T16:39:19.390Z
Learning: Applies to AGENT.md : Update `AGENT.md` to reflect any changes in development workflow or standards.

Applied to files:

  • README.md
📚 Learning: applies to agent.md : update agent.md to reflect any changes in development workflow or standards....
Learnt from: CR
PR: darvaza-proxy/core#0
File: AGENT.md:0-0
Timestamp: 2025-08-04T16:07:42.107Z
Learning: Applies to AGENT.md : Update AGENT.md to reflect any changes in development workflow or standards.

Applied to files:

  • README.md
🪛 LanguageTool
TESTING.md

[grammar] ~968-~968: Consider using “to” with “prefer”.
Context: ...t.Helper() in all helper functions. * Prefer table-driven tests over individual test functions. * Keep setup and clean-...

(PREFER_OVER_TO)

README.md

[locale-violation] ~304-~304: Lower-case ‘ok’ is American English. For British English use “OK”.
Context: ... value or panics with PanicError if ok is false. Useful for operations that sh...

(OK)


[locale-violation] ~306-~306: Lower-case ‘ok’ is American English. For British English use “OK”.
Context: ... always returns the value, ignoring the ok flag. When ok is false, the returned ...

(OK)


[locale-violation] ~307-~307: Lower-case ‘ok’ is American English. For British English use “OK”.
Context: ...the value, ignoring the ok flag. When ok is false, the returned value is typical...

(OK)


[uncategorized] ~312-~312: Possible missing article found.
Context: ...MaybeOK(As[any, T](value)). Returns converted value on success, or the zero value of ...

(AI_HYDRA_LEO_MISSING_THE)


[locale-violation] ~314-~314: Lower-case ‘ok’ is American English. For British English use “OK”.
Context: ...he As[any, T] function, which returns (value, ok) for type conversion, allowing custom ...

(OK)

🔇 Additional comments (18)
internal/build/cspell.json (1)

27-27: LGTM!

The addition of "Fatalf" to the spell checker dictionary is necessary and correctly positioned alphabetically to support the new fatal assertion methods introduced in this PR.

panic.go (2)

158-176: LGTM!

MustT is well-implemented with proper generics usage, comprehensive documentation, and follows the established Must* pattern. The panic message includes both source and target types, which aids debugging.


178-193: LGTM!

MaybeT correctly implements graceful type conversion with zero value fallback. The revive disable comment for unchecked-type-assertion is appropriate here since the function intentionally ignores conversion failures.

TESTING_core.md (2)

131-134: LGTM!

Clear and concise documentation of the new Fatal/FailNow support in MockT, properly integrated with the existing feature list.


159-200: Excellent documentation for Fatal/FailNow testing patterns.

This new section provides comprehensive guidance on testing fatal assertion scenarios with clear examples and practical usage patterns. The example demonstrates both AssertMust* usage and manual FailNow patterns effectively.

TESTING.md (2)

115-135: Excellent documentation for fatal assertions.

Clear distinction between standard and fatal assertions with practical examples. The explanation of AssertMust* functions calling t.FailNow() on failure is well-documented.


858-878: LGTM!

Good practical example demonstrating how to test functions that call Fatal/FailNow methods using MockT.Run() with proper verification patterns.

panic_test.go (5)

21-23: LGTM!

Proper TestCase interface validation declarations following the mandatory compliance requirements.


811-867: Excellent test coverage for MustT success scenarios.

Comprehensive test implementation covering multiple types with proper factory functions, TestCase interface usage, and type-safe generic testing patterns.


869-923: LGTM!

Well-implemented panic tests using AssertPanic to verify MustT correctly panics on invalid type conversions across various scenarios.


925-1036: Comprehensive MaybeT test coverage.

Excellent testing of both successful conversions and graceful fallback to zero values, with proper nil handling for interface types and good separation of test logic by target type.


1038-1045: LGTM!

Simple and appropriate mockStringer helper type for testing fmt.Stringer interface conversions.

testing_test.go (1)

634-1183: Excellent test coverage for the new testing infrastructure!

The tests comprehensively cover all new functionality including:

  • MockT's Fatal, Fatalf, and FailNow methods with proper panic recovery
  • The Run method's behavior with various edge cases
  • Early abort patterns demonstrating the use case for AssertMust* functions
  • All 14 AssertMust* variants with both success and failure scenarios

The tests follow best practices with clear test names, proper use of helper functions, and thorough verification of all behaviors.

README.md (1)

301-349: Documentation updates are clear and comprehensive!

The README effectively documents:

  • The new generic type conversion utilities (MustT/MaybeT) with clear explanations of their relationship to the As function
  • Fatal assertion helpers with proper context about their behavior and use cases
  • MockT's enhanced capabilities for Fatal/FailNow support

The examples are practical and help users understand the usage patterns.

Also applies to: 472-473, 510-560

testing.go (4)

12-12: Good use of sentinel error pattern!

Using a sentinel error for MockT.FailNow panic recovery is a clean approach that allows distinguishing between FailNow panics and other panics.


63-94: Smart refactoring to reduce lock contention!

Pre-computing formatted messages before acquiring the lock is a good optimization that reduces the time the mutex is held. This improves concurrent performance when multiple goroutines are logging.


96-129: Well-implemented Fatal methods with proper panic behavior!

The Fatal and Fatalf methods correctly combine error recording with immediate termination via panic. The FailNow method properly marks the test as failed before panicking, maintaining consistency with the testing.T interface behavior.


182-211: Excellent implementation of the Run method!

The Run method provides a clean way to test functions that call Fatal/FailNow:

  • Proper nil checks for defensive programming
  • Correct panic recovery that only catches errMockTFailNow
  • Re-panics other panics to maintain expected behavior
  • Clear documentation with usage example

This enables comprehensive testing of assertion functions without terminating the test runner.

@amery amery self-assigned this Aug 4, 2025
@amery amery requested a review from karasz August 4, 2025 17:48
@amery amery force-pushed the pr-amery-testing branch from dcfb6fe to 20f0ec2 Compare August 5, 2025 02:03
@amery
Copy link
Contributor Author

amery commented Aug 5, 2025

rebased

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (4)
TESTING.md (1)

968-968: Address grammar issue identified by static analysis.

The phrase should use "to" rather than "over" with "prefer" for correct grammar.

-* Prefer table-driven tests over individual test functions.
+* Prefer table-driven tests to individual test functions.
README.md (3)

472-474: Line-length exceeds markdown-lint 80-character limit.

The two wrapped lines describing MockT reach ~120 chars. Re-wrap at ≤ 80 chars to satisfy internal/build/markdownlint.json.

- `LastError()`, `LastLog()`), reset capabilities, and full Fatal/FailNow
- support with panic recovery via the `Run()` method.
+ `LastError()`, `LastLog()`), reset capabilities, and full Fatal/FailNow
+ support (with panic recovery) via the `Run()` method.

525-543: Ensure each bullet terminates with a period for markdown consistency.

A few multi-line bullets (e.g. Lines 528, 534, 542) end without a trailing
full stop once the continuation line is joined. Add a period at the end of
each bullet to follow the doc-style convention used elsewhere in the file.


314-316: Capitalise “OK” when not used as the Go boolean variable.

LanguageTool flags the lower-case “ok”. Here it is plain English, not the
code identifier, so prefer “OK”.

- `(value, ok)` for type conversion, allowing custom handling of conversion
+ `(value, OK)` for type conversion, allowing custom handling of conversion
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between dcfb6fe and 20f0ec2.

📒 Files selected for processing (8)
  • README.md (4 hunks)
  • TESTING.md (7 hunks)
  • TESTING_core.md (2 hunks)
  • internal/build/cspell.json (1 hunks)
  • panic.go (1 hunks)
  • panic_test.go (2 hunks)
  • testing.go (6 hunks)
  • testing_test.go (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • internal/build/cspell.json
🚧 Files skipped from review as they are similar to previous changes (3)
  • TESTING_core.md
  • panic.go
  • panic_test.go
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{md,go}

📄 CodeRabbit Inference Engine (AGENT.md)

Check spelling in both Markdown and Go source files using CSpell with configuration in internal/build/cspell.json.

Files:

  • testing_test.go
  • testing.go
  • README.md
  • TESTING.md
**/*.go

📄 CodeRabbit Inference Engine (AGENT.md)

**/*.go: Use Go 1.23+ generics for type-safe utilities.
Enforce strict linting rules via revive as configured in internal/build/revive.toml: max function length 40 lines, max function results 3, max arguments 5, cognitive complexity 7, cyclomatic complexity 10.
Enforce struct field alignment optimization for memory efficiency using the fieldalignment tool.
Use golangci-lint with configuration in .golangci.yml for comprehensive Go code linting.

Files:

  • testing_test.go
  • testing.go
**/*_test.go

📄 CodeRabbit Inference Engine (AGENT.md)

**/*_test.go: Prefer table-driven tests for Go code.
Use helper functions like ST, AssertEqualT, AssertSliceEqualT, AssertError(), AssertBool(), AssertPanic(), AssertNoPanic(), RunConcurrentTest(), RunBenchmark(), and RunTestCases() in testutils_test.go to reduce boilerplate and improve test consistency.
Provide comprehensive coverage for generic functions.

Files:

  • testing_test.go
**/*.md

📄 CodeRabbit Inference Engine (AGENT.md)

**/*.md: Enforce Markdown formatting rules, including 80-character line limits and strict formatting, using markdownlint with configuration in internal/build/markdownlint.json.
Check Markdown files for grammar and style issues using LanguageTool with configuration in internal/build/languagetool.cfg.
When editing Markdown files, ensure compliance with LanguageTool, CSpell, and Markdownlint.
End all bullet points in Markdown files with periods for consistency.
Capitalize proper nouns correctly (JavaScript, TypeScript, Markdown) in documentation.
Use consistent punctuation in examples and lists in documentation.
Provide context and 'why' explanations in documentation, not just 'what' descriptions.
Add examples for complex concepts or common pitfalls in documentation.
Update documentation when adding new tools or changing workflows.
Keep the pre-commit checklist current with project practices.
Review documentation changes for missing articles, punctuation, and compound modifiers.

Files:

  • README.md
  • TESTING.md
README.md

📄 CodeRabbit Inference Engine (AGENT.md)

Update README.md to reflect significant changes in functionality or API.

Files:

  • README.md
🧠 Learnings (15)
📓 Common learnings
Learnt from: CR
PR: darvaza-proxy/core#0
File: AGENT.md:0-0
Timestamp: 2025-08-04T16:07:42.136Z
Learning: Applies to **/*_test.go : Use helper functions like S[T](), AssertEqual[T](), AssertSliceEqual[T](), AssertError(), AssertBool(), AssertPanic(), AssertNoPanic(), RunConcurrentTest(), RunBenchmark(), and RunTestCases() in testutils_test.go to reduce boilerplate and improve test consistency.
Learnt from: CR
PR: darvaza-proxy/core#0
File: AGENT.md:0-0
Timestamp: 2025-08-04T16:07:42.136Z
Learning: Applies to **/*_test.go : Provide comprehensive coverage for generic functions.
Learnt from: CR
PR: darvaza-proxy/core#0
File: AGENT.md:0-0
Timestamp: 2025-08-04T16:07:42.136Z
Learning: Applies to **/*.go : Use Go 1.23+ generics for type-safe utilities.
Learnt from: CR
PR: darvaza-proxy/core#0
File: AGENT.md:0-0
Timestamp: 2025-08-04T16:07:42.136Z
Learning: Applies to **/*_test.go : Prefer table-driven tests for Go code.
📚 Learning: applies to **/*_test.go : use helper functions like s[t](), assertequal[t](), assertsliceequal[t](),...
Learnt from: CR
PR: darvaza-proxy/core#0
File: AGENT.md:0-0
Timestamp: 2025-08-04T16:07:42.136Z
Learning: Applies to **/*_test.go : Use helper functions like S[T](), AssertEqual[T](), AssertSliceEqual[T](), AssertError(), AssertBool(), AssertPanic(), AssertNoPanic(), RunConcurrentTest(), RunBenchmark(), and RunTestCases() in testutils_test.go to reduce boilerplate and improve test consistency.

Applied to files:

  • testing_test.go
  • testing.go
  • README.md
  • TESTING.md
📚 Learning: applies to **/*_test.go : provide comprehensive coverage for generic functions....
Learnt from: CR
PR: darvaza-proxy/core#0
File: AGENT.md:0-0
Timestamp: 2025-08-04T16:07:42.136Z
Learning: Applies to **/*_test.go : Provide comprehensive coverage for generic functions.

Applied to files:

  • testing_test.go
  • testing.go
  • README.md
  • TESTING.md
📚 Learning: applies to **/*_test.go : prefer table-driven tests for go code....
Learnt from: CR
PR: darvaza-proxy/core#0
File: AGENT.md:0-0
Timestamp: 2025-08-04T16:07:42.136Z
Learning: Applies to **/*_test.go : Prefer table-driven tests for Go code.

Applied to files:

  • testing_test.go
  • testing.go
  • README.md
  • TESTING.md
📚 Learning: applies to readme.md : update readme.md to reflect significant changes in functionality or api....
Learnt from: CR
PR: darvaza-proxy/core#0
File: AGENT.md:0-0
Timestamp: 2025-08-04T16:07:42.136Z
Learning: Applies to README.md : Update README.md to reflect significant changes in functionality or API.

Applied to files:

  • README.md
  • TESTING.md
📚 Learning: applies to **/*.go : use go 1.23+ generics for type-safe utilities....
Learnt from: CR
PR: darvaza-proxy/core#0
File: AGENT.md:0-0
Timestamp: 2025-08-04T16:07:42.136Z
Learning: Applies to **/*.go : Use Go 1.23+ generics for type-safe utilities.

Applied to files:

  • README.md
📚 Learning: applies to agent.md : update `agent.md` to reflect any changes in development workflow or standards....
Learnt from: CR
PR: darvaza-proxy/core#0
File: AGENT.md:0-0
Timestamp: 2025-07-18T16:39:19.390Z
Learning: Applies to AGENT.md : Update `AGENT.md` to reflect any changes in development workflow or standards.

Applied to files:

  • README.md
📚 Learning: applies to agent.md : update agent.md to reflect any changes in development workflow or standards....
Learnt from: CR
PR: darvaza-proxy/core#0
File: AGENT.md:0-0
Timestamp: 2025-08-04T16:07:42.136Z
Learning: Applies to AGENT.md : Update AGENT.md to reflect any changes in development workflow or standards.

Applied to files:

  • README.md
  • TESTING.md
📚 Learning: applies to **/*.md : review documentation changes for missing articles, punctuation, and compound mo...
Learnt from: CR
PR: darvaza-proxy/core#0
File: AGENT.md:0-0
Timestamp: 2025-08-04T16:07:42.136Z
Learning: Applies to **/*.md : Review documentation changes for missing articles, punctuation, and compound modifiers.

Applied to files:

  • TESTING.md
📚 Learning: use only the go standard library and minimal golang.org/x packages; zero external dependencies....
Learnt from: CR
PR: darvaza-proxy/core#0
File: AGENT.md:0-0
Timestamp: 2025-08-04T16:07:42.136Z
Learning: Use only the Go standard library and minimal golang.org/x packages; zero external dependencies.

Applied to files:

  • TESTING.md
📚 Learning: always run make tidy first before committing: go code formatting and whitespace clean-up, markdown f...
Learnt from: CR
PR: darvaza-proxy/core#0
File: AGENT.md:0-0
Timestamp: 2025-08-04T16:07:42.136Z
Learning: ALWAYS run make tidy first before committing: Go code formatting and whitespace clean-up, Markdown files checked with CSpell and markdownlint, Shell scripts checked with shellcheck.

Applied to files:

  • TESTING.md
📚 Learning: always run make tidy which includes golangci-lint checks....
Learnt from: CR
PR: darvaza-proxy/core#0
File: AGENT.md:0-0
Timestamp: 2025-08-04T16:07:42.136Z
Learning: Always run make tidy which includes golangci-lint checks.

Applied to files:

  • TESTING.md
📚 Learning: applies to **/*.go : max function results: 3....
Learnt from: CR
PR: darvaza-proxy/core#0
File: AGENT.md:0-0
Timestamp: 2025-07-18T16:39:19.390Z
Learning: Applies to **/*.go : Max function results: 3.

Applied to files:

  • TESTING.md
📚 Learning: verify all tests pass with make test before committing....
Learnt from: CR
PR: darvaza-proxy/core#0
File: AGENT.md:0-0
Timestamp: 2025-08-04T16:07:42.136Z
Learning: Verify all tests pass with make test before committing.

Applied to files:

  • TESTING.md
📚 Learning: always run `make tidy` first before committing: fix all issues (go formatting, whitespace, cspell, m...
Learnt from: CR
PR: darvaza-proxy/core#0
File: AGENT.md:0-0
Timestamp: 2025-07-18T16:39:19.390Z
Learning: ALWAYS run `make tidy` first before committing: fix all issues (Go formatting, whitespace, CSpell, markdownlint, shellcheck).

Applied to files:

  • TESTING.md
🪛 LanguageTool
README.md

[locale-violation] ~304-~304: Lower-case ‘ok’ is American English. For British English use “OK”.
Context: ... value or panics with PanicError if ok is false. Useful for operations that sh...

(OK)


[locale-violation] ~306-~306: Lower-case ‘ok’ is American English. For British English use “OK”.
Context: ... always returns the value, ignoring the ok flag. When ok is false, the returned ...

(OK)


[locale-violation] ~307-~307: Lower-case ‘ok’ is American English. For British English use “OK”.
Context: ...the value, ignoring the ok flag. When ok is false, the returned value is typical...

(OK)


[uncategorized] ~312-~312: Possible missing article found.
Context: ...MaybeOK(As[any, T](value)). Returns converted value on success, or the zero value of ...

(AI_HYDRA_LEO_MISSING_THE)


[locale-violation] ~314-~314: Lower-case ‘ok’ is American English. For British English use “OK”.
Context: ...he As[any, T] function, which returns (value, ok) for type conversion, allowing custom ...

(OK)

TESTING.md

[grammar] ~968-~968: Consider using “to” with “prefer”.
Context: ...t.Helper() in all helper functions. * Prefer table-driven tests over individual test functions. * Keep setup and clean-...

(PREFER_OVER_TO)

🔇 Additional comments (15)
testing.go (8)

12-33: LGTM! Excellent use of sentinel error pattern.

The addition of errMockTFailNow as a sentinel error for panic recovery is a clean implementation of the fail-fast pattern. The interface extensions maintain backwards compatibility whilst adding the necessary fatal methods.


37-51: Excellent documentation for the enhanced MockT capabilities.

The comprehensive documentation clearly explains the Fatal/FailNow panic mechanism and provides practical examples of using the Run() method for testing assertion functions. This will be invaluable for users implementing fail-fast test patterns.


63-94: Good performance optimisation for thread safety.

Pre-computing the formatted messages before acquiring mutex locks reduces lock contention time. This optimisation is applied consistently across all message methods without changing behaviour.


96-116: Solid implementation of fatal assertion methods.

The Fatal and Fatalf methods correctly combine error recording with fail-fast behavior. The thread-safe implementation follows the established pattern of existing methods whilst adding the sentinel panic for recovery.


125-129: Correct implementation of FailNow semantics.

The method properly calls Fail() before panicking with the sentinel error, matching the behavior of testing.T.FailNow() whilst enabling recovery via the Run() method.


182-211: Excellent implementation of panic recovery for fatal assertions.

The Run() method is well-designed with comprehensive nil checks, proper panic recovery that distinguishes FailNow panics from other panics, and clear documentation explaining its purpose. This enables robust testing of fatal assertion functions.


615-689: Consistent implementation of fail-fast assertion pattern.

The AssertMust* functions correctly implement the fail-fast pattern by calling the underlying assertion functions and only invoking FailNow() on failure. The consistent documentation, proper Helper() usage, and maintained generic constraints ensure these will integrate seamlessly with existing test code.


690-816: Comprehensive completion of the fail-fast assertion framework.

The remaining AssertMust* functions maintain the consistent fail-fast pattern. The special handling in AssertMustTypeIs to return the cast value on success is correctly implemented. This provides a complete toolkit for fail-fast assertions covering all testing scenarios.

TESTING.md (2)

115-135: Excellent documentation explaining fail-fast assertion behaviour.

The clear distinction between AssertFoo() (continue on failure) and AssertMustFoo() (terminate on failure) is well-explained with practical examples. The key difference summary effectively reinforces the concept for users.


858-878: Valuable addition explaining how to test fatal assertion scenarios.

The new section provides essential guidance for testing functions that call Fatal/FailNow methods. The practical example clearly demonstrates how to use MockT.Run() to recover from panics and verify expected failure behaviour.

testing_test.go (4)

635-713: Comprehensive testing of fatal assertion functionality.

The test suite thoroughly covers all aspects of the new Fatal/Fatalf/FailNow methods and the MockT.Run() recovery mechanism. Edge cases including nil checks and panic propagation are properly tested, providing confidence in the implementation's robustness.


715-831: Excellent validation of early abort patterns.

The test suite effectively validates the common if !Assert() { FailNow() } pattern, covering both successful continuation and proper abort scenarios. The mixed pattern testing demonstrates real-world usage and ensures the fail-fast behaviour works correctly in complex test scenarios.


833-849: Well-organised comprehensive test coverage for AssertMust functions.

The systematic testing of all 14 AssertMust* functions with consistent naming and organisation ensures complete coverage of the fail-fast assertion helpers.


851-1182: Thorough and consistent testing of all AssertMust functions.

Each AssertMust* function is comprehensively tested with both success (execution continues) and failure (execution aborts) scenarios. The consistent pattern across all tests and verification that post-failure code is unreachable confirms the correct implementation of fail-fast semantics.

README.md (1)

510-516: Minor wording & punctuation clean-up in the “Fatal Assertions” intro.

  1. Line-length is > 80 chars.
  2. Missing full stop after Line 515.
  3. “similar to t.Error() vs t.Fatal()” reads more fluently.

[ suggest_nitpick ]

- methods terminate execution, similar to `t.Error()` vs `t.Fatal()`.
+ methods terminate execution — similar to `t.Error()` vs `t.Fatal()`.

amery added 3 commits August 6, 2025 00:41
…t tests

Add Fatal, Fatalf, and FailNow methods to T interface for complete
testing.T compatibility. Implement thread-safe versions in MockT with
proper panic behaviour using special errMockTFailNow error.

Add Run() method to MockT for panic recovery, enabling testing of
assertion functions that may call Fatal/FailNow methods. The Run method
executes test functions and recovers from FailNow panics whilst
propagating other panics.

Optimise MockT performance by assembling formatted messages before
acquiring mutex locks in Fatal/Fatalf methods, reducing contention in
concurrent scenarios.

Add comprehensive test coverage for early abort pattern
(if !Assert() { FailNow() }) demonstrating proper behaviour with MockT.
Tests verify successful assertions continue execution whilst failed
assertions abort immediately.

Update documentation in README.md, TESTING.md, and TESTING_core.md to
reflect new Fatal/FailNow capabilities and provide usage examples.

All tests pass with 97.0% coverage.

Signed-off-by: Alejandro Mery <amery@apptly.co>
Add MustT[T] and MaybeT[T] functions for type conversion, building on
the existing As[any, T] function:

* MustT[T](value any) T - equivalent to MustOK(As[any, T](value)). Returns
  converted value or panics with PanicError if type conversion fails.
* MaybeT[T](value any) T - equivalent to MaybeOK(As[any, T](value)). Returns
  converted value on success, or zero value of type T if conversion fails.

These utilities follow the established pattern where Must* functions panic
on failure whilst Maybe* functions return zero values, composing naturally
with the existing As/MustOK/MaybeOK building blocks.

The single generic parameter design provides a clean interface where you
only specify the target type, accepting any value as input for maximum
flexibility in type conversion scenarios.

Add comprehensive test coverage with separate test cases for successful
conversions, panic scenarios, and zero value handling. Tests demonstrate
type conversion across basic types (string, int, float64), interfaces
(error, fmt.Stringer), and failure cases.

Update documentation in README.md to show the clear relationships between
utilities and make explicit the role of zero values in Maybe* functions.
Add examples demonstrating the composability: MustT = MustOK(As[any, T]) and
MaybeT = MaybeOK(As[any, T]), with As[any, T] as the building block for custom
handling of conversion failures.

All tests pass with 97.1% coverage.

Signed-off-by: Alejandro Mery <amery@apptly.co>
…failure

Add 14 new AssertMustFoo() functions that automatically call t.FailNow()
when assertions fail, providing a cleaner alternative to the manual
`if !AssertFoo() { t.FailNow() }` pattern.

New functions follow Go testing conventions where "Fatal" methods
terminate execution, similar to t.Error() vs t.Fatal():

- AssertMustEqual[T], AssertMustNotEqual[T], AssertMustSliceEqual[T]
- AssertMustTrue, AssertMustFalse, AssertMustNil, AssertMustNotNil
- AssertMustContains, AssertMustError, AssertMustNoError, AssertMustErrorIs
- AssertMustPanic, AssertMustNoPanic, AssertMustTypeIs[T]

All functions include comprehensive tests using MockT.Run() to verify
both success (execution continues) and failure (t.FailNow() called,
execution terminates) scenarios.

Documentation added to README.md with clear explanation of Error vs
Fatal patterns and usage examples.

Signed-off-by: Alejandro Mery <amery@apptly.co>
@amery amery force-pushed the pr-amery-testing branch from 20f0ec2 to 566fa13 Compare August 6, 2025 00:42
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (3)
TESTING.md (2)

117-120: Wrap long sentence to respect 80-character limit

Line 118 runs past the markdownlint 80-character limit.
Re-flowing keeps the file compliant without changing semantics.

- and automatically call `t.FailNow()` if the assertion fails, terminating test execution immediately:
+and automatically call `t.FailNow()` if the assertion fails,
+terminating test execution immediately:

858-878: Terminate descriptive paragraph with a full stop and keep lines short

The introductory text at Lines 860-862 exceeds 80 characters and ends
without a period. Consider adding a full stop and wrapping:

-MockT supports testing functions that call Fatal/FailNow methods via the `Run()`
-method, which recovers from FailNow panics:
+MockT supports testing functions that call **Fatal**/`FailNow` methods via
+the `Run()` method, which recovers from `FailNow` panics.
README.md (1)

301-314: Use “OK” instead of “ok” in prose and clarify the article

LanguageTool flags “ok” as American English. Capitalising also avoids
confusion with the back-ticked parameter name.

-* `MustOK[T](value T, ok bool) T` - returns value or panics with `PanicError` if
-  ok is false. Useful for operations that should always succeed, such as map
+* `MustOK[T](value T, ok bool) T` - returns value or panics with `PanicError`
+  if **OK** is false. Useful for operations that should always succeed, such as
+  map
@@
-* `MaybeOK[T](value T, ok bool) T` - always returns the value, ignoring the ok
-  flag. When ok is false, the returned value is typically the zero value of
-  type T from the failed operation.
+* `MaybeOK[T](value T, ok bool) T` - always returns the value, ignoring the
+  **OK** flag. When **OK** is false, the returned value is typically the zero
+  value of type T from the failed operation.
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 20f0ec2 and 566fa13.

📒 Files selected for processing (8)
  • README.md (4 hunks)
  • TESTING.md (7 hunks)
  • TESTING_core.md (2 hunks)
  • internal/build/cspell.json (1 hunks)
  • panic.go (1 hunks)
  • panic_test.go (2 hunks)
  • testing.go (6 hunks)
  • testing_test.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
  • panic.go
  • internal/build/cspell.json
  • TESTING_core.md
  • panic_test.go
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{md,go}

📄 CodeRabbit Inference Engine (AGENT.md)

Check spelling in both Markdown and Go source files using CSpell with configuration in internal/build/cspell.json.

Files:

  • testing_test.go
  • testing.go
  • README.md
  • TESTING.md
**/*.go

📄 CodeRabbit Inference Engine (AGENT.md)

**/*.go: Use Go 1.23+ generics for type-safe utilities.
Enforce strict linting rules via revive as configured in internal/build/revive.toml: max function length 40 lines, max function results 3, max arguments 5, cognitive complexity 7, cyclomatic complexity 10.
Enforce struct field alignment optimization for memory efficiency using the fieldalignment tool.
Use golangci-lint with configuration in .golangci.yml for comprehensive Go code linting.

Files:

  • testing_test.go
  • testing.go
**/*_test.go

📄 CodeRabbit Inference Engine (AGENT.md)

**/*_test.go: Prefer table-driven tests for Go code.
Use helper functions like ST, AssertEqualT, AssertSliceEqualT, AssertError(), AssertBool(), AssertPanic(), AssertNoPanic(), RunConcurrentTest(), RunBenchmark(), and RunTestCases() in testutils_test.go to reduce boilerplate and improve test consistency.
Provide comprehensive coverage for generic functions.

Files:

  • testing_test.go
**/*.md

📄 CodeRabbit Inference Engine (AGENT.md)

**/*.md: Enforce Markdown formatting rules, including 80-character line limits and strict formatting, using markdownlint with configuration in internal/build/markdownlint.json.
Check Markdown files for grammar and style issues using LanguageTool with configuration in internal/build/languagetool.cfg.
When editing Markdown files, ensure compliance with LanguageTool, CSpell, and Markdownlint.
End all bullet points in Markdown files with periods for consistency.
Capitalize proper nouns correctly (JavaScript, TypeScript, Markdown) in documentation.
Use consistent punctuation in examples and lists in documentation.
Provide context and 'why' explanations in documentation, not just 'what' descriptions.
Add examples for complex concepts or common pitfalls in documentation.
Update documentation when adding new tools or changing workflows.
Keep the pre-commit checklist current with project practices.
Review documentation changes for missing articles, punctuation, and compound modifiers.

Files:

  • README.md
  • TESTING.md
README.md

📄 CodeRabbit Inference Engine (AGENT.md)

Update README.md to reflect significant changes in functionality or API.

Files:

  • README.md
🧠 Learnings (17)
📓 Common learnings
Learnt from: CR
PR: darvaza-proxy/core#0
File: AGENT.md:0-0
Timestamp: 2025-08-04T16:07:42.136Z
Learning: Applies to **/*_test.go : Provide comprehensive coverage for generic functions.
Learnt from: CR
PR: darvaza-proxy/core#0
File: AGENT.md:0-0
Timestamp: 2025-08-04T16:07:42.136Z
Learning: Applies to **/*_test.go : Use helper functions like S[T](), AssertEqual[T](), AssertSliceEqual[T](), AssertError(), AssertBool(), AssertPanic(), AssertNoPanic(), RunConcurrentTest(), RunBenchmark(), and RunTestCases() in testutils_test.go to reduce boilerplate and improve test consistency.
Learnt from: CR
PR: darvaza-proxy/core#0
File: AGENT.md:0-0
Timestamp: 2025-08-04T16:07:42.136Z
Learning: Applies to **/*.go : Use Go 1.23+ generics for type-safe utilities.
📚 Learning: applies to **/*_test.go : use helper functions like s[t](), assertequal[t](), assertsliceequal[t](),...
Learnt from: CR
PR: darvaza-proxy/core#0
File: AGENT.md:0-0
Timestamp: 2025-08-04T16:07:42.136Z
Learning: Applies to **/*_test.go : Use helper functions like S[T](), AssertEqual[T](), AssertSliceEqual[T](), AssertError(), AssertBool(), AssertPanic(), AssertNoPanic(), RunConcurrentTest(), RunBenchmark(), and RunTestCases() in testutils_test.go to reduce boilerplate and improve test consistency.

Applied to files:

  • testing_test.go
  • testing.go
  • README.md
  • TESTING.md
📚 Learning: applies to **/*_test.go : provide comprehensive coverage for generic functions....
Learnt from: CR
PR: darvaza-proxy/core#0
File: AGENT.md:0-0
Timestamp: 2025-08-04T16:07:42.136Z
Learning: Applies to **/*_test.go : Provide comprehensive coverage for generic functions.

Applied to files:

  • testing_test.go
  • testing.go
  • README.md
  • TESTING.md
📚 Learning: applies to **/*_test.go : prefer table-driven tests for go code....
Learnt from: CR
PR: darvaza-proxy/core#0
File: AGENT.md:0-0
Timestamp: 2025-08-04T16:07:42.136Z
Learning: Applies to **/*_test.go : Prefer table-driven tests for Go code.

Applied to files:

  • testing_test.go
  • testing.go
  • README.md
  • TESTING.md
📚 Learning: in go test functions using assertion helpers like assertsame, assertequal, etc., early returns after...
Learnt from: amery
PR: darvaza-proxy/core#135
File: compounderror_test.go:201-201
Timestamp: 2025-08-05T22:27:53.946Z
Learning: In Go test functions using assertion helpers like AssertSame, AssertEqual, etc., early returns after assertion calls are only necessary when there is subsequent code that should be skipped if the assertion fails. At the end of a function or code block where no further operations follow, the early return pattern is redundant since the function will naturally return anyway.

Applied to files:

  • testing_test.go
  • testing.go
  • README.md
  • TESTING.md
📚 Learning: applies to readme.md : update readme.md to reflect significant changes in functionality or api....
Learnt from: CR
PR: darvaza-proxy/core#0
File: AGENT.md:0-0
Timestamp: 2025-08-04T16:07:42.136Z
Learning: Applies to README.md : Update README.md to reflect significant changes in functionality or API.

Applied to files:

  • README.md
  • TESTING.md
📚 Learning: applies to **/*.go : use go 1.23+ generics for type-safe utilities....
Learnt from: CR
PR: darvaza-proxy/core#0
File: AGENT.md:0-0
Timestamp: 2025-08-04T16:07:42.136Z
Learning: Applies to **/*.go : Use Go 1.23+ generics for type-safe utilities.

Applied to files:

  • README.md
📚 Learning: applies to agent.md : update `agent.md` to reflect any changes in development workflow or standards....
Learnt from: CR
PR: darvaza-proxy/core#0
File: AGENT.md:0-0
Timestamp: 2025-07-18T16:39:19.390Z
Learning: Applies to AGENT.md : Update `AGENT.md` to reflect any changes in development workflow or standards.

Applied to files:

  • README.md
📚 Learning: applies to agent.md : update agent.md to reflect any changes in development workflow or standards....
Learnt from: CR
PR: darvaza-proxy/core#0
File: AGENT.md:0-0
Timestamp: 2025-08-04T16:07:42.136Z
Learning: Applies to AGENT.md : Update AGENT.md to reflect any changes in development workflow or standards.

Applied to files:

  • README.md
📚 Learning: applies to **/*.md : add examples for complex concepts or common pitfalls in documentation....
Learnt from: CR
PR: darvaza-proxy/core#0
File: AGENT.md:0-0
Timestamp: 2025-08-04T16:07:42.136Z
Learning: Applies to **/*.md : Add examples for complex concepts or common pitfalls in documentation.

Applied to files:

  • TESTING.md
📚 Learning: applies to **/*.md : review documentation changes for missing articles, punctuation, and compound mo...
Learnt from: CR
PR: darvaza-proxy/core#0
File: AGENT.md:0-0
Timestamp: 2025-08-04T16:07:42.136Z
Learning: Applies to **/*.md : Review documentation changes for missing articles, punctuation, and compound modifiers.

Applied to files:

  • TESTING.md
📚 Learning: use only the go standard library and minimal golang.org/x packages; zero external dependencies....
Learnt from: CR
PR: darvaza-proxy/core#0
File: AGENT.md:0-0
Timestamp: 2025-08-04T16:07:42.136Z
Learning: Use only the Go standard library and minimal golang.org/x packages; zero external dependencies.

Applied to files:

  • TESTING.md
📚 Learning: always run make tidy first before committing: go code formatting and whitespace clean-up, markdown f...
Learnt from: CR
PR: darvaza-proxy/core#0
File: AGENT.md:0-0
Timestamp: 2025-08-04T16:07:42.136Z
Learning: ALWAYS run make tidy first before committing: Go code formatting and whitespace clean-up, Markdown files checked with CSpell and markdownlint, Shell scripts checked with shellcheck.

Applied to files:

  • TESTING.md
📚 Learning: applies to **/*.go : max function results: 3....
Learnt from: CR
PR: darvaza-proxy/core#0
File: AGENT.md:0-0
Timestamp: 2025-07-18T16:39:19.390Z
Learning: Applies to **/*.go : Max function results: 3.

Applied to files:

  • TESTING.md
📚 Learning: always run make tidy which includes golangci-lint checks....
Learnt from: CR
PR: darvaza-proxy/core#0
File: AGENT.md:0-0
Timestamp: 2025-08-04T16:07:42.136Z
Learning: Always run make tidy which includes golangci-lint checks.

Applied to files:

  • TESTING.md
📚 Learning: verify all tests pass with make test before committing....
Learnt from: CR
PR: darvaza-proxy/core#0
File: AGENT.md:0-0
Timestamp: 2025-08-04T16:07:42.136Z
Learning: Verify all tests pass with make test before committing.

Applied to files:

  • TESTING.md
📚 Learning: always run `make tidy` first before committing: fix all issues (go formatting, whitespace, cspell, m...
Learnt from: CR
PR: darvaza-proxy/core#0
File: AGENT.md:0-0
Timestamp: 2025-07-18T16:39:19.390Z
Learning: ALWAYS run `make tidy` first before committing: fix all issues (Go formatting, whitespace, CSpell, markdownlint, shellcheck).

Applied to files:

  • TESTING.md
🧬 Code Graph Analysis (1)
testing_test.go (1)
testing.go (21)
  • T (22-33)
  • MockT (45-51)
  • AssertFalse (436-439)
  • AssertTrue (421-424)
  • AssertEqual (263-272)
  • AssertPanic (368-385)
  • AssertMustEqual (622-627)
  • AssertMustNotEqual (636-641)
  • AssertMustSliceEqual (650-655)
  • S (225-230)
  • AssertMustContains (664-669)
  • AssertMustError (678-683)
  • AssertMustNoError (692-697)
  • AssertMustPanic (706-711)
  • AssertMustNoPanic (720-725)
  • AssertMustTrue (736-741)
  • AssertMustFalse (752-757)
  • AssertMustErrorIs (766-771)
  • AssertMustTypeIs (781-788)
  • AssertMustNil (797-802)
  • AssertMustNotNil (811-816)
🪛 LanguageTool
README.md

[locale-violation] ~304-~304: Lower-case ‘ok’ is American English. For British English use “OK”.
Context: ... value or panics with PanicError if ok is false. Useful for operations that sh...

(OK)


[locale-violation] ~306-~306: Lower-case ‘ok’ is American English. For British English use “OK”.
Context: ... always returns the value, ignoring the ok flag. When ok is false, the returned ...

(OK)


[locale-violation] ~307-~307: Lower-case ‘ok’ is American English. For British English use “OK”.
Context: ...the value, ignoring the ok flag. When ok is false, the returned value is typical...

(OK)


[uncategorized] ~312-~312: Possible missing article found.
Context: ...MaybeOK(As[any, T](value)). Returns converted value on success, or the zero value of ...

(AI_HYDRA_LEO_MISSING_THE)


[locale-violation] ~314-~314: Lower-case ‘ok’ is American English. For British English use “OK”.
Context: ...he As[any, T] function, which returns (value, ok) for type conversion, allowing custom ...

(OK)

TESTING.md

[grammar] ~968-~968: Consider using “to” with “prefer”.
Context: ...t.Helper() in all helper functions. * Prefer table-driven tests over individual test functions. * Keep setup and clean-...

(PREFER_OVER_TO)

🔇 Additional comments (18)
testing.go (10)

12-12: Excellent sentinel error implementation.

The sentinel error follows Go best practices and provides clear identification for FailNow panics in the panic recovery mechanism.


26-27: LGTM! Interface properly extended with fatal methods.

The T interface now fully matches Go's testing.T interface with the addition of Fatal, Fatalf, and FailNow methods. This maintains compatibility whilst enabling full testing functionality.

Also applies to: 31-31


37-44: Comprehensive documentation for MockT enhancements.

The documentation clearly explains the fatal method behaviour, panic recovery mechanism, and provides practical usage examples. This will help users understand how to test assertion functions that call Fatal methods.


63-63: Improved message formatting consistency.

The change to use fmt.Sprint and fmt.Sprintf ensures consistent formatting of arguments across all MockT methods, which is more robust than direct string concatenation.

Also applies to: 66-66, 73-73, 76-76, 82-82, 85-85, 90-90, 93-93


96-105: Excellent Fatal method implementation.

The method correctly combines Error and FailNow functionality, maintains thread safety with proper mutex usage, and uses the sentinel error for controlled panic recovery. The implementation mirrors Go's testing.T.Fatal behaviour perfectly.


107-116: Consistent Fatalf implementation.

The method follows the same pattern as Fatal whilst properly handling formatted messages. Thread safety and panic recovery are correctly implemented.


125-129: Clean FailNow implementation.

The method correctly reuses the existing Fail() method and uses the sentinel error for panic recovery. Simple and effective implementation that mirrors testing.T.FailNow.


182-211: Robust Run method with excellent panic recovery.

The implementation includes comprehensive nil checks, proper panic recovery that distinguishes between FailNow and other panics, and excellent documentation with practical examples. This enables effective testing of fatal assertion functions.


615-627: Well-implemented fatal assertion pattern.

AssertMustEqual correctly follows the fail-fast pattern by calling the underlying assertion and then FailNow on failure. The generic type constraint and documentation are appropriate.


629-816: Comprehensive and consistent AssertMust function suite.*

All 13 remaining AssertMust* functions follow the same reliable pattern: delegate to the underlying assertion, call FailNow() on failure, and include proper documentation. AssertMustTypeIs correctly returns the cast value on success. The implementation is consistent, well-documented, and provides the fail-fast semantics described in the PR objectives.

testing_test.go (6)

635-674: Comprehensive testing of MockT fatal methods.

The tests properly use MockT.Run for panic recovery and verify correct behaviour: Fatal/Fatalf record error messages and mark tests as failed, whilst FailNow only marks as failed without recording errors. The test patterns are well-structured and comprehensive.


676-713: Thorough testing of MockT.Run method edge cases.

The tests comprehensively cover successful execution, nil parameter handling, and proper panic propagation for non-FailNow panics. The use of AssertPanic to test panic propagation is appropriate and demonstrates the method's robustness.


715-831: Excellent demonstration of early abort patterns.

The tests comprehensively demonstrate the early abort pattern with various scenarios: successful continuation, failed abortion, multiple assertions, and mixed patterns. The tests clearly show the difference between regular assertions and early abort patterns, with proper verification of execution flow.


833-849: Well-organised test structure for AssertMust functions.*

The use of subtests provides clear organisation for testing all 14 AssertMust* functions. This structure makes it easy to run individual tests and understand test coverage.


851-1013: Consistent and thorough testing of AssertMust functions (first half).*

All tests follow the same reliable pattern: test success cases that allow execution to continue and failure cases that abort execution via FailNow. The verification of log counts and error states properly demonstrates the fail-fast semantics.


1015-1182: Comprehensive completion of AssertMust function testing.*

The remaining tests maintain the same high standard with consistent success/failure patterns. AssertMustTypeIs correctly tests both the return value on success and abort behaviour on failure. The comprehensive coverage aligns well with the coding guidelines for generic function testing.

README.md (2)

472-474: LGTM – clear description of the enhanced MockT

The added sentence accurately documents MockT.Run() and its Fatal/FailNow
behaviour. No issues spotted.


510-558: LGTM – exhaustive fatal assertion list

The list is complete, consistently punctuated, and follows the documented
naming conventions.

@amery amery added the enhancement New feature or request label Aug 6, 2025
Copy link
Contributor

@karasz karasz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

awesome, especially this:

func (m *MockT) Run(_ string, f func(T)) (ok bool) {
	if m == nil || f == nil {
		return false
	}

      defer func() {
          if r := recover(); r != nil && r != errMockTFailNow {
              panic(r) // Re-panic non-FailNow errors
          }
      }()

      f(m)

      return !m.Failed()
  }

@karasz karasz merged commit 8ac4fc2 into main Aug 8, 2025
17 checks passed
@karasz karasz deleted the pr-amery-testing branch August 8, 2025 15:30
@amery
Copy link
Contributor Author

amery commented Aug 8, 2025

Released as v0.18.1.

go get darvaza.org/core@v0.18.1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request Review effort 4/5

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants