docs: map existing codebase

This commit is contained in:
2026-02-28 20:12:08 +01:00
commit 7f1a4ce1f1
7 changed files with 1049 additions and 0 deletions
+97
View File
@@ -0,0 +1,97 @@
# Architecture
**Analysis Date:** 2026-02-28
## Pattern Overview
**Overall:** Single-Binary CLI/TUI Application (Rust)
**Key Characteristics:**
- Monolithic Rust binary using Ratatui for terminal UI
- Minimal dependency footprint (only Ratatui as external dependency)
- Single entry point with main function
- Early-stage project with foundational structure only
## Layers
**Presentation Layer:**
- Purpose: Terminal user interface rendering and interaction
- Location: `src/main.rs` (currently)
- Contains: TUI initialization, event handling, widget rendering
- Depends on: Ratatui framework
- Used by: End users through terminal
**Business Logic Layer:**
- Purpose: Core application functionality
- Location: TBD - not yet implemented
- Contains: Data processing, command handling, state management
- Depends on: None currently defined
- Used by: Presentation layer
**Data Layer:**
- Purpose: Data persistence and retrieval
- Location: TBD - not yet implemented
- Contains: File I/O, caching, serialization
- Depends on: Standard library (File, IO)
- Used by: Business logic layer
## Data Flow
**Typical User Interaction Flow:**
1. Terminal input captured by Ratatui event handling
2. User action (keyboard/mouse) parsed into application command
3. Command dispatched to business logic handler
4. Handler processes request, potentially reads/writes data
5. State updated based on result
6. UI re-rendered with new state in next frame
**State Management:**
- Single application state entity (not yet defined)
- Immutable state passed to rendering function
- Ratatui handles incremental screen updates
## Key Abstractions
**Terminal User Interface (TUI):**
- Purpose: Encapsulate all terminal rendering and input handling
- Examples: `src/main.rs` (current single module)
- Pattern: React-like paradigm via Ratatui (state -> render)
**Application Command/Action:**
- Purpose: Abstract user intentions from input events
- Examples: Not yet implemented
- Pattern: Enum-based command pattern expected
## Entry Points
**Binary Entry:**
- Location: `src/main.rs`
- Triggers: `cargo run` or binary execution
- Responsibilities:
- Initialize Ratatui terminal
- Set up event loop
- Handle application lifecycle
- Render UI each frame
- Currently: Placeholder with "Hello, world!" output
## Error Handling
**Strategy:** Not yet defined
**Patterns:**
- Ratatui provides Result types for I/O operations
- Expected approach: Result-based error propagation using ? operator
- Terminal restoration should be ensured on panic (Ratatui provides Drop impl)
## Cross-Cutting Concerns
**Logging:** Not yet implemented. Standard approach would use `log` crate or println! macros during development.
**Validation:** Not yet implemented. Expected in business logic layer once commands are defined.
**Terminal State:** Ratatui manages terminal state (raw mode, cursor visibility, etc.). Must ensure proper cleanup on application exit.
---
*Architecture analysis: 2026-02-28*
+104
View File
@@ -0,0 +1,104 @@
# Codebase Concerns
**Analysis Date:** 2026-02-28
## Critical Issues
**Empty Application Stub:**
- Issue: The entire application is a bare "Hello, world!" stub with no functional implementation
- Files: `src/main.rs`
- Impact: No actual BBS markdown functionality exists; application is not usable
- Fix approach: Implement core application logic for markdown bulletin board system functionality
**Invalid Edition Specification:**
- Issue: `Cargo.toml` specifies `edition = "2024"` which is not a valid Rust edition
- Files: `Cargo.toml`
- Impact: Build will fail or behave unexpectedly if edition validation is enforced; incorrect edition can affect language feature availability
- Fix approach: Change to a valid edition: `2021` (latest stable) or `2018` if legacy support needed
## Tech Debt
**Minimal Dependency Management:**
- Issue: Heavy dependency on ratatui (0.30.0) and its entire ecosystem for a stub application
- Files: `Cargo.toml`
- Impact: Unnecessary compiled binary size and build time for functionality that doesn't yet exist; approximately 60+ transitive dependencies for "Hello, world!"
- Fix approach: Keep ratatui when actual TUI is implemented; document why ratatui was chosen early
**No Error Handling:**
- Issue: Application has no error handling, logging, or graceful failure modes
- Files: `src/main.rs`
- Impact: Crashes will be silent or unhelpful; no debugging information available
- Fix approach: Implement structured error handling; consider using `anyhow` or `thiserror` crate (already available in dependencies)
**No Architecture Documentation:**
- Issue: Zero guidance on how BBS-MD should be structured or what features should be implemented
- Files: Project root (missing design docs)
- Impact: Development direction unclear; future contributors won't understand intent
- Fix approach: Create architecture documentation, feature specification, and roadmap
## Missing Critical Features
**No TUI Implementation:**
- What's missing: Terminal UI is imported (ratatui) but never used
- Blocks: Cannot create/view/edit bulletin board content
- Priority: High
**No Data Persistence:**
- What's missing: No markdown file handling, no storage mechanism
- Blocks: Cannot persist BBS posts or configuration
- Priority: High
**No Input Processing:**
- What's missing: Application ignores user input entirely
- Blocks: Cannot interact with application
- Priority: High
## Test Coverage Gaps
**Zero Testing:**
- What's not tested: All functionality (or complete lack thereof)
- Files: No test directory exists; `src/main.rs` has no tests
- Risk: No confidence in correctness; refactoring will be dangerous
- Priority: High
## Scalability & Architecture Concerns
**Monolithic Structure:**
- Problem: Single main.rs file will quickly become unmaintainable as features are added
- Current capacity: ~45 lines before severe maintainability issues
- Scaling path: Create modular structure with separate modules for TUI layer, data layer, business logic
**Dependency Organization:**
- Problem: Entire ratatui ecosystem locked in at build time even when not used
- Current capacity: 60+ transitive dependencies inflating binary
- Scaling path: Feature-gate dependencies or defer dependency addition until features are implemented
## Security Considerations
**Unvalidated Input:**
- Risk: Once input processing is added, no visible validation or sanitization strategy exists
- Files: Will be implemented in future features
- Current mitigation: None (application ignores input)
- Recommendations: Plan input validation for markdown parsing; sanitize user-provided content if displayed; consider file path traversal protections if file loading is implemented
**File System Access:**
- Risk: Future markdown file handling could expose security issues (directory traversal, privilege escalation)
- Files: Not yet implemented
- Current mitigation: None
- Recommendations: When implementing file I/O, enforce strict path validation; restrict operations to designated directories only
## Dependencies at Risk
**Edition Mismatch:**
- Risk: Invalid edition specification may cause build failures or unexpected behavior in future toolchain versions
- Impact: Application may not compile with newer Rust tools
- Migration plan: Immediately fix to `edition = "2021"` to match stable toolchain
**Tight Coupling to Ratatui:**
- Risk: Early adoption of specific TUI framework before requirements are clear
- Impact: Switching frameworks later will require significant refactoring
- Migration plan: Encapsulate ratatui behind abstraction layer; consider generic TUI trait to allow future framework swaps
---
*Concerns audit: 2026-02-28*
+200
View File
@@ -0,0 +1,200 @@
# Coding Conventions
**Analysis Date:** 2026-02-28
## Overview
This is an early-stage Rust project with minimal codebase (single `main.rs` file). Conventions are established based on:
- Rust language defaults and community standards
- Cargo default behavior
- Current code patterns in the project
## Naming Patterns
**Files:**
- Snake case: `main.rs`, `lib.rs` are standard entry points
- Module files use snake_case: `user_service.rs`, `data_handler.rs`
- Test modules within files or in separate `tests/` directory
**Functions:**
- Snake case throughout: `fn handle_connection()`, `fn parse_input()`
- Use descriptive verb-based names: `fn calculate_sum()`, `fn build_response()`
**Variables:**
- Snake case for bindings: `let user_id`, `let response_data`
- Constants use UPPER_CASE: `const MAX_BUFFER_SIZE: usize = 1024`
- Mutable bindings explicitly marked: `let mut count = 0`
**Types and Structs:**
- PascalCase for type names: `struct User`, `enum Status`, `trait Handler`
- Generic parameters use single letters or PascalCase: `T`, `S`, `Request`
- Lifetime parameters use lowercase: `'a`, `'static`
## Code Style
**Formatting:**
- Default Rust formatting applied by `rustfmt` (de facto standard)
- 4-space indentation (Rust default)
- No semicolons in final expressions that return values
- Closing braces on same line except for block statements
**Linting:**
- Clippy lints should be addressed as part of development
- No explicit `clippy.toml` or linting configuration currently present
- Default clippy warnings and errors should be resolved before commit
**Edition:**
- Rust 2024 edition (specified in `Cargo.toml`)
- Supports latest language features and idioms
## Import Organization
**Order:**
1. Standard library imports (`use std::`)
2. External crate imports (`use ratatui::`, other external deps)
3. Internal crate imports (`use crate::`)
4. Module declarations (`mod xyz;`)
**Example:**
```rust
use std::io;
use std::collections::HashMap;
use ratatui::backend::CrosstermBackend;
use ratatui::Terminal;
use crate::ui::draw;
use crate::handler::InputHandler;
```
**Path Aliases:**
- No path aliases configured currently
- Can be added via workspace root configuration if needed
## Error Handling
**Patterns:**
- Use `Result<T, E>` for fallible operations
- Propagate errors with `?` operator rather than unwrapping when possible
- Use `anyhow::Result` for application-level errors (dependency available)
- Only use `.unwrap()` or `.expect()` for code that should never panic in normal operation
**Example:**
```rust
fn read_config(path: &str) -> Result<Config> {
let content = std::fs::read_to_string(path)?;
let config = serde_json::from_str(&content)?;
Ok(config)
}
```
## Logging
**Framework:** Not yet selected/integrated
**When logging is added:**
- Use `log` crate for production logging
- Use `env_logger` or similar for log configuration
- Log levels: ERROR for failures, WARN for unusual conditions, INFO for significant events, DEBUG for detailed traces
- Avoid logging sensitive data (credentials, tokens, PII)
## Comments
**When to Comment:**
- Explain the "why" not the "what"
- Document non-obvious algorithmic decisions
- Explain trade-offs or workarounds
- Mark intentional violations of conventions with `// FIXME:` or `// TODO:`
**Doc Comments:**
- Use `///` for public item documentation
- Document public functions, structs, enums, traits
- Include examples for complex or non-obvious public APIs
**Example:**
```rust
/// Processes a user command from the input buffer.
///
/// This function parses the raw input and dispatches to appropriate handlers.
///
/// # Arguments
/// * `input` - Raw user input string
///
/// # Returns
/// `Result<CommandResult, Error>` indicating success or the error encountered
pub fn process_command(input: &str) -> Result<CommandResult> {
// Implementation
}
```
## Function Design
**Size:**
- Keep functions small and focused (ideally < 50 lines)
- Extract helper functions for complex logic
- Separate parsing, validation, and execution logic
**Parameters:**
- Use owned values for simple types, references for larger types
- Prefer `&[T]` over `&Vec<T>` for function parameters
- Use structs to group related parameters (> 3 related params)
**Return Values:**
- Use `Result<T, E>` for operations that can fail
- Use `Option<T>` for values that may be absent
- Avoid returning `Box<dyn Trait>` unless necessary for dynamic dispatch
## Module Design
**Exports:**
- Explicitly declare public items with `pub`
- Use `pub use` to re-export important types at module boundaries
- Keep implementation details private (`non-pub` by default)
**Module Structure:**
```rust
// src/main.rs
mod ui;
mod handler;
mod model;
use ui::App;
use handler::InputHandler;
fn main() {
// Implementation
}
```
**Barrel Files:**
- Use `mod.rs` files in subdirectories to organize module exports
- Example: `src/ui/mod.rs` exports types from `ui/draw.rs`, `ui/state.rs`
## Unsafe Code
**Usage:**
- Avoid unsafe blocks unless necessary for FFI or performance-critical code
- Document unsafe code with `// SAFETY:` comments explaining invariants
- Minimize unsafe scope
**Example:**
```rust
// SAFETY: ptr is guaranteed to point to valid, initialized memory
// returned from foreign_function, which owns its lifetime
unsafe {
let result = process_data(ptr);
}
```
## Workspace and Multi-Crate Structure
**Currently:** Single binary crate (`bbs-md`)
**If expanding:**
- Consider separating into `bbs-md` (binary) and `bbs-md-core` (library)
- Use workspace for shared dependencies and configuration
- Place library code in `src/lib.rs`, binary-specific code in `src/main.rs`
---
*Convention analysis: 2026-02-28*
+76
View File
@@ -0,0 +1,76 @@
# External Integrations
**Analysis Date:** 2026-02-28
## APIs & External Services
**Not detected** - This is a standalone TUI application with no external API integrations.
## Data Storage
**Databases:**
- Not detected - No database client/ORM dependencies present
**File Storage:**
- Local filesystem only - Markdown files read/written to local disk
**Caching:**
- Not detected - No external caching service
## Authentication & Identity
**Auth Provider:**
- Custom or None - No authentication framework detected
**Implementation:**
- Local-only TUI application with no user authentication layer
## Monitoring & Observability
**Error Tracking:**
- Not detected - No error tracking service integration
**Logs:**
- Standard output/stderr via log crate facade
- Controlled via application logging configuration
## CI/CD & Deployment
**Hosting:**
- Standalone binary deployment - Compiled as single executable
**CI Pipeline:**
- Not detected - No CI/CD configuration files present
## Environment Configuration
**Required env vars:**
- None detected - Configuration appears to be hardcoded or via CLI arguments
**Secrets location:**
- Not applicable - No external service credentials required
## Webhooks & Callbacks
**Incoming:**
- Not applicable - Standalone CLI application
**Outgoing:**
- Not applicable - No webhook support detected
## Terminal Environment
**Integration Points:**
- Terminal protocol: VT100 escape sequences
- Platform support via crossterm:
- Unix/Linux systems: Raw mode via termios
- Windows systems: Windows API for console mode
- macOS: POSIX terminal support
**Signal Handling:**
- Unix signals (SIGTERM, SIGINT) for graceful shutdown
- Integrated via signal-hook and mio event loop
---
*Integration audit: 2026-02-28*
+128
View File
@@ -0,0 +1,128 @@
# Technology Stack
**Analysis Date:** 2026-02-28
## Languages
**Primary:**
- Rust - CLI/TUI application for markdown bulletin board system
## Runtime
**Environment:**
- Rust compiler and runtime
**Package Manager:**
- Cargo
- Lockfile: `Cargo.lock` present
## Frameworks
**Core:**
- ratatui 0.30.0 - Terminal user interface (TUI) framework for building rich CLI applications
**Build:**
- cargo - Rust package manager and build system
## Key Dependencies
**Critical:**
- ratatui 0.30.0 - Main TUI framework providing terminal rendering, event handling, and widgets
- ratatui-core - Core functionality for ratatui
- ratatui-crossterm - Crossterm backend integration for ratatui
- ratatui-macros - Proc macros for ratatui
- ratatui-termwiz - Termwiz backend support for ratatui
- ratatui-widgets - Widget library for ratatui
**Terminal & Input:**
- crossterm 0.29.0 - Cross-platform terminal manipulation library (Windows/Unix compatible)
- signal-hook - Unix signal handling for clean shutdowns
- signal-hook-mio - Integration between signal-hook and mio
- termwiz - Terminal operations library with wide character support
- terminfo - Terminal capability detection
- vtparse - VT100 escape sequence parser
- utf8parse - UTF-8 parsing utilities
**UI Rendering & Text:**
- unicode-width - Calculate display width of unicode characters
- unicode-truncate - Truncate unicode strings to display width
- unicode-segmentation - Segment unicode text
- wezterm-bidi - Bidirectional text support
- fancy-regex - Advanced regex support with lookahead/lookbehind
- regex 1.x - Regular expression library
**Graphics & Color:**
- csscolorparser 0.6.2 - Parse CSS color strings
- wezterm-color-types - Color type definitions
- euclid - 2D and 3D geometry primitives
- line-clipping - Line clipping algorithms
**Data Structures & Utilities:**
- indexmap - Hash map preserving insertion order
- hashbrown - Faster hashmap implementation
- smallvec - Vector that stores small amounts inline
- itertools - Iterator extensions
- nom - Parser combinators library
- pest - PEG parser generator
- strum/strum_macros - Enum utilities and macros
**Serialization:**
- serde/serde_json - Serialization framework
- base64 - Base64 encoding/decoding
**Error Handling:**
- anyhow 1.0.102 - Flexible error handling
- thiserror - Structured error types
**Platform Support:**
- libc - C library bindings (Unix)
- rustix - Wrapper around system calls
- nix - Unix-like API bindings
- winapi - Windows API bindings
- windows-sys - Windows system APIs
- parking_lot - Synchronization primitives
**Hashing & Crypto:**
- sha2 - SHA-2 digest algorithms
- xxhash-rust - xxHash algorithm
**UUID & ID Generation:**
- uuid - UUID generation and parsing
- mac_address - MAC address utilities
**Logging:**
- log - Logging facade
**Development & Macros:**
- syn - Rust syntax tree parsing
- quote - Quoting for proc macros
- proc-macro2 - Proc macro utilities
- darling - Attribute macro argument parsing
## Configuration
**Build Configuration:**
- Edition: 2024 (Rust edition)
- Target: Binary executable
- Manifest: `Cargo.toml`
**Dependencies Management:**
- Lock file: `Cargo.lock` ensures reproducible builds
- All dependencies from crates.io registry
- Transitive dependency management handled by Cargo
## Platform Requirements
**Development:**
- Rust toolchain (cargo)
- POSIX-compliant system (Linux, macOS) or Windows
- Terminal support for modern escape sequences
**Production:**
- Binary compiled for target platform (Linux, macOS, Windows)
- Terminal with VT100 escape sequence support
- UTF-8 capable terminal
---
*Stack analysis: 2026-02-28*
+120
View File
@@ -0,0 +1,120 @@
# Codebase Structure
**Analysis Date:** 2026-02-28
## Directory Layout
```
bbs-md/
├── src/ # Rust source code
│ └── main.rs # Binary entry point and main application logic
├── target/ # Build artifacts (generated)
├── .git/ # Git repository metadata
├── .planning/ # Planning and documentation
│ └── codebase/ # Architecture and structure docs
├── Cargo.toml # Rust package manifest
├── Cargo.lock # Dependency lock file
└── .gitignore # Git ignore rules
```
## Directory Purposes
**src/**
- Purpose: All Rust source code for the project
- Contains: Rust modules and binary logic
- Key files: `main.rs`
**.planning/codebase/**
- Purpose: Architecture and codebase analysis documents
- Contains: ARCHITECTURE.md, STRUCTURE.md, CONVENTIONS.md, TESTING.md (as written)
- Generated by: Codebase mapping process
**target/**
- Purpose: Build output directory (generated by Cargo)
- Contains: Compiled binaries, dependencies, metadata
- Generated: Yes
- Committed: No (in .gitignore)
## Key File Locations
**Entry Points:**
- `src/main.rs`: Main binary executable, contains fn main() and all current application logic
**Configuration:**
- `Cargo.toml`: Package metadata, dependencies, build configuration
**Build Output:**
- `Cargo.lock`: Locked dependency versions ensuring reproducible builds
## Naming Conventions
**Files:**
- `main.rs`: Entry point for binary crate
- `lib.rs`: Would be used for library crate (not present)
- Module files: `module_name.rs` (snake_case)
- Cargo files: `Cargo.toml`, `Cargo.lock`
**Directories:**
- `src/`: Source code directory (Rust convention)
- `target/`: Build output (Cargo convention)
- Module directories: `snake_case/` for organizing modules into subdirectories
**Modules:**
- Snake_case for module names in Rust
- Single-word module names preferred for clarity
## Where to Add New Code
**New Feature:**
- Primary code: `src/main.rs` until structure grows
- Once > 300 lines: Extract to `src/feature_name.rs`, then `mod feature_name;` in main.rs
- Tests: In same file with `#[cfg(test)]` module, or separate `src/feature_name_test.rs`
**New Component/Module:**
- Implementation: Create `src/module_name.rs`
- Export in `src/main.rs` with `mod module_name;`
- Public items: Use `pub` keyword and re-export in main if needed for internal use
**Utilities:**
- Shared helpers: Create `src/utils.rs` or `src/common.rs` for cross-cutting utilities
- General-purpose: Keep in dedicated module, expose via public functions
**UI Components:**
- Ratatui-specific code: Keep in dedicated module like `src/ui.rs` or `src/widgets.rs`
- Separate widget rendering logic from business logic
- Re-export commonly used widgets from central location
## Special Directories
**target/:**
- Purpose: Contains compiled binaries, intermediate build files, and dependencies
- Generated: Yes
- Committed: No
**.git/:**
- Purpose: Git repository metadata
- Generated: Yes
- Committed: Not applicable (part of .git directory)
## Recommended Module Organization (As Project Grows)
Once the codebase expands beyond the current single-file structure:
```
src/
├── main.rs # Binary entry, module declarations, main loop
├── app.rs # Application state and core logic
├── ui/
│ ├── mod.rs # UI module exports
│ ├── widgets.rs # Custom widget definitions
│ └── events.rs # Event handling logic
├── commands.rs # Command/action definitions
├── errors.rs # Error types
└── utils.rs # Utility functions
```
This structure keeps concerns separated while maintaining minimal interdependencies.
---
*Structure analysis: 2026-02-28*
+324
View File
@@ -0,0 +1,324 @@
# Testing Patterns
**Analysis Date:** 2026-02-28
## Test Framework
**Test Runner:**
- Rust built-in test framework (via `cargo test`)
- No external test framework currently integrated
- Can add `tokio` for async testing if needed later
**Assertion Library:**
- Standard `assert!()` and `assert_eq!()` macros from standard library
- Can add `pretty_assertions` crate for better failure output if desired
**Run Commands:**
```bash
cargo test # Run all tests
cargo test -- --nocapture # Run tests with output visible
cargo test -- --test-threads=1 # Run tests sequentially
cargo test --lib # Run only library tests
cargo test --doc # Run doctests
```
**Watch Mode:**
```bash
# Using cargo-watch (install with: cargo install cargo-watch)
cargo watch -x test # Re-run tests on file changes
```
**Coverage:**
```bash
# Using cargo-tarpaulin (install with: cargo install cargo-tarpaulin)
cargo tarpaulin --out Html # Generate HTML coverage report
```
## Test File Organization
**Location - Unit Tests:**
- Co-located with implementation: Tests in same file as source code
- Tests go in submodule at end of source file
**Location - Integration Tests:**
- Separate `tests/` directory at workspace root
- File: `tests/integration_test.rs` or similar
- Each file is compiled as separate crate
**Naming:**
- Unit test modules: `#[cfg(test)] mod tests`
- Integration test files: `integration_test.rs`, `e2e_test.rs`
- Test functions: `test_function_name_description()`
- Unit tests: `tests::test_parses_valid_input()`
**Current Structure:**
```
src/
├── main.rs # Contains #[cfg(test)] mod tests
├── lib.rs # If created, contains library tests
└── ...
tests/
├── integration_test.rs
└── ...
```
## Test Structure
**Suite Organization - Unit Test Pattern:**
```rust
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_function_does_something() {
let input = setup_test_data();
let result = function_under_test(input);
assert_eq!(result, expected_value);
}
}
```
**Suite Organization - Integration Test Pattern:**
```rust
// tests/integration_test.rs
#[test]
fn test_system_integrates_correctly() {
let app = App::new();
let result = app.process_command("help");
assert!(result.is_ok());
}
```
**Patterns:**
- **Setup:** Create test data or fixtures in test function body
- **Teardown:** Not typically needed in Rust; cleanup happens automatically when test scope ends
- **Assertion:** Use `assert!()`, `assert_eq!()`, `assert_ne!()` for conditions
## Mocking
**Framework:** No explicit mocking framework currently integrated
**If mocking becomes necessary:**
- Use `mockito` crate for HTTP mocking
- Use `mockall` crate for trait-based mocking
- Use `proptest` crate for property-based testing
**Current Approach:**
- Manual test doubles: Create simplified implementations of traits for testing
- Dependency injection: Pass different implementations at test time
- Stub data: Return hardcoded test data instead of external calls
**Example of Manual Test Double:**
```rust
#[cfg(test)]
mod tests {
struct MockDataStore {
data: Vec<String>,
}
impl DataStore for MockDataStore {
fn fetch(&self, id: u32) -> Option<String> {
self.data.get(id as usize).cloned()
}
}
#[test]
fn test_with_mock() {
let mock = MockDataStore { data: vec!["test".to_string()] };
let result = process_data(&mock);
assert!(result.is_ok());
}
}
```
**What to Mock:**
- External service calls (network, file I/O)
- Database operations
- Time-dependent behavior
- Hardware-dependent code
**What NOT to Mock:**
- Core business logic
- Standard library functions
- Tested utility functions
- Pure functions
## Fixtures and Factories
**Test Data:**
- Currently: Manual test data created in test functions
- Pattern: Helper functions to build test objects
**Example:**
```rust
#[cfg(test)]
mod tests {
fn create_test_user() -> User {
User {
id: 1,
name: "Test User".to_string(),
email: "test@example.com".to_string(),
}
}
#[test]
fn test_user_creation() {
let user = create_test_user();
assert_eq!(user.name, "Test User");
}
}
```
**Location:**
- Helper functions in same module as tests: `#[cfg(test)] mod tests`
- If many fixtures needed: Create `src/test_utils.rs` (not included in release build via `#[cfg(test)]`)
## Coverage
**Requirements:** Not currently enforced
**To Enable Coverage Tracking:**
```bash
# Using llvm-cov (install with: cargo install cargo-llvm-cov)
cargo llvm-cov # Generate coverage report
cargo llvm-cov --html # HTML report in target/llvm-cov/html
```
**Target for new code:**
- Aim for 80%+ coverage on public APIs
- 100% coverage on critical paths
- Document uncovered code with `#[cfg(test)]` or comments
## Test Types
**Unit Tests:**
- Scope: Single function or small module in isolation
- Approach: Test behavior with various inputs including edge cases
- Location: Same file as implementation in `#[cfg(test)] mod tests`
- Tools: Standard library assertions
**Integration Tests:**
- Scope: Multiple components working together
- Approach: Test workflows and interactions between modules
- Location: `tests/` directory at workspace root
- Tools: Standard library assertions
**Doc Tests:**
- Scope: Examples in `///` doc comments
- Approach: Verify example code actually works
- Location: Documentation strings in source
- Tools: Built-in `cargo test --doc`
**E2E Tests:**
- Currently: Not applicable (TUI application, no external API)
- When applicable: Test complete user workflows end-to-end
**Example Doc Test:**
```rust
/// Calculate the sum of two numbers.
///
/// # Examples
///
/// ```
/// assert_eq!(add(2, 2), 4);
/// ```
pub fn add(a: i32, b: i32) -> i32 {
a + b
}
```
## Common Patterns
**Async Testing:**
- Not currently used (no async in codebase)
- When needed: Use `#[tokio::test]` attribute with `tokio` crate
**Example (future reference):**
```rust
#[tokio::test]
async fn test_async_function() {
let result = async_operation().await;
assert!(result.is_ok());
}
```
**Error Testing:**
- Test both success and failure paths
- Use `.is_err()` or `.is_ok()` to test Result types
- Use `.is_some()` or `.is_none()` to test Option types
**Example:**
```rust
#[test]
fn test_handles_invalid_input() {
let result = parse_config("invalid");
assert!(result.is_err());
}
#[test]
fn test_handles_valid_input() {
let result = parse_config("valid");
assert!(result.is_ok());
}
```
**Property-Based Testing (future):**
If using `proptest`:
```rust
#[test]
fn test_reverse_is_involutive(input in ".*") {
let reversed = reverse(&input);
let double_reversed = reverse(&reversed);
assert_eq!(input, double_reversed);
}
```
## Test Organization Best Practices
**File Structure:**
```
src/
├── main.rs
├── ui.rs # Contains #[cfg(test)] mod tests at bottom
├── handler.rs # Contains #[cfg(test)] mod tests at bottom
└── model.rs # Contains #[cfg(test)] mod tests at bottom
tests/
├── integration_tests.rs # Full-system integration tests
└── fixtures/ # Test data files if needed
```
**Test Module Template:**
```rust
// At end of source file
#[cfg(test)]
mod tests {
use super::*;
// Setup helpers
fn create_test_fixture() -> TestData {
// ...
}
// Tests organized by function
mod function_name_tests {
use super::*;
#[test]
fn test_success_case() {
// ...
}
#[test]
fn test_error_case() {
// ...
}
}
}
```
---
*Testing analysis: 2026-02-28*