cli + tui to publish to leaflet (wip) & manage tasks, notes & watch/read lists 馃崈
charm leaflet readability golang
1# Testing Documentation 2 3This document outlines the testing patterns and practices used in the `noteleaf` application. 4 5## Overview 6 7The codebase follows Go's standard testing practices with specialized testing utilities for complex scenarios. Tests use the standard library along with carefully selected dependencies like faker for data generation and BubbleTea for TUI testing. This approach keeps dependencies minimal while providing robust testing infrastructure for interactive components and complex integrations. 8 9### Organization 10 11Each package contains its own test files alongside the source code. Test files are organized by functionality and mirror the structure of the source code they test. The codebase includes four main test utility files that provide specialized testing infrastructure: 12 13- `internal/services/test_utilities.go` - HTTP mocking and media service testing 14- `internal/repo/test_utilities.go` - Database testing and data generation 15- `internal/ui/test_utilities.go` - TUI testing framework and interactive component testing 16- `internal/handlers/test_utilities.go` - Handler testing with database isolation and input simulation 17 18## Patterns 19 20### Handler Creation 21 22Tests create real handler instances using temporary databases to ensure test isolation. Factory functions handle both database setup and handler initialization, returning both the handler and a cleanup function. 23 24### Database Isolation 25 26Tests use temporary directories and environment variable manipulation to create isolated database instances. Each test gets its own temporary SQLite database that is automatically cleaned up after the test completes. 27 28The `setupCommandTest` function creates a temporary directory, sets `XDG_CONFIG_HOME` to point to it, and initializes the database schema. This ensures tests don't interfere with each other or with development data. 29 30### Resource Management 31 32Tests properly manage resources using cleanup functions returned by factory methods. The cleanup function handles both handler closure and temporary directory removal. This pattern ensures complete resource cleanup even if tests fail. 33 34### Error Handling 35 36Tests use `t.Fatal` for setup errors that prevent test execution and `t.Error` for test assertion failures. Fatal errors stop test execution while errors allow tests to continue checking other conditions. 37 38### Context Cancellation 39 40Error case testing frequently uses context cancellation to simulate database and network failures. The pattern creates a context, immediately cancels it, then calls the function under test to verify error handling. This provides a reliable way to test error paths without requiring complex mock setups or external failure injection. 41 42### Command Structure 43 44Command group tests verify cobra command structure including use strings, aliases, short descriptions, and subcommand presence. Tests check that commands are properly configured without executing their logic. 45 46### Interface Compliance 47 48Tests verify interface compliance using compile-time checks with blank identifier assignments. This ensures structs implement expected interfaces without runtime overhead. 49 50## Test Infrastructure 51 52### Test Utility Frameworks 53 54The codebase provides comprehensive testing utilities organized by layer and functionality. Each test utility file contains specialized helpers, mocks, and test infrastructure for its respective domain. 55 56#### Database Testing Utilities 57 58`internal/repo/test_utilities.go` provides comprehensive database testing infrastructure: 59 60- **In-Memory Database Creation**: `CreateTestDB` creates isolated SQLite databases with full schema 61- **Sample Data Factories**: Functions like `CreateSampleTask`, `CreateSampleBook` generate realistic test data 62- **Faker Integration**: Uses jaswdr/faker for generating realistic fake data with `CreateFakeArticle` 63- **Test Setup Helpers**: `SetupTestData` creates a full set of sample data across all models 64- **Custom Assertions**: Generic assertion helpers like `AssertEqual`, `AssertContains`, `AssertNoError` 65 66#### HTTP Service Testing 67 68`internal/services/test_utilities.go` provides HTTP mocking and media service testing: 69 70- **Mock Configuration**: `MockConfig` structure for configuring service behavior 71- **Function Replacement**: `SetupMediaMocks` replaces service functions with controllable mocks 72- **Sample Data Access**: Helper functions that use embedded HTML samples for realistic testing 73- **Specialized Scenarios**: Pre-configured mock setups for success and failure scenarios 74- **Assertion Helpers**: Domain-specific assertions for movies, TV shows, and error conditions 75 76#### TUI Testing Framework 77 78`internal/ui/test_utilities.go` provides a comprehensive BubbleTea testing framework: 79 80- **TUITestSuite**: Complete testing infrastructure for interactive TUI components 81- **Controlled I/O**: `ControlledOutput` and `ControlledInput` for deterministic testing 82- **Message Simulation**: Key press simulation, message queuing, and timing control 83- **State Verification**: Model state checking and view content assertions 84- **Timeout Handling**: Configurable timeouts for async operations 85- **Mock Repository**: Test doubles for repository interfaces 86 87#### Handler Testing Infrastructure 88 89`internal/handlers/test_utilities.go` provides end-to-end handler testing: 90 91- **Environment Isolation**: `HandlerTestHelper` creates isolated test environments 92- **Input Simulation**: `InputSimulator` for testing interactive components that use `fmt.Scanf` 93- **HTTP Mocking**: Comprehensive HTTP server mocking for external API testing 94- **Database Helpers**: Database corruption and error scenario testing 95- **Editor Mocking**: `MockEditor` for testing file editing workflows 96- **Assertion Helpers**: Handler-specific assertions and verification functions 97 98### Advanced Testing Patterns 99 100#### Input Simulation for Interactive Components 101 102Interactive handlers that use `fmt.Scanf` require special testing infrastructure with an `io.Reader` implementation. 103 104The `InputSimulator` provides controlled input sequences that prevent tests from hanging while maintaining coverage of interactive code paths. 105 106#### TUI Testing with BubbleTea Framework 107 108The TUI testing framework addresses the fundamental challenge of testing interactive terminal applications in a deterministic, concurrent environment. BubbleTea's message-passing architecture creates unique testing requirements that standard Go testing patterns cannot adequately address. 109 110The framework implements a controlled execution environment that replaces BubbleTea's typical program loop with a deterministic testing harness. Rather than running an actual terminal program, the "testing suite" directly manages model state transitions by simulating the Update/View cycle. This approach eliminates the non-deterministic behavior inherent in real terminal interactions while preserving the exact message flow patterns that production code experiences. 111 112State verification relies on function composition patterns where test conditions are expressed as closures that capture specific model states. The `WaitFor` mechanism uses polling with configurable timeouts, addressing the async nature of BubbleTea model updates without creating race conditions. This pattern bridges imperative test assertions with BubbleTea's declarative update model. 113This is inspired by front-end/TS/JS testing patterns. 114 115The framework's I/O abstraction layer replaces terminal input/output with controlled buffers that implement standard Go interfaces. 116This design maintains interface compatibility while providing complete control over timing and content. The controlled I/O system captures all output for later verification and injects precise input sequences, enabling complex interaction testing without external dependencies. 117 118Concurrency management uses channels and context propagation to coordinate between the testing framework and the model under test. 119The suite manages goroutine lifecycle and ensures proper cleanup, preventing test interference and resource leaks. This architecture supports testing of models that perform background operations or handle async events. 120 121#### HTTP Service Mocking 122 123Service testing uses HTTP mocking with request capture. A `MockServer` is instantiated, and its URL is used in test scoped services. 124 125#### Database Schema Testing 126 127Database tests use comprehensive schema setup with (automatic) cleanup 128 129#### Environment Manipulation 130 131Environment testing utilities provide controlled environment manipulation. Environment variables are restored after instantiation. 132 133## Test Organization Patterns 134 135### Single Root Test 136 137The preferred test organization pattern uses a single root test function with nested subtests using `t.Run`. This provides clear hierarchical organization and allows running specific test sections while maintaining shared setup and context. This pattern offers several advantages: clear test hierarchy with logical grouping, ability to run specific test sections, consistent test structure across the codebase, and shared setup that can be inherited by subtests. 138 139### Integration vs Unit Testing 140 141The codebase emphasizes integration testing over heavy mocking by using real handlers and services to verify actual behavior rather than mocked interactions. The goal is to catch integration issues while maintaining test reliability. 142 143### Static Output 144 145UI components support static output modes for testing. Tests capture output using bytes.Buffer and verify content using string contains checks rather than exact string matching for better test maintainability. 146 147### Standard Output Redirection 148 149For testing functions that write to stdout, tests use a pipe redirection pattern with goroutines to capture output. The pattern saves the original stdout, redirects to a pipe, captures output in a separate goroutine, and restores stdout after the test. This ensures clean output capture without interfering with the testing framework. 150 151## Utilities 152 153### Test Data Generation 154 155The codebase uses sophisticated data generation strategies: 156 157- **Factory Functions**: Each package provides factory functions for creating valid test data 158- **Faker Integration**: Uses `jaswdr/faker` for generating realistic fake data with proper randomization 159- **Sample Data Creators**: Functions like `CreateSampleTask`, `CreateSampleBook` provide consistent test data 160- **Embedded Resources**: Services use embedded HTML samples from real API responses for realistic testing 161 162### Assertion Helpers 163 164Custom assertion functions provide clear error messages and reduce test code duplication: 165 166- **Generic Assertions**: `AssertEqual`, `AssertNoError`, `AssertContains` for common checks 167- **Domain-Specific Assertions**: `AssertMovieInResults`, `AssertNoteExists` for specialized verification 168- **TUI Assertions**: `AssertViewContains`, `AssertModelState` for BubbleTea model testing 169- **HTTP Assertions**: `AssertRequestMade` for verifying HTTP interactions 170 171### Mock Infrastructure 172 173Each layer provides specialized mocking capabilities: 174 175- **Service Mocking**: Function replacement with configurable behavior and embedded test data 176- **HTTP Mocking**: `HTTPMockServer` with request capture and response customization 177- **Input Mocking**: `InputSimulator` for deterministic interactive component testing 178- **Editor Mocking**: `MockEditor` for file editing workflow testing 179- **Repository Mocking**: `MockTaskRepository` for TUI component testing 180 181### Environment and Resource Management 182 183Testing utilities provide comprehensive resource management: 184 185- **Environment Isolation**: `EnvironmentTestHelper` for controlled environment variable manipulation 186- **Database Isolation**: Temporary SQLite databases with automatic cleanup 187- **File System Isolation**: Temporary directories with automatic cleanup 188- **Process Isolation**: Handler helpers that create completely isolated test environments 189 190## Testing CLI Commands 191 192Command group tests focus on structure verification rather than execution testing. Tests check command configuration, subcommand presence, and interface compliance. This approach ensures command trees are properly constructed without requiring complex execution mocking. 193 194### CommandGroup Interface Testing 195 196The CommandGroup interface enables testable CLI architecture. Tests verify that command groups implement the interface correctly and return properly configured cobra commands. This pattern separates command structure from command execution. 197 198Interface compliance is tested using compile-time checks within the "Interface Implementations" subtest, ensuring all command structs properly implement the CommandGroup interface without runtime overhead. 199 200## Performance Considerations 201 202Tests avoid expensive operations in setup functions. Handler creation uses real instances but tests focus on structure verification rather than full execution paths. This keeps test suites fast while maintaining coverage of critical functionality. 203 204The single root test pattern allows for efficient resource management where setup costs can be amortized across multiple related test cases. 205 206## Interactive Component Testing 207 208The codebase provides comprehensive testing infrastructure for interactive components, including both terminal UI applications and command-line interfaces that require user input. 209 210### Input Simulation Framework 211 212Interactive handlers that use `fmt.Scanf` require specialized testing infrastructure: 213 214- **InputSimulator**: Provides controlled input sequences that implement `io.Reader` 215- **Menu Selection Helpers**: `MenuSelection`, `MenuCancel`, `MenuSequence` for common interaction patterns 216- **Handler Integration**: Handlers can accept `io.Reader` for input, enabling deterministic testing 217- **Cleanup Management**: Automatic cleanup prevents resource leaks in test environments 218 219### TUI Testing with BubbleTea 220 221The TUI testing framework provides complete testing infrastructure for interactive terminal interfaces: 222 223- **TUITestSuite**: Comprehensive testing framework for BubbleTea models 224- **Message Simulation**: Key press simulation, window resize events, and custom message handling 225- **State Verification**: Model state checking with custom condition functions 226- **View Assertions**: Content verification and output capture 227- **Timing Control**: Configurable timeouts and delay handling for async operations 228- **Mock Integration**: Repository mocking for isolated component testing 229 230### Interactive Test Scenarios 231 232Interactive handlers should test comprehensive scenarios: 233 234- **Valid user selections** - User chooses valid menu options and inputs 235- **Cancellation flows** - User chooses to cancel operations (option 0 or escape keys) 236- **Invalid choices** - User selects out-of-range options or provides invalid input 237- **Navigation patterns** - Keyboard navigation, scrolling, and multi-step interactions 238- **Error handling** - Network errors, service failures, and data validation errors 239- **Empty states** - Search returns no results, empty lists, and missing data 240- **Edge cases** - Boundary conditions, malformed input, and resource constraints 241 242### TUI Component Testing Patterns 243 244BubbleTea components use specialized testing patterns: 245 246- **Key Sequence Testing**: Simulate complex user interactions with timing 247- **State Transition Testing**: Verify model state changes through user actions 248- **View Content Testing**: Assert specific content appears in rendered output 249- **Async Operation Testing**: Handle loading states and network operations 250- **Responsive Design Testing**: Test different terminal sizes and window resize handling 251 252This comprehensive testing approach ensures interactive components work reliably in automated environments while maintaining full coverage of user interaction paths. 253 254## Errors 255 256Error coverage follows a systematic approach to identify and test failure scenarios: 257 2581. **Context Cancellation** - Primary method for testing database and network timeout scenarios 2592. **Invalid Input** - Malformed data, empty inputs, boundary conditions 2603. **Resource Exhaustion** - Database connection failures, memory limits 2614. **Constraint Violations** - Duplicate keys, foreign key failures 2625. **State Validation** - Testing functions with invalid system states 2636. **Interactive Input** - Invalid user choices, cancellation handling, input simulation errors