# TinyTorch Testing Architecture ## ๐ŸŽฏ Overview: Two-Tier Testing Strategy TinyTorch uses a **two-tier testing approach** that separates component validation from system integration: 1. **Inline Tests** (`modules/`) - Component validation, unit tests 2. **Integration Tests** (`tests/`) - Inter-module integration, edge cases, system tests This separation follows ML engineering best practices: validate components in isolation, then test how they work together. --- ## ๐Ÿ“‹ Tier 1: Inline Tests (Component Validation) ### **Location**: `modules/XX_modulename/*.py` ### **Purpose**: - โœ… Validate individual components work correctly **in isolation** - โœ… Test single module functionality - โœ… Provide immediate feedback during development - โœ… Educate students about expected behavior - โœ… Fast execution for rapid iteration ### **What Gets Tested**: - Individual class/function correctness - Mathematical operations (forward passes) - Shape transformations - Basic edge cases and error handling - Component-level functionality ### **Test Pattern**: ```python def test_unit_componentname(): """๐Ÿงช Unit Test: Component Name **This is a unit test** - it tests [component] in isolation. """ print("๐Ÿ”ฌ Unit Test: Component...") # Test implementation assert condition, "โœ… Component works" print("โœ… Component test passed") ``` ### **Example**: `modules/01_tensor/tensor.py` - `test_unit_tensor_creation()` - Tests tensor creation - `test_unit_arithmetic_operations()` - Tests +, -, *, / - `test_unit_matrix_multiplication()` - Tests @ operator - `test_unit_shape_manipulation()` - Tests reshape, transpose - `test_unit_reduction_operations()` - Tests sum, mean, max ### **Execution**: ```bash # Run inline tests only tito test 01_tensor --inline-only # Tests run when you execute the module file python modules/01_tensor/tensor.py ``` ### **Key Characteristics**: - โœ… **Fast**: Run during development for immediate feedback - โœ… **Isolated**: No dependencies on other modules - โœ… **Educational**: Shows students what "correct" looks like - โœ… **Component-focused**: Tests one thing at a time --- ## ๐Ÿ“Š Tier 2: Integration Tests (`tests/` Directory) ### **Location**: `tests/` ### **Purpose**: - โœ… Test how **multiple modules work together** - โœ… Validate cross-module dependencies - โœ… Test realistic workflows and use cases - โœ… Ensure system-level correctness - โœ… Catch bugs that unit tests miss - โœ… Test edge cases and corner scenarios - โœ… Validate exported code (`tinytorch/`) works correctly ### **Key Insight**: **Component correctness โ‰  System correctness** A tensor might work perfectly in isolation, but fail when gradients flow through layers โ†’ activations โ†’ losses โ†’ optimizers. Integration tests catch these "seam" bugs. --- ## ๐Ÿ—‚๏ธ Structure of `tests/` Directory ### 1. **Module-Specific Integration Tests** (`tests/XX_modulename/`) **Purpose**: Test that module N works correctly **with all previous modules** (1 through N-1) **Example**: `tests/05_autograd/test_progressive_integration.py` - Tests autograd with Tensor (01), Activations (02), Layers (03), Losses (04) - Validates that gradients flow correctly through the entire stack built so far **Pattern**: Progressive integration ```python # tests/05_autograd/test_progressive_integration.py def test_autograd_with_all_previous_modules(): # Uses real Tensor, real Layers, real Activations, real Losses # Then tests Autograd (05) with all of them x = Tensor([[1.0, 2.0]], requires_grad=True) layer = Linear(2, 3) activation = ReLU() loss_fn = MSELoss() output = activation(layer(x)) loss = loss_fn(output, target) loss.backward() assert x.grad is not None # Gradient flowed through everything! ``` **Why This Matters**: - Catches integration bugs early - Ensures modules don't break previous functionality - Validates the "seams" between modules --- ### 2. **Cross-Module Integration Tests** (`tests/integration/`) **Purpose**: Test **multiple modules working together** in realistic scenarios **Key Files**: - `test_gradient_flow.py` - **CRITICAL**: Validates gradients flow through entire training stack - `test_end_to_end_training.py` - Full training loops - `test_module_compatibility.py` - Module interfaces **Example**: `tests/integration/test_gradient_flow.py` ```python def test_complete_training_stack(): """Test that gradients flow through: Tensor โ†’ Layers โ†’ Activations โ†’ Loss โ†’ Autograd โ†’ Optimizer""" # Uses modules 01, 02, 03, 04, 05, 06, 07 # Validates the entire training pipeline works ``` **Why This Matters**: - Catches bugs that unit tests miss - Validates the "seams" between modules - Ensures training actually works end-to-end - Tests realistic ML workflows --- ### 3. **Edge Cases & Stress Tests** (`tests/05_autograd/`, `tests/debugging/`) **Purpose**: Test **corner cases** and **common pitfalls** **Examples**: - `tests/05_autograd/test_broadcasting.py` - Broadcasting gradient bugs - `tests/05_autograd/test_computation_graph.py` - Graph construction edge cases - `tests/debugging/test_gradient_vanishing.py` - Detect vanishing gradients - `tests/debugging/test_common_mistakes.py` - "Did you forget backward()?" style tests **Philosophy**: When these tests fail, the error message should **teach the student** what went wrong and how to fix it. **Why This Matters**: - Catches numerical stability issues - Tests edge cases that break in production - Pedagogical: teaches debugging skills --- ### 4. **Regression Tests** (`tests/regression/`) **Purpose**: Ensure **previously fixed bugs don't come back** **Pattern**: Each bug gets a test file - `test_issue_20241125_conv_fc_shapes.py` - Tests a specific bug that was fixed - Documents the bug, root cause, fix, and prevention **Why This Matters**: - Prevents regressions - Documents historical bugs - Ensures fixes persist --- ### 5. **Performance Tests** (`tests/performance/`) **Purpose**: Validate **systems performance** characteristics **Examples**: - Memory profiling - Speed benchmarks - Scalability tests **Why This Matters**: - Ensures implementations are efficient - Validates performance characteristics - Catches performance regressions --- ### 6. **System Tests** (`tests/system/`) **Purpose**: Test **entire system workflows** **Examples**: - End-to-end training pipelines - Model export/import - Checkpoint system tests **Why This Matters**: - Validates complete workflows - Tests production scenarios - Ensures system-level correctness --- ### 7. **Checkpoint Tests** (`tests/checkpoints/`) **Purpose**: Validate **milestone capabilities** **Examples**: - `checkpoint_01_foundation.py` - Tensor operations mastered - `checkpoint_05_learning.py` - Autograd working correctly **Why This Matters**: - Validates student progress - Ensures milestones are met - Provides clear success criteria --- ## ๐Ÿ”„ Code Flow: Development โ†’ Export โ†’ Testing ``` โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ DEVELOPMENT WORKFLOW โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ 1. DEVELOP in modules/ โ””โ”€> modules/01_tensor/tensor.py โ”œโ”€> Write code โ”œโ”€> Write inline tests (test_unit_*) โ””โ”€> Run: python modules/01_tensor/tensor.py 2. EXPORT to tinytorch/ โ””โ”€> tito export 01_tensor โ””โ”€> Code exported to tinytorch/core/tensor.py 3. TEST integration โ””โ”€> tests/01_tensor/test_progressive_integration.py โ”œโ”€> Imports from tinytorch.core.tensor (exported code!) โ”œโ”€> Tests module works with previous modules โ””โ”€> Run: pytest tests/01_tensor/ 4. TEST cross-module โ””โ”€> tests/integration/test_gradient_flow.py โ”œโ”€> Imports from tinytorch.* (all exported modules) โ”œโ”€> Tests multiple modules working together โ””โ”€> Run: pytest tests/integration/ ``` --- ## ๐ŸŽฏ Decision Tree: Where Should This Test Go? ``` Is it testing a single component in isolation? โ”œโ”€ YES โ†’ modules/XX_modulename/*.py (inline test_unit_*) โ”‚ โ””โ”€ NO โ†’ Is it testing module N with previous modules? โ”œโ”€ YES โ†’ tests/XX_modulename/test_progressive_integration.py โ”‚ โ””โ”€ NO โ†’ Is it testing multiple modules together? โ”œโ”€ YES โ†’ tests/integration/test_*.py โ”‚ โ””โ”€ NO โ†’ Is it an edge case or stress test? โ”œโ”€ YES โ†’ tests/XX_modulename/test_*_edge_cases.py โ”‚ OR tests/debugging/test_*.py โ”‚ โ””โ”€ NO โ†’ Is it a regression test? โ”œโ”€ YES โ†’ tests/regression/test_issue_*.py โ”‚ โ””โ”€ NO โ†’ Is it a performance test? โ”œโ”€ YES โ†’ tests/performance/test_*.py โ”‚ โ””โ”€ NO โ†’ Is it a system test? โ””โ”€ YES โ†’ tests/system/test_*.py ``` --- ## ๐Ÿ“ Best Practices ### **DO**: โœ… Write inline tests immediately after implementing a component โœ… Test one thing per inline test function โœ… Use descriptive test function names (`test_unit_sigmoid`, not `test1`) โœ… Add integration tests when combining multiple modules โœ… Run inline tests frequently during development โœ… Run full test suite before committing โœ… Test exported code (`tinytorch/`), not development code (`modules/`) โœ… Write tests that catch real bugs you've encountered ### **DON'T**: โŒ Mix inline and integration test concerns โŒ Test implementation details in integration tests โŒ Skip inline tests and jump to integration โŒ Test mocked/fake components (use real ones) โŒ Create dependencies between test files โŒ Test code in `modules/` directly in `tests/` (test `tinytorch/` instead) โŒ Duplicate inline tests in `tests/` directory --- ## ๐Ÿ” Key Distinctions | Aspect | Inline Tests (`modules/`) | Integration Tests (`tests/`) | |--------|-------------------------|----------------------------| | **Location** | `modules/XX_name/*.py` | `tests/XX_name/` or `tests/integration/` | | **Scope** | Single component | Multiple modules | | **Dependencies** | None (isolated) | Previous modules | | **Speed** | Fast | Slower | | **Purpose** | Component correctness | System correctness | | **When to run** | During development | Before commit/export | | **What gets tested** | `modules/` code directly | `tinytorch/` exported code | | **Example** | `test_unit_tensor_creation()` | `test_tensor_with_layers()` | --- ## ๐Ÿš€ Testing Workflow ### For Students: ```bash # 1. Work on module cd modules/01_tensor vim tensor.py # 2. Run inline tests (fast feedback) python tensor.py # or tito test 01_tensor --inline-only # 3. Export to package tito export 01_tensor # 4. Run integration tests (full validation) tito test 01_tensor # or pytest tests/01_tensor/ # 5. Run cross-module tests (ensure nothing broke) pytest tests/integration/ ``` ### For Instructors: ```bash # Comprehensive test suite tito test --comprehensive # Specific module deep dive tito test 05_autograd --detailed # All inline tests only (quick check) tito test --all --inline-only # Critical integration tests pytest tests/integration/test_gradient_flow.py -v ``` --- ## ๐Ÿ’ก Why This Architecture? ### **Separation of Concerns**: - **Inline tests** = "Does this component work?" - **Integration tests** = "Do these components work together?" ### **Educational Value**: - Students learn component testing first - Then learn integration testing - Mirrors professional ML engineering workflows ### **Practical Benefits**: - Fast feedback during development (inline tests) - Comprehensive validation before commit (integration tests) - Catches bugs at the right level - Clear mental model: component vs. system ### **Real-World Alignment**: - Professional ML teams use this pattern - Unit tests for components - Integration tests for pipelines - System tests for workflows --- ## ๐Ÿ“š Summary **Think of `tests/` as the "system validation layer":** 1. **`modules/` inline tests** = "Does my component work?" 2. **`tests/XX_modulename/`** = "Does my module work with previous modules?" 3. **`tests/integration/`** = "Do multiple modules work together?" 4. **`tests/debugging/`** = "Are there edge cases I'm missing?" 5. **`tests/regression/`** = "Did I break something that was working?" 6. **`tests/performance/`** = "Is my implementation efficient?" 7. **`tests/system/`** = "Does the entire system work?" **The key insight**: `tests/` validates that exported code (`tinytorch/`) works correctly in realistic scenarios, catching bugs that isolated unit tests miss. --- **Last Updated**: 2025-01-XX **Test Infrastructure**: Complete (20/20 modules have test directories) **Philosophy**: Component correctness โ‰  System correctness