Files
TinyTorch/test_educational_integration.py
Vijay Janapa Reddi 45a9cef548 Major reorganization: Remove setup module, renumber all modules, add tito setup command and numeric shortcuts
- Removed 01_setup module (archived to archive/setup_module)
- Renumbered all modules: tensor is now 01, activations is 02, etc.
- Added tito setup command for environment setup and package installation
- Added numeric shortcuts: tito 01, tito 02, etc. for quick module access
- Fixed view command to find dev files correctly
- Updated module dependencies and references
- Improved user experience: immediate ML learning instead of boring setup
2025-09-28 07:02:08 -04:00

422 lines
18 KiB
Python

#!/usr/bin/env python3
"""
Educational Enhancement Integration Tests for TinyTorch
Tests visual teaching elements, systems insights, and pedagogical coherence
"""
import sys
import os
import re
from pathlib import Path
# Add project root to Python path
project_root = Path(__file__).parent
sys.path.insert(0, str(project_root))
class EducationalIntegrationTester:
def __init__(self):
self.results = {}
self.module_paths = [
"/Users/VJ/GitHub/TinyTorch/modules/01_tensor/tensor_dev.py",
"/Users/VJ/GitHub/TinyTorch/modules/02_activations/activations_dev.py",
"/Users/VJ/GitHub/TinyTorch/modules/03_layers/layers_dev.py",
"/Users/VJ/GitHub/TinyTorch/modules/04_losses/losses_dev.py",
"/Users/VJ/GitHub/TinyTorch/modules/05_autograd/autograd_dev.py",
"/Users/VJ/GitHub/TinyTorch/modules/06_optimizers/optimizers_dev.py",
"/Users/VJ/GitHub/TinyTorch/modules/07_training/training_dev.py",
"/Users/VJ/GitHub/TinyTorch/modules/08_spatial/spatial_dev.py",
"/Users/VJ/GitHub/TinyTorch/modules/09_dataloader/dataloader_dev.py",
"/Users/VJ/GitHub/TinyTorch/modules/11_embeddings/embeddings_dev.py",
"/Users/VJ/GitHub/TinyTorch/modules/12_attention/attention_dev.py"
]
def print_section(self, title):
"""Print section header"""
print(f"\n{'='*70}")
print(f" {title}")
print(f"{'='*70}")
def test_all_educational_integration(self):
"""Run all educational integration tests"""
self.print_section("EDUCATIONAL ENHANCEMENT INTEGRATION TESTS")
# Test 1: Visual Teaching Elements Consistency
self.test_visual_teaching_consistency()
# Test 2: Systems Insights Integration
self.test_systems_insights_integration()
# Test 3: Graduated Comment Strategy
self.test_graduated_comment_strategy()
# Test 4: ML Systems Thinking Questions
self.test_ml_systems_thinking_questions()
# Test 5: Pedagogical Flow Consistency
self.test_pedagogical_flow_consistency()
# Test 6: NBGrader Metadata Integration
self.test_nbgrader_metadata_integration()
# Generate report
self.generate_educational_report()
def test_visual_teaching_consistency(self):
"""Test consistency of visual teaching elements across modules"""
print("\n1. Testing Visual Teaching Elements Consistency...")
visual_elements = {
"emojis_in_headers": 0,
"progress_indicators": 0,
"visual_separators": 0,
"step_by_step_numbering": 0,
"memory_diagrams": 0
}
total_modules = 0
for module_path in self.module_paths:
if os.path.exists(module_path):
total_modules += 1
with open(module_path, 'r', encoding='utf-8') as f:
content = f.read()
# Check for visual elements
if re.search(r'#{1,3}.*[🔥🧪🎯🚀💡⚡🔬🎉📈🔍]', content):
visual_elements["emojis_in_headers"] += 1
if "Progress:" in content or "progress:" in content:
visual_elements["progress_indicators"] += 1
if "=" * 20 in content or "-" * 20 in content:
visual_elements["visual_separators"] += 1
if re.search(r'\d+\.\s+\*\*', content): # Numbered bold steps
visual_elements["step_by_step_numbering"] += 1
if "memory" in content.lower() and ("diagram" in content.lower() or "layout" in content.lower()):
visual_elements["memory_diagrams"] += 1
print(f" Total modules analyzed: {total_modules}")
for element, count in visual_elements.items():
percentage = (count / total_modules) * 100 if total_modules > 0 else 0
print(f" {element}: {count}/{total_modules} modules ({percentage:.1f}%)")
self.results["visual_teaching"] = {
"total_modules": total_modules,
"elements": visual_elements,
"average_coverage": sum(visual_elements.values()) / (len(visual_elements) * total_modules) * 100 if total_modules > 0 else 0
}
def test_systems_insights_integration(self):
"""Test systems insights integration across modules"""
print("\n2. Testing Systems Insights Integration...")
systems_concepts = {
"memory_analysis": 0,
"performance_complexity": 0,
"scaling_behavior": 0,
"production_context": 0,
"hardware_implications": 0,
"memory_profiling": 0
}
total_modules = 0
for module_path in self.module_paths:
if os.path.exists(module_path):
total_modules += 1
with open(module_path, 'r', encoding='utf-8') as f:
content = f.read().lower()
# Check for systems concepts
if any(term in content for term in ["memory", "ram", "allocation", "footprint"]):
systems_concepts["memory_analysis"] += 1
if any(term in content for term in ["complexity", "o(n", "performance", "timing"]):
systems_concepts["performance_complexity"] += 1
if any(term in content for term in ["scaling", "bottleneck", "larger", "scaling"]):
systems_concepts["scaling_behavior"] += 1
if any(term in content for term in ["pytorch", "tensorflow", "production", "deployment"]):
systems_concepts["production_context"] += 1
if any(term in content for term in ["gpu", "cpu", "vectorization", "parallel"]):
systems_concepts["hardware_implications"] += 1
if any(term in content for term in ["tracemalloc", "profiling", "memory_info", "psutil"]):
systems_concepts["memory_profiling"] += 1
print(f" Total modules analyzed: {total_modules}")
for concept, count in systems_concepts.items():
percentage = (count / total_modules) * 100 if total_modules > 0 else 0
print(f" {concept}: {count}/{total_modules} modules ({percentage:.1f}%)")
self.results["systems_insights"] = {
"total_modules": total_modules,
"concepts": systems_concepts,
"average_coverage": sum(systems_concepts.values()) / (len(systems_concepts) * total_modules) * 100 if total_modules > 0 else 0
}
def test_graduated_comment_strategy(self):
"""Test graduated comment strategy across modules"""
print("\n3. Testing Graduated Comment Strategy...")
comment_patterns = {
"detailed_explanations": 0,
"inline_comments": 0,
"docstring_examples": 0,
"parameter_explanations": 0,
"step_by_step_comments": 0
}
total_modules = 0
for module_path in self.module_paths:
if os.path.exists(module_path):
total_modules += 1
with open(module_path, 'r', encoding='utf-8') as f:
content = f.read()
# Check for comment patterns
if len(re.findall(r'""".*?"""', content, re.DOTALL)) > 5:
comment_patterns["detailed_explanations"] += 1
if len(re.findall(r'#.*\n', content)) > 20:
comment_patterns["inline_comments"] += 1
if ">>>" in content and "Example" in content:
comment_patterns["docstring_examples"] += 1
if "Args:" in content or "Parameters:" in content:
comment_patterns["parameter_explanations"] += 1
if re.search(r'# Step \d+', content):
comment_patterns["step_by_step_comments"] += 1
print(f" Total modules analyzed: {total_modules}")
for pattern, count in comment_patterns.items():
percentage = (count / total_modules) * 100 if total_modules > 0 else 0
print(f" {pattern}: {count}/{total_modules} modules ({percentage:.1f}%)")
self.results["graduated_comments"] = {
"total_modules": total_modules,
"patterns": comment_patterns,
"average_coverage": sum(comment_patterns.values()) / (len(comment_patterns) * total_modules) * 100 if total_modules > 0 else 0
}
def test_ml_systems_thinking_questions(self):
"""Test ML Systems Thinking questions across modules"""
print("\n4. Testing ML Systems Thinking Questions...")
question_types = {
"memory_performance": 0,
"systems_architecture": 0,
"production_engineering": 0,
"scaling_analysis": 0,
"interactive_questions": 0,
"reflection_questions": 0
}
total_modules = 0
for module_path in self.module_paths:
if os.path.exists(module_path):
total_modules += 1
with open(module_path, 'r', encoding='utf-8') as f:
content = f.read().lower()
# Check for question types
if "memory" in content and "performance" in content and "?" in content:
question_types["memory_performance"] += 1
if "architecture" in content and "?" in content:
question_types["systems_architecture"] += 1
if "production" in content and "?" in content:
question_types["production_engineering"] += 1
if "scaling" in content and "?" in content:
question_types["scaling_analysis"] += 1
if "ml systems thinking" in content:
question_types["interactive_questions"] += 1
if "reflection" in content and "?" in content:
question_types["reflection_questions"] += 1
print(f" Total modules analyzed: {total_modules}")
for qtype, count in question_types.items():
percentage = (count / total_modules) * 100 if total_modules > 0 else 0
print(f" {qtype}: {count}/{total_modules} modules ({percentage:.1f}%)")
self.results["ml_systems_questions"] = {
"total_modules": total_modules,
"question_types": question_types,
"average_coverage": sum(question_types.values()) / (len(question_types) * total_modules) * 100 if total_modules > 0 else 0
}
def test_pedagogical_flow_consistency(self):
"""Test pedagogical flow consistency across modules"""
print("\n5. Testing Pedagogical Flow Consistency...")
flow_elements = {
"learning_objectives": 0,
"build_use_reflect": 0,
"implementation_first": 0,
"immediate_testing": 0,
"systems_analysis": 0,
"module_summary": 0
}
total_modules = 0
for module_path in self.module_paths:
if os.path.exists(module_path):
total_modules += 1
with open(module_path, 'r', encoding='utf-8') as f:
content = f.read()
# Check for flow elements
if "Learning Goals" in content or "learning objectives" in content:
flow_elements["learning_objectives"] += 1
if "Build → Use → Reflect" in content or "build.*use.*reflect" in content.lower():
flow_elements["build_use_reflect"] += 1
if re.search(r'def\s+\w+.*:', content) and re.search(r'test.*:', content):
flow_elements["implementation_first"] += 1
if "Unit Test:" in content:
flow_elements["immediate_testing"] += 1
if "Systems Analysis" in content or "systems analysis" in content.lower():
flow_elements["systems_analysis"] += 1
if "MODULE SUMMARY" in content or "module summary" in content.lower():
flow_elements["module_summary"] += 1
print(f" Total modules analyzed: {total_modules}")
for element, count in flow_elements.items():
percentage = (count / total_modules) * 100 if total_modules > 0 else 0
print(f" {element}: {count}/{total_modules} modules ({percentage:.1f}%)")
self.results["pedagogical_flow"] = {
"total_modules": total_modules,
"elements": flow_elements,
"average_coverage": sum(flow_elements.values()) / (len(flow_elements) * total_modules) * 100 if total_modules > 0 else 0
}
def test_nbgrader_metadata_integration(self):
"""Test NBGrader metadata integration across modules"""
print("\n6. Testing NBGrader Metadata Integration...")
nbgrader_elements = {
"solution_blocks": 0,
"grade_cells": 0,
"locked_cells": 0,
"schema_version_3": 0,
"grade_ids": 0,
"assessment_questions": 0
}
total_modules = 0
for module_path in self.module_paths:
if os.path.exists(module_path):
total_modules += 1
with open(module_path, 'r', encoding='utf-8') as f:
content = f.read()
# Check for NBGrader elements
if "BEGIN SOLUTION" in content and "END SOLUTION" in content:
nbgrader_elements["solution_blocks"] += 1
if '"grade": true' in content:
nbgrader_elements["grade_cells"] += 1
if '"locked": true' in content:
nbgrader_elements["locked_cells"] += 1
if '"schema_version": 3' in content:
nbgrader_elements["schema_version_3"] += 1
if '"grade_id"' in content:
nbgrader_elements["grade_ids"] += 1
if any(term in content for term in ["assessment", "question", "quiz", "grade"]):
nbgrader_elements["assessment_questions"] += 1
print(f" Total modules analyzed: {total_modules}")
for element, count in nbgrader_elements.items():
percentage = (count / total_modules) * 100 if total_modules > 0 else 0
print(f" {element}: {count}/{total_modules} modules ({percentage:.1f}%)")
self.results["nbgrader_metadata"] = {
"total_modules": total_modules,
"elements": nbgrader_elements,
"average_coverage": sum(nbgrader_elements.values()) / (len(nbgrader_elements) * total_modules) * 100 if total_modules > 0 else 0
}
def generate_educational_report(self):
"""Generate comprehensive educational integration report"""
self.print_section("EDUCATIONAL INTEGRATION SUMMARY REPORT")
print(f"\nOVERALL EDUCATIONAL INTEGRATION ANALYSIS:")
print(f"{'='*50}")
for category, data in self.results.items():
print(f"\n{category.upper().replace('_', ' ')}:")
print(f" Coverage: {data['average_coverage']:.1f}%")
print(f" Modules analyzed: {data['total_modules']}")
# Show top elements/concepts
if 'elements' in data:
items = data['elements']
elif 'concepts' in data:
items = data['concepts']
elif 'patterns' in data:
items = data['patterns']
elif 'question_types' in data:
items = data['question_types']
else:
items = {}
if items:
top_items = sorted(items.items(), key=lambda x: x[1], reverse=True)[:3]
print(f" Top elements:")
for item, count in top_items:
percentage = (count / data['total_modules']) * 100 if data['total_modules'] > 0 else 0
print(f" - {item}: {count} modules ({percentage:.1f}%)")
# Overall assessment
avg_coverage = sum(data['average_coverage'] for data in self.results.values()) / len(self.results)
print(f"\n{'='*50}")
print(f"OVERALL EDUCATIONAL INTEGRATION SCORE: {avg_coverage:.1f}%")
if avg_coverage >= 80:
print("🎉 EXCELLENT: Strong educational integration across modules")
elif avg_coverage >= 60:
print("✅ GOOD: Solid educational integration with room for improvement")
elif avg_coverage >= 40:
print("⚠️ MODERATE: Inconsistent educational integration")
else:
print("❌ NEEDS WORK: Educational integration requires significant improvement")
# Specific recommendations
print(f"\nRECOMMENDATIONS:")
for category, data in self.results.items():
if data['average_coverage'] < 60:
print(f" - Improve {category.replace('_', ' ')} consistency across modules")
return avg_coverage >= 60
if __name__ == "__main__":
print("Starting Educational Enhancement Integration Tests...")
tester = EducationalIntegrationTester()
success = tester.test_all_educational_integration()
sys.exit(0 if success else 1)