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 without external libraries. Tests use only the standard library package and avoid mock frameworks or assertion libraries. This is to keep dependencies minimal and tests readable using standard Go patterns.
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.
12
13## Patterns
14
15### Handler Creation Pattern
16
17Tests 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.
18
19### Database Isolation
20
21Tests 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.
22
23The `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.
24
25### Resource Management
26
27Tests 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.
28
29### Error Handling
30
31Tests 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.
32
33### Context Cancellation Testing Pattern
34
35Error 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.
36
37### Command Structure Testing
38
39Command 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.
40
41### Interface Compliance Testing
42
43Tests verify interface compliance using compile-time checks with blank identifier assignments. This ensures structs implement expected interfaces without runtime overhead.
44
45## Test Organization Patterns
46
47### Single Root Test
48
49The 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.
50
51### Integration vs Unit Testing
52
53The 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.
54
55### Static Output
56
57UI 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.
58
59### Standard Output Redirection
60
61For 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.
62
63## Utilities
64
65### Helpers
66
67Test files include helper functions for creating test data and finding elements in collections. These utilities reduce code duplication and improve test readability.
68
69### Mock Data
70
71Tests create realistic mock data using factory functions (powered by faker) that return properly initialized structs with sensible defaults.
72
73## Testing CLI Commands
74
75Command 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.
76
77### CommandGroup Interface Testing
78
79The 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.
80
81Interface compliance is tested using compile-time checks within the "Interface Implementations" subtest, ensuring all command structs properly implement the CommandGroup interface without runtime overhead.
82
83## Performance Considerations
84
85Tests 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.
86
87The single root test pattern allows for efficient resource management where setup costs can be amortized across multiple related test cases.
88
89## Errors
90
91Error coverage follows a systematic approach to identify and test failure scenarios:
92
931. **Context Cancellation** - Primary method for testing database and network timeout scenarios
942. **Invalid Input** - Malformed data, empty inputs, boundary conditions
953. **Resource Exhaustion** - Database connection failures, memory limits
964. **Constraint Violations** - Duplicate keys, foreign key failures
975. **State Validation** - Testing functions with invalid system states