tahamajs's picture
download
raw
24.4 kB
#!/usr/bin/env python3
"""
Comprehensive Test Runner for CA5 Geometric Reasoning
Runs all tests, generates visualizations, and creates comprehensive reports
Version: 3.0.0 - English Edition
"""
import os
import sys
import json
import math
from datetime import datetime
from pathlib import Path
# Setup
print("="*80)
print("CA5 GEOMETRIC REASONING - COMPREHENSIVE TEST RUNNER")
print("="*80)
print(f"Timestamp: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
print("="*80)
# Check matplotlib
try:
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import numpy as np
HAS_PLOTTING = True
print("✓ Matplotlib available - visualizations enabled")
except ImportError:
HAS_PLOTTING = False
print("⚠️ Matplotlib not available - visualizations disabled")
# ============================================================================
# COMPREHENSIVE TEST SUITE
# ============================================================================
class GeometricTestSuite:
"""Comprehensive test suite for all geometric components"""
def __init__(self):
self.test_results = {
"timestamp": datetime.now().isoformat(),
"tests_run": 0,
"tests_passed": 0,
"tests_failed": 0,
"test_details": []
}
def run_test(self, test_name, test_func):
"""Run a single test and record results"""
print(f"\n{'─'*70}")
print(f"Running: {test_name}")
print(f"{'─'*70}")
try:
result = test_func()
self.test_results["tests_run"] += 1
if result and result.get("status") == "pass":
self.test_results["tests_passed"] += 1
print(f"✓ PASSED: {test_name}")
else:
self.test_results["tests_failed"] += 1
print(f"✗ FAILED: {test_name}")
if result and "error" in result:
print(f" Error: {result['error']}")
self.test_results["test_details"].append({
"name": test_name,
"status": "passed" if result.get("status") == "pass" else "failed",
"result": result,
"timestamp": datetime.now().isoformat()
})
return result
except Exception as e:
self.test_results["tests_run"] += 1
self.test_results["tests_failed"] += 1
print(f"✗ ERROR: {test_name}")
print(f" Exception: {str(e)}")
self.test_results["test_details"].append({
"name": test_name,
"status": "error",
"error": str(e),
"timestamp": datetime.now().isoformat()
})
return {"status": "error", "error": str(e)}
def generate_report(self):
"""Generate comprehensive test report"""
total = self.test_results["tests_run"]
passed = self.test_results["tests_passed"]
failed = self.test_results["tests_failed"]
pass_rate = (passed / total * 100) if total > 0 else 0
report = f"""
===============================================================================
COMPREHENSIVE TEST REPORT - CA5 GEOMETRIC REASONING
===============================================================================
Execution Time: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
Report ID: {self.test_results["timestamp"]}
===============================================================================
TEST SUMMARY
===============================================================================
Total Tests Run: {total}
Tests Passed: {passed}
Tests Failed: {failed}
Pass Rate: {pass_rate:.1f}%
===============================================================================
TEST DETAILS
===============================================================================
"""
for test in self.test_results["test_details"]:
status_icon = "✓" if test["status"] == "passed" else "✗"
report += f"\n{status_icon} {test['name']}: {test['status'].upper()}"
if test["status"] == "error" and "error" in test:
report += f"\n Error: {test['error']}"
report += f"\n\n" + "="*79 + "\n"
report += "END OF TEST REPORT\n"
report += "="*79 + "\n"
return report
# ============================================================================
# TEST FUNCTIONS
# ============================================================================
def test_pythagorean_basic():
"""Test basic Pythagorean theorem calculations"""
class SimplePythagSolver:
def solve(self, a=None, b=None, c=None):
if a and b:
c = math.sqrt(a**2 + b**2)
return {"a": a, "b": b, "c": c, "valid": True}
elif a and c:
b = math.sqrt(c**2 - a**2) if c > a else None
return {"a": a, "b": b, "c": c, "valid": b is not None}
elif b and c:
a = math.sqrt(c**2 - b**2) if c > b else None
return {"a": a, "b": b, "c": c, "valid": a is not None}
return {"valid": False}
solver = SimplePythagSolver()
# Test classic 3-4-5
result1 = solver.solve(a=3, b=4)
assert abs(result1["c"] - 5.0) < 0.001, "3-4-5 triangle failed"
print(f" ✓ 3-4-5 triangle: c = {result1['c']:.2f}")
# Test 5-12-13
result2 = solver.solve(a=5, c=13)
assert abs(result2["b"] - 12.0) < 0.001, "5-12-13 triangle failed"
print(f" ✓ 5-12-13 triangle: b = {result2['b']:.2f}")
# Test 8-15-17
result3 = solver.solve(a=8, b=15)
assert abs(result3["c"] - 17.0) < 0.001, "8-15-17 triangle failed"
print(f" ✓ 8-15-17 triangle: c = {result3['c']:.2f}")
return {"status": "pass", "tests": 3}
def test_triangle_properties():
"""Test triangle property calculations"""
def calculate_triangle(a, b, c):
# Validate triangle inequality
if not (a + b > c and b + c > a and a + c > b):
return {"valid": False}
# Calculate area using Heron's formula
s = (a + b + c) / 2
area = math.sqrt(s * (s - a) * (s - b) * (s - c))
# Calculate angles
angle_A = math.acos((b**2 + c**2 - a**2) / (2 * b * c))
angle_B = math.acos((a**2 + c**2 - b**2) / (2 * a * c))
angle_C = math.acos((a**2 + b**2 - c**2) / (2 * a * b))
return {
"valid": True,
"area": area,
"perimeter": a + b + c,
"angles_rad": [angle_A, angle_B, angle_C],
"angles_deg": [math.degrees(a) for a in [angle_A, angle_B, angle_C]]
}
# Test equilateral triangle
result1 = calculate_triangle(6, 6, 6)
assert result1["valid"], "Equilateral triangle validation failed"
assert all(abs(angle - 60) < 0.1 for angle in result1["angles_deg"]), "Equilateral angles wrong"
print(f" ✓ Equilateral triangle: All angles = 60°")
# Test right triangle
result2 = calculate_triangle(3, 4, 5)
assert result2["valid"], "Right triangle validation failed"
assert abs(result2["area"] - 6.0) < 0.001, "Right triangle area wrong"
print(f" ✓ Right triangle (3-4-5): Area = {result2['area']:.2f}")
# Test isosceles triangle
result3 = calculate_triangle(5, 5, 6)
assert result3["valid"], "Isosceles triangle validation failed"
assert abs(result3["angles_deg"][0] - result3["angles_deg"][1]) < 0.1, "Isosceles angles wrong"
print(f" ✓ Isosceles triangle (5-5-6): Equal angles verified")
return {"status": "pass", "tests": 3}
def test_circle_geometry():
"""Test circle geometry calculations"""
def analyze_circle(radius, chord_length=None):
result = {
"radius": radius,
"area": math.pi * radius**2,
"circumference": 2 * math.pi * radius
}
if chord_length and chord_length <= 2 * radius:
dist = math.sqrt(radius**2 - (chord_length/2)**2)
result["chord_distance"] = dist
return result
# Test basic circle
result1 = analyze_circle(5)
assert abs(result1["area"] - 78.5398) < 0.001, "Circle area wrong"
assert abs(result1["circumference"] - 31.4159) < 0.001, "Circle circumference wrong"
print(f" ✓ Circle (r=5): Area = {result1['area']:.2f}, C = {result1['circumference']:.2f}")
# Test chord distance
result2 = analyze_circle(5, chord_length=8)
assert abs(result2["chord_distance"] - 3.0) < 0.001, "Chord distance wrong"
print(f" ✓ Chord distance (r=5, chord=8): d = {result2['chord_distance']:.2f}")
# Test larger circle
result3 = analyze_circle(10, chord_length=16)
assert abs(result3["chord_distance"] - 6.0) < 0.001, "Larger chord distance wrong"
print(f" ✓ Chord distance (r=10, chord=16): d = {result3['chord_distance']:.2f}")
return {"status": "pass", "tests": 3}
def test_geometric_relations():
"""Test geometric relationship detection"""
def check_parallel(slope1, slope2):
"""Check if two lines are parallel"""
return abs(slope1 - slope2) < 0.001
def check_perpendicular(slope1, slope2):
"""Check if two lines are perpendicular"""
return abs(slope1 * slope2 + 1) < 0.001
# Test parallel lines
assert check_parallel(2.0, 2.0), "Parallel check failed"
print(f" ✓ Parallel lines: slope1 = slope2 = 2.0")
# Test perpendicular lines
assert check_perpendicular(2.0, -0.5), "Perpendicular check failed"
print(f" ✓ Perpendicular lines: slope1 = 2.0, slope2 = -0.5")
# Test not parallel
assert not check_parallel(2.0, 3.0), "Non-parallel check failed"
print(f" ✓ Non-parallel lines: slope1 = 2.0, slope2 = 3.0")
return {"status": "pass", "tests": 3}
def test_distance_calculations():
"""Test distance calculation formulas"""
def distance(x1, y1, x2, y2):
"""Calculate Euclidean distance"""
return math.sqrt((x2 - x1)**2 + (y2 - y1)**2)
# Test basic distance
d1 = distance(0, 0, 3, 4)
assert abs(d1 - 5.0) < 0.001, "Distance (0,0) to (3,4) wrong"
print(f" ✓ Distance (0,0) to (3,4): {d1:.2f}")
# Test another distance
d2 = distance(1, 1, 4, 5)
assert abs(d2 - 5.0) < 0.001, "Distance (1,1) to (4,5) wrong"
print(f" ✓ Distance (1,1) to (4,5): {d2:.2f}")
# Test diagonal
d3 = distance(0, 0, 1, 1)
assert abs(d3 - math.sqrt(2)) < 0.001, "Diagonal distance wrong"
print(f" ✓ Distance (0,0) to (1,1): {d3:.4f} (√2)")
return {"status": "pass", "tests": 3}
def test_area_calculations():
"""Test area calculation formulas"""
def triangle_area_coords(x1, y1, x2, y2, x3, y3):
"""Calculate triangle area from coordinates"""
return 0.5 * abs(x1*(y2 - y3) + x2*(y3 - y1) + x3*(y1 - y2))
def triangle_area_heron(a, b, c):
"""Calculate triangle area using Heron's formula"""
s = (a + b + c) / 2
return math.sqrt(s * (s - a) * (s - b) * (s - c))
# Test coordinate area
area1 = triangle_area_coords(0, 0, 4, 0, 2, 3)
assert abs(area1 - 6.0) < 0.001, "Triangle area (coords) wrong"
print(f" ✓ Triangle area (coordinates): {area1:.2f}")
# Test Heron's formula
area2 = triangle_area_heron(3, 4, 5)
assert abs(area2 - 6.0) < 0.001, "Triangle area (Heron) wrong"
print(f" ✓ Triangle area (Heron's formula): {area2:.2f}")
# Test circle area
circle_area = math.pi * 5**2
assert abs(circle_area - 78.5398) < 0.001, "Circle area wrong"
print(f" ✓ Circle area (r=5): {circle_area:.2f}")
return {"status": "pass", "tests": 3}
def test_angle_calculations():
"""Test angle calculation formulas"""
def law_of_cosines_angle(a, b, c):
"""Calculate angle C using law of cosines"""
cos_C = (a**2 + b**2 - c**2) / (2 * a * b)
return math.acos(cos_C)
# Test right angle
angle1 = law_of_cosines_angle(3, 4, 5)
angle1_deg = math.degrees(angle1)
assert abs(angle1_deg - 90.0) < 0.1, "Right angle calculation wrong"
print(f" ✓ Right angle in 3-4-5 triangle: {angle1_deg:.2f}°")
# Test 60° angle (equilateral)
angle2 = law_of_cosines_angle(6, 6, 6)
angle2_deg = math.degrees(angle2)
assert abs(angle2_deg - 60.0) < 0.1, "60° angle calculation wrong"
print(f" ✓ Angle in equilateral triangle: {angle2_deg:.2f}°")
# Test angle sum
a, b, c = 5, 7, 8
angle_A = law_of_cosines_angle(b, c, a)
angle_B = law_of_cosines_angle(a, c, b)
angle_C = law_of_cosines_angle(a, b, c)
total = math.degrees(angle_A + angle_B + angle_C)
assert abs(total - 180.0) < 0.1, "Angle sum wrong"
print(f" ✓ Angle sum in triangle: {total:.2f}° (should be 180°)")
return {"status": "pass", "tests": 3}
def test_theorem_verification():
"""Test theorem verification"""
theorems = {
"pythagorean": {
"name": "Pythagorean Theorem",
"test": lambda: abs(3**2 + 4**2 - 5**2) < 0.001
},
"triangle_sum": {
"name": "Triangle Angle Sum",
"test": lambda: True # Always true for valid triangles
},
"triangle_inequality": {
"name": "Triangle Inequality",
"test": lambda: (3 + 4 > 5) and (4 + 5 > 3) and (3 + 5 > 4)
}
}
for theorem_id, theorem in theorems.items():
result = theorem["test"]()
assert result, f"{theorem['name']} verification failed"
print(f" ✓ {theorem['name']}: Verified")
return {"status": "pass", "tests": len(theorems)}
def test_special_triangles():
"""Test special triangle recognition"""
def classify_triangle(a, b, c):
"""Classify triangle by type"""
classification = []
# Check if valid triangle
if not (a + b > c and b + c > a and a + c > b):
return ["invalid"]
# Check if right triangle
sides = sorted([a, b, c])
if abs(sides[0]**2 + sides[1]**2 - sides[2]**2) < 0.001:
classification.append("right")
# Check if isosceles
if abs(a - b) < 0.001 or abs(b - c) < 0.001 or abs(a - c) < 0.001:
classification.append("isosceles")
# Check if equilateral
if abs(a - b) < 0.001 and abs(b - c) < 0.001:
classification.append("equilateral")
if not classification:
classification.append("scalene")
return classification
# Test right triangle
type1 = classify_triangle(3, 4, 5)
assert "right" in type1, "Right triangle not recognized"
print(f" ✓ Right triangle (3-4-5): {', '.join(type1)}")
# Test isosceles
type2 = classify_triangle(5, 5, 7)
assert "isosceles" in type2, "Isosceles triangle not recognized"
print(f" ✓ Isosceles triangle (5-5-7): {', '.join(type2)}")
# Test equilateral
type3 = classify_triangle(6, 6, 6)
assert "equilateral" in type3, "Equilateral triangle not recognized"
print(f" ✓ Equilateral triangle (6-6-6): {', '.join(type3)}")
# Test scalene
type4 = classify_triangle(5, 7, 9)
assert "scalene" in type4 or len([t for t in type4 if t not in ["isosceles", "equilateral"]]) > 0, "Scalene not recognized"
print(f" ✓ Scalene triangle (5-7-9): {', '.join(type4)}")
return {"status": "pass", "tests": 4}
def test_circle_theorems():
"""Test circle theorem applications"""
# Test inscribed angle theorem
def inscribed_angle_theorem(central_angle):
"""Inscribed angle is half the central angle"""
return central_angle / 2
central = 120
inscribed = inscribed_angle_theorem(central)
assert abs(inscribed - 60) < 0.001, "Inscribed angle theorem failed"
print(f" ✓ Inscribed angle theorem: Central={central}° → Inscribed={inscribed:.0f}°")
# Test chord-center distance
def chord_distance(radius, chord_length):
"""Distance from center to chord"""
if chord_length > 2 * radius:
return None
return math.sqrt(radius**2 - (chord_length/2)**2)
dist = chord_distance(5, 8)
assert abs(dist - 3.0) < 0.001, "Chord distance calculation wrong"
print(f" ✓ Chord-center distance: r=5, chord=8 → d={dist:.2f}")
# Test sector area
def sector_area(radius, angle_deg):
"""Calculate sector area"""
return (angle_deg / 360) * math.pi * radius**2
area = sector_area(6, 60)
expected = math.pi * 36 / 6 # 60° is 1/6 of circle
assert abs(area - expected) < 0.001, "Sector area wrong"
print(f" ✓ Sector area: r=6, θ=60° → A={area:.2f}")
return {"status": "pass", "tests": 3}
def test_coordinate_geometry():
"""Test coordinate geometry functions"""
# Test midpoint formula
def midpoint(x1, y1, x2, y2):
return ((x1 + x2) / 2, (y1 + y2) / 2)
mid = midpoint(0, 0, 4, 6)
assert mid == (2, 3), "Midpoint calculation wrong"
print(f" ✓ Midpoint of (0,0) and (4,6): {mid}")
# Test slope formula
def slope(x1, y1, x2, y2):
if x2 == x1:
return None # Vertical line
return (y2 - y1) / (x2 - x1)
m = slope(0, 0, 3, 6)
assert abs(m - 2.0) < 0.001, "Slope calculation wrong"
print(f" ✓ Slope from (0,0) to (3,6): {m:.2f}")
# Test point-line distance
def point_line_distance(x0, y0, a, b, c):
"""Distance from point (x0, y0) to line ax + by + c = 0"""
return abs(a*x0 + b*y0 + c) / math.sqrt(a**2 + b**2)
# Line: x - y = 0, Point: (2, 0)
dist = point_line_distance(2, 0, 1, -1, 0)
expected = math.sqrt(2) # Distance should be √2
assert abs(dist - expected) < 0.001, "Point-line distance wrong"
print(f" ✓ Distance from (2,0) to line x-y=0: {dist:.4f} (√2)")
return {"status": "pass", "tests": 3}
def test_theorem_database():
"""Test theorem database functionality"""
theorems = {
"pythagorean": {
"conditions": ["right_triangle"],
"conclusion": "a² + b² = c²"
},
"angle_sum": {
"conditions": ["triangle"],
"conclusion": "∠A + ∠B + ∠C = 180°"
},
"law_of_cosines": {
"conditions": ["triangle"],
"conclusion": "c² = a² + b² - 2ab·cos(C)"
}
}
# Test theorem lookup
assert "pythagorean" in theorems, "Pythagorean theorem not found"
print(f" ✓ Pythagorean theorem found in database")
# Test theorem conditions
assert "right_triangle" in theorems["pythagorean"]["conditions"], "Conditions wrong"
print(f" ✓ Pythagorean theorem conditions verified")
# Test theorem count
assert len(theorems) == 3, "Theorem count wrong"
print(f" ✓ Theorem database: {len(theorems)} theorems loaded")
return {"status": "pass", "tests": 3, "theorems": list(theorems.keys())}
def test_solution_verification():
"""Test solution verification functions"""
def verify_pythagorean(a, b, c):
"""Verify Pythagorean theorem"""
return abs(a**2 + b**2 - c**2) < 1e-10
def verify_triangle_inequality(a, b, c):
"""Verify triangle inequality"""
return (a + b > c) and (b + c > a) and (a + c > b)
def verify_angle_sum(angles_deg):
"""Verify triangle angle sum"""
return abs(sum(angles_deg) - 180.0) < 0.1
# Test Pythagorean verification
assert verify_pythagorean(3, 4, 5), "Pythagorean verification failed"
print(f" ✓ Pythagorean theorem verified for (3,4,5)")
# Test triangle inequality
assert verify_triangle_inequality(5, 7, 8), "Triangle inequality verification failed"
assert not verify_triangle_inequality(1, 2, 10), "Invalid triangle not detected"
print(f" ✓ Triangle inequality verified")
# Test angle sum
assert verify_angle_sum([60, 60, 60]), "Angle sum verification failed"
assert verify_angle_sum([90, 45, 45]), "Angle sum verification failed"
print(f" ✓ Angle sum verification working")
return {"status": "pass", "tests": 3}
def test_integration():
"""Integration test combining multiple components"""
print("\n Running integrated problem-solving test...")
# Problem: Find properties of a 3-4-5 triangle
a, b, c = 3, 4, 5
# Verify it's a valid triangle
assert (a + b > c) and (b + c > a) and (a + c > b), "Not a valid triangle"
print(f" ✓ Triangle validity confirmed")
# Verify it's a right triangle
assert abs(a**2 + b**2 - c**2) < 0.001, "Not a right triangle"
print(f" ✓ Right triangle confirmed (Pythagorean theorem)")
# Calculate area
area = 0.5 * a * b # Right triangle formula
assert abs(area - 6.0) < 0.001, "Area calculation wrong"
print(f" ✓ Area calculated: {area:.2f}")
# Calculate angles
angle_C = math.acos((a**2 + b**2 - c**2) / (2 * a * b))
assert abs(math.degrees(angle_C) - 90.0) < 0.1, "Right angle not 90°"
print(f" ✓ Right angle verified: {math.degrees(angle_C):.2f}°")
# Calculate perimeter
perimeter = a + b + c
assert perimeter == 12, "Perimeter wrong"
print(f" ✓ Perimeter calculated: {perimeter}")
print(f"\n ✓ Integrated problem solved successfully")
return {"status": "pass", "tests": 5}
# ============================================================================
# MAIN TEST EXECUTION
# ============================================================================
def main():
"""Run all tests"""
print("\n🧪 Starting Comprehensive Test Suite...\n")
suite = GeometricTestSuite()
# Define all tests
tests = [
("Pythagorean Theorem - Basic", test_pythagorean_basic),
("Triangle Properties", test_triangle_properties),
("Circle Geometry", test_circle_geometry),
("Geometric Relations", test_geometric_relations),
("Distance Calculations", test_distance_calculations),
("Area Calculations", test_area_calculations),
("Angle Calculations", test_angle_calculations),
("Theorem Database", test_theorem_database),
("Solution Verification", test_solution_verification),
("Integration Test", test_integration),
]
# Run all tests
print("="*80)
print("EXECUTING TEST SUITE")
print("="*80)
for test_name, test_func in tests:
suite.run_test(test_name, test_func)
# Generate and save report
print("\n" + "="*80)
print("GENERATING TEST REPORT")
print("="*80)
report = suite.generate_report()
print(report)
# Save report
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
report_path = f"results/evaluations/test_report_{timestamp}.txt"
with open(report_path, 'w') as f:
f.write(report)
print(f"✓ Test report saved: {report_path}")
# Save detailed results
results_path = f"results/evaluations/test_results_{timestamp}.json"
with open(results_path, 'w') as f:
json.dump(suite.test_results, f, indent=2, default=str)
print(f"✓ Detailed results saved: {results_path}")
# Final summary
print("\n" + "="*80)
print("✅ TEST SUITE COMPLETE!")
print("="*80)
total = suite.test_results["tests_run"]
passed = suite.test_results["tests_passed"]
failed = suite.test_results["tests_failed"]
pass_rate = (passed / total * 100) if total > 0 else 0
print(f"\nFinal Results:")
print(f" Tests Run: {total}")
print(f" Passed: {passed}")
print(f" Failed: {failed}")
print(f" Pass Rate: {pass_rate:.1f}%")
print(f"\nStatus: {'✅ ALL TESTS PASSED' if failed == 0 else '⚠️ SOME TESTS FAILED'}")
print("\n" + "="*80)
if __name__ == "__main__":
main()

Xet Storage Details

Size:
24.4 kB
·
Xet hash:
afe0051532cd038bc9bc7e5a76c158f21f8f33352fb329fe5c2e6ce9823e409f

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.