From 049af609cc95b969215824c0533eeee924f09377 Mon Sep 17 00:00:00 2001 From: Vijay Janapa Reddi Date: Tue, 30 Sep 2025 07:42:42 -0400 Subject: [PATCH] Fix module test execution pattern with if __name__ == '__main__' guards MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This change ensures tests run immediately when developing modules but don't execute when modules are imported by other modules. Changes: - Protected all test executions with if __name__ == "__main__" blocks - Unit tests run immediately after function definitions during development - Module integration test (test_module()) runs at end when executed directly - Updated module-developer.md with new testing patterns and examples Benefits: - Students see immediate feedback when developing (python module_dev.py runs all tests) - Clean imports: later modules can import earlier ones without triggering tests - Maintains educational flow: tests visible right after implementations - Compatible with nbgrader and notebook environments Tested: - Module 01 runs all tests when executed directly ✓ - Importing Tensor from tensor_dev doesn't run tests ✓ - Cross-module imports work without test interference ✓ --- .claude/agents/module-developer.md | 67 +++++++++++++++-------- modules/01_tensor/tensor_dev.py | 18 ++++-- modules/02_activations/activations_dev.py | 18 ++++-- modules/03_layers/layers_dev.py | 9 ++- modules/04_losses/losses_dev.py | 11 +++- modules/05_autograd/autograd_dev.py | 12 ++-- modules/06_optimizers/optimizers_dev.py | 15 ++++- modules/07_training/training_dev.py | 12 ++-- modules/08_dataloader/dataloader_dev.py | 15 +++-- modules/09_spatial/spatial_dev.py | 12 ++-- 10 files changed, 132 insertions(+), 57 deletions(-) diff --git a/.claude/agents/module-developer.md b/.claude/agents/module-developer.md index 5f6c78ff..89242c64 100644 --- a/.claude/agents/module-developer.md +++ b/.claude/agents/module-developer.md @@ -168,13 +168,25 @@ class Tensor: self.data = np.array(data) # ... rest of implementation -# Test code MUST be protected +def test_unit_tensor_creation(): + """Test function definition""" + print("🔬 Unit Test: Tensor Creation...") + # Test implementation + print("✅ Tensor creation works correctly!") + +# Test execution IMMEDIATELY after function - protected by __main__ guard if __name__ == "__main__": - # Only runs when file is executed directly, NOT on import - test_unit_tensor_creation() - test_unit_arithmetic_operations() - test_unit_matrix_multiplication() - demo_systems_analysis() + test_unit_tensor_creation() # Runs when developing this module + +# Later in the file... +def test_module(): + """Comprehensive module test""" + # Runs all unit tests + pass + +# At the end of file - protected execution +if __name__ == "__main__": + test_module() # Final integration test ``` ### **NEVER Do This (Breaks Imports):** @@ -195,14 +207,25 @@ demo_function() # FORBIDDEN at module level class Tensor: pass -def test_tensor_creation(): +def test_unit_tensor_creation(): # Test implementation pass +# Run test immediately after definition when developing if __name__ == "__main__": - # Safe to run tests here - test_tensor_creation() - print("All tests passed!") + test_unit_tensor_creation() + +def test_unit_arithmetic(): + # Another test + pass + +# Run this test too when developing +if __name__ == "__main__": + test_unit_arithmetic() + +# At the end - comprehensive test +if __name__ == "__main__": + test_module() ``` ## 🚨 **CRITICAL FIRST RULE: ASSESS MODULE COMPLEXITY** @@ -758,7 +781,9 @@ def test_unit_function_name(): # Test implementation with clear assertions print("✅ [Function] works correctly!") -test_unit_function_name() # Run immediately +# Run test immediately when developing this module +if __name__ == "__main__": + test_unit_function_name() ``` @@ -1333,7 +1358,9 @@ def test_unit_some_function(): print("✅ some_function works correctly!") -test_unit_some_function() # Run immediately +# Run test immediately after definition when developing +if __name__ == "__main__": + test_unit_some_function() ``` **Test Explanation Pattern:** @@ -1385,8 +1412,9 @@ def test_module(): print("🎉 ALL TESTS PASSED! Module ready for export.") print("Run: tito module complete [module_number]") -# Call before module summary -test_module() +# Run comprehensive module test when executed directly +if __name__ == "__main__": + test_module() ``` @@ -1470,16 +1498,9 @@ def test_module(): print("🎉 ALL TESTS PASSED! Module ready for export.") -test_module() -``` - -**2. Main Execution Block (Part 8):** -```python -# %% +# Run comprehensive module test when executed directly if __name__ == "__main__": - print("🚀 Running [Module Name] module...") - test_module() # Run the comprehensive test - print("✅ Module validation complete!") + test_module() ``` **3. Then Module Summary:** diff --git a/modules/01_tensor/tensor_dev.py b/modules/01_tensor/tensor_dev.py index 82dfb882..8a5ea370 100644 --- a/modules/01_tensor/tensor_dev.py +++ b/modules/01_tensor/tensor_dev.py @@ -720,7 +720,8 @@ def test_unit_tensor_creation(): print("✅ Tensor creation works correctly!") -# test_unit_tensor_creation() # Moved to main block +if __name__ == "__main__": + test_unit_tensor_creation() # %% [markdown] """ @@ -855,7 +856,8 @@ def test_unit_arithmetic_operations(): print("✅ Arithmetic operations work correctly!") -# test_unit_arithmetic_operations() # Moved to main block +if __name__ == "__main__": + test_unit_arithmetic_operations() # %% [markdown] """ @@ -1004,7 +1006,8 @@ def test_unit_matrix_multiplication(): print("✅ Matrix multiplication works correctly!") -# test_unit_matrix_multiplication() # Moved to main block +if __name__ == "__main__": + test_unit_matrix_multiplication() # %% [markdown] """ @@ -1169,7 +1172,8 @@ def test_unit_shape_manipulation(): print("✅ Shape manipulation works correctly!") -# test_unit_shape_manipulation() # Moved to main block +if __name__ == "__main__": + test_unit_shape_manipulation() # %% [markdown] """ @@ -1328,7 +1332,8 @@ def test_unit_reduction_operations(): print("✅ Reduction operations work correctly!") -# test_unit_reduction_operations() # Moved to main block +if __name__ == "__main__": + test_unit_reduction_operations() # %% [markdown] """ @@ -1637,7 +1642,8 @@ def test_module(): print("Run: tito module complete 01_tensor") # Run comprehensive module test -test_module() +if __name__ == "__main__": + test_module() # %% [markdown] diff --git a/modules/02_activations/activations_dev.py b/modules/02_activations/activations_dev.py index 674edc85..eb13e5b7 100644 --- a/modules/02_activations/activations_dev.py +++ b/modules/02_activations/activations_dev.py @@ -250,7 +250,8 @@ def test_unit_sigmoid(): print("✅ Sigmoid works correctly!") -# test_unit_sigmoid() # Moved to main block +if __name__ == "__main__": + test_unit_sigmoid() # %% [markdown] """ @@ -366,7 +367,8 @@ def test_unit_relu(): print("✅ ReLU works correctly!") -# test_unit_relu() # Moved to main block +if __name__ == "__main__": + test_unit_relu() # %% [markdown] """ @@ -480,7 +482,8 @@ def test_unit_tanh(): print("✅ Tanh works correctly!") -# test_unit_tanh() # Moved to main block +if __name__ == "__main__": + test_unit_tanh() # %% [markdown] """ @@ -603,7 +606,8 @@ def test_unit_gelu(): print("✅ GELU works correctly!") -# test_unit_gelu() # Moved to main block +if __name__ == "__main__": + test_unit_gelu() # %% [markdown] """ @@ -742,7 +746,8 @@ def test_unit_softmax(): print("✅ Softmax works correctly!") -# test_unit_softmax() # Moved to main block +if __name__ == "__main__": + test_unit_softmax() # %% [markdown] """ @@ -884,7 +889,8 @@ def test_module(): print("Run: tito module complete 02") # Run comprehensive module test -test_module() +if __name__ == "__main__": + test_module() # %% [markdown] diff --git a/modules/03_layers/layers_dev.py b/modules/03_layers/layers_dev.py index 2b360b66..e24034b1 100644 --- a/modules/03_layers/layers_dev.py +++ b/modules/03_layers/layers_dev.py @@ -336,7 +336,8 @@ def test_unit_linear_layer(): print("✅ Linear layer works correctly!") -# Test will be run in main block +if __name__ == "__main__": + test_unit_linear_layer() @@ -545,7 +546,8 @@ def test_unit_dropout_layer(): print("✅ Dropout layer works correctly!") -# Test will be run in main block +if __name__ == "__main__": + test_unit_dropout_layer() # %% [markdown] """ @@ -886,7 +888,8 @@ def test_module(): print("Run: tito module complete 03_layers") # Run comprehensive module test -test_module() +if __name__ == "__main__": + test_module() # %% [markdown] diff --git a/modules/04_losses/losses_dev.py b/modules/04_losses/losses_dev.py index f8bdf6d6..28f504a0 100644 --- a/modules/04_losses/losses_dev.py +++ b/modules/04_losses/losses_dev.py @@ -301,6 +301,8 @@ def test_unit_log_softmax(): print("✅ log_softmax works correctly with numerical stability!") +if __name__ == "__main__": + test_unit_log_softmax() # %% [markdown] """ @@ -448,6 +450,8 @@ def test_unit_mse_loss(): print("✅ MSELoss works correctly!") +if __name__ == "__main__": + test_unit_mse_loss() # %% [markdown] """ @@ -627,6 +631,8 @@ def test_unit_cross_entropy_loss(): print("✅ CrossEntropyLoss works correctly!") +if __name__ == "__main__": + test_unit_cross_entropy_loss() # %% [markdown] """ @@ -822,6 +828,8 @@ def test_unit_binary_cross_entropy_loss(): print("✅ BinaryCrossEntropyLoss works correctly!") +if __name__ == "__main__": + test_unit_binary_cross_entropy_loss() # %% [markdown] """ @@ -1301,7 +1309,8 @@ def test_module(): # %% # Run comprehensive module test -test_module() +if __name__ == "__main__": + test_module() # %% [markdown] diff --git a/modules/05_autograd/autograd_dev.py b/modules/05_autograd/autograd_dev.py index 7e8606d6..bb1c2ec1 100644 --- a/modules/05_autograd/autograd_dev.py +++ b/modules/05_autograd/autograd_dev.py @@ -307,7 +307,8 @@ def test_unit_function_base(): print("✅ Function base class works correctly!") -# Test function defined above, will be called in main block +if __name__ == "__main__": + test_unit_function_base() # %% [markdown] """ @@ -725,7 +726,8 @@ def test_unit_operation_functions(): print("✅ Operation functions work correctly!") -# Test function defined above, will be called in main block +if __name__ == "__main__": + test_unit_operation_functions() # %% [markdown] """ @@ -997,7 +999,8 @@ def test_unit_tensor_autograd(): print("✅ Tensor autograd enhancement works correctly!") -# Test function defined above, will be called in main block +if __name__ == "__main__": + test_unit_tensor_autograd() # %% [markdown] """ @@ -1346,7 +1349,8 @@ def test_module(): # %% # Run comprehensive module test -test_module() +if __name__ == "__main__": + test_module() # %% [markdown] diff --git a/modules/06_optimizers/optimizers_dev.py b/modules/06_optimizers/optimizers_dev.py index aae09474..145d98d3 100644 --- a/modules/06_optimizers/optimizers_dev.py +++ b/modules/06_optimizers/optimizers_dev.py @@ -345,6 +345,9 @@ def test_unit_optimizer_base(): print("✅ Base Optimizer works correctly!") +if __name__ == "__main__": + test_unit_optimizer_base() + # %% [markdown] """ ## SGD - Stochastic Gradient Descent @@ -560,6 +563,9 @@ def test_unit_sgd_optimizer(): print("✅ SGD optimizer works correctly!") +if __name__ == "__main__": + test_unit_sgd_optimizer() + # %% [markdown] """ ## Adam - Adaptive Moment Estimation @@ -803,6 +809,9 @@ def test_unit_adam_optimizer(): print("✅ Adam optimizer works correctly!") +if __name__ == "__main__": + test_unit_adam_optimizer() + # %% [markdown] """ ## AdamW - Adam with Decoupled Weight Decay @@ -1039,6 +1048,9 @@ def test_unit_adamw_optimizer(): print("✅ AdamW optimizer works correctly!") +if __name__ == "__main__": + test_unit_adamw_optimizer() + # %% [markdown] """ ## 4. Integration: Bringing It Together @@ -1409,7 +1421,8 @@ def test_module(): # %% # Run comprehensive module test -test_module() +if __name__ == "__main__": + test_module() # %% [markdown] """ diff --git a/modules/07_training/training_dev.py b/modules/07_training/training_dev.py index bf7ccf64..258f24e1 100644 --- a/modules/07_training/training_dev.py +++ b/modules/07_training/training_dev.py @@ -253,7 +253,8 @@ def test_unit_cosine_schedule(): print("✅ CosineSchedule works correctly!") -# test_unit_cosine_schedule() # Moved to main guard +if __name__ == "__main__": + test_unit_cosine_schedule() # %% [markdown] """ @@ -394,7 +395,8 @@ def test_unit_clip_grad_norm(): print("✅ Gradient clipping works correctly!") -# test_unit_clip_grad_norm() # Moved to main guard +if __name__ == "__main__": + test_unit_clip_grad_norm() # %% [markdown] """ @@ -806,7 +808,8 @@ def test_unit_trainer(): print(f"✅ Trainer works correctly! Final loss: {loss:.4f}") -# test_unit_trainer() # Moved to main guard +if __name__ == "__main__": + test_unit_trainer() # %% [markdown] """ @@ -1288,7 +1291,8 @@ def test_module(): # %% nbgrader={"grade": false, "grade_id": "main", "locked": false, "solution": false} # Run comprehensive module test -test_module() +if __name__ == "__main__": + test_module() # %% [markdown] """ diff --git a/modules/08_dataloader/dataloader_dev.py b/modules/08_dataloader/dataloader_dev.py index b66d334f..1d14c2ce 100644 --- a/modules/08_dataloader/dataloader_dev.py +++ b/modules/08_dataloader/dataloader_dev.py @@ -209,7 +209,8 @@ def test_unit_dataset(): print("✅ Dataset interface works correctly!") -# test_unit_dataset() # Moved to main block +if __name__ == "__main__": + test_unit_dataset() # %% [markdown] @@ -388,7 +389,8 @@ def test_unit_tensordataset(): print("✅ TensorDataset works correctly!") -# test_unit_tensordataset() # Moved to main block +if __name__ == "__main__": + test_unit_tensordataset() # %% [markdown] @@ -615,7 +617,8 @@ def test_unit_dataloader(): print("✅ DataLoader works correctly!") -# test_unit_dataloader() # Moved to main block +if __name__ == "__main__": + test_unit_dataloader() # %% [markdown] @@ -828,7 +831,8 @@ def test_unit_download_functions(): print("✅ Download functions work correctly!") -# test_unit_download_functions() # Moved to main block +if __name__ == "__main__": + test_unit_download_functions() # %% [markdown] @@ -1165,7 +1169,8 @@ def test_module(): # %% # Run comprehensive module test -test_module() +if __name__ == "__main__": + test_module() diff --git a/modules/09_spatial/spatial_dev.py b/modules/09_spatial/spatial_dev.py index ab50431a..34b21bba 100644 --- a/modules/09_spatial/spatial_dev.py +++ b/modules/09_spatial/spatial_dev.py @@ -588,7 +588,8 @@ def test_unit_conv2d(): print("✅ Conv2d works correctly!") -# Test will be called in main execution +if __name__ == "__main__": + test_unit_conv2d() # %% [markdown] """ @@ -1127,7 +1128,8 @@ def test_unit_pooling(): print("✅ Pooling operations work correctly!") -# Test will be called in main execution +if __name__ == "__main__": + test_unit_pooling() # %% [markdown] """ @@ -1574,7 +1576,8 @@ def test_unit_simple_cnn(): print("✅ SimpleCNN integration works correctly!") -# Test will be called in main execution +if __name__ == "__main__": + test_unit_simple_cnn() # %% [markdown] """ @@ -1669,7 +1672,8 @@ def test_module(): # %% nbgrader={"grade": false, "grade_id": "main-execution", "solution": true} # Run comprehensive module test -test_module() +if __name__ == "__main__": + test_module() # %% [markdown]