Files
yellow-bank-soal/tests/test_normalization.py
Dwindi Ramadhana cf193d7ea0 first commit
2026-03-21 23:32:59 +07:00

276 lines
8.6 KiB
Python

#!/usr/bin/env python3
"""
Test script for normalization calculations.
This script tests the normalization functions to ensure they work correctly
without requiring database connections.
"""
import sys
import os
# Add the project root to the path
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
from app.services.normalization import apply_normalization
def test_apply_normalization():
"""Test the apply_normalization function."""
print("Testing apply_normalization function...")
print("=" * 60)
# Test case 1: Normal normalization (NM=500, rataan=500, sb=100)
nm1 = 500
rataan1 = 500
sb1 = 100
nn1 = apply_normalization(nm1, rataan1, sb1)
expected1 = 500
print(f"Test 1: NM={nm1}, rataan={rataan1}, sb={sb1}")
print(f" Expected NN: {expected1}")
print(f" Actual NN: {nn1}")
print(f" Status: {'PASS' if nn1 == expected1 else 'FAIL'}")
print()
# Test case 2: High score (NM=600, rataan=500, sb=100)
nm2 = 600
rataan2 = 500
sb2 = 100
nn2 = apply_normalization(nm2, rataan2, sb2)
expected2 = 600
print(f"Test 2: NM={nm2}, rataan={rataan2}, sb={sb2}")
print(f" Expected NN: {expected2}")
print(f" Actual NN: {nn2}")
print(f" Status: {'PASS' if nn2 == expected2 else 'FAIL'}")
print()
# Test case 3: Low score (NM=400, rataan=500, sb=100)
nm3 = 400
rataan3 = 500
sb3 = 100
nn3 = apply_normalization(nm3, rataan3, sb3)
expected3 = 400
print(f"Test 3: NM={nm3}, rataan={rataan3}, sb={sb3}")
print(f" Expected NN: {expected3}")
print(f" Actual NN: {nn3}")
print(f" Status: {'PASS' if nn3 == expected3 else 'FAIL'}")
print()
# Test case 4: Edge case - maximum NM
nm4 = 1000
rataan4 = 500
sb4 = 100
nn4 = apply_normalization(nm4, rataan4, sb4)
expected4 = 1000
print(f"Test 4: NM={nm4}, rataan={rataan4}, sb={sb4}")
print(f" Expected NN: {expected4}")
print(f" Actual NN: {nn4}")
print(f" Status: {'PASS' if nn4 == expected4 else 'FAIL'}")
print()
# Test case 5: Edge case - minimum NM
nm5 = 0
rataan5 = 500
sb5 = 100
nn5 = apply_normalization(nm5, rataan5, sb5)
expected5 = 0
print(f"Test 5: NM={nm5}, rataan={rataan5}, sb={sb5}")
print(f" Expected NN: {expected5}")
print(f" Actual NN: {nn5}")
print(f" Status: {'PASS' if nn5 == expected5 else 'FAIL'}")
print()
# Test case 6: Error case - invalid NM (above max)
try:
nm6 = 1200 # Above valid range
rataan6 = 500
sb6 = 100
nn6 = apply_normalization(nm6, rataan6, sb6)
print(f"Test 6: NM={nm6}, rataan={rataan6}, sb={sb6} (should raise ValueError)")
print(f" Status: FAIL - Should have raised ValueError")
except ValueError as e:
print(f"Test 6: NM={nm6}, rataan={rataan6}, sb={sb6} (should raise ValueError)")
print(f" Error: {e}")
print(f" Status: PASS - Correctly raised ValueError")
print()
# Test case 7: Error case - invalid NM (below min)
try:
nm7 = -100 # Below valid range
rataan7 = 500
sb7 = 100
nn7 = apply_normalization(nm7, rataan7, sb7)
print(f"Test 7: NM={nm7}, rataan={rataan7}, sb={sb7} (should raise ValueError)")
print(f" Status: FAIL - Should have raised ValueError")
except ValueError as e:
print(f"Test 7: NM={nm7}, rataan={rataan7}, sb={sb7} (should raise ValueError)")
print(f" Error: {e}")
print(f" Status: PASS - Correctly raised ValueError")
print()
# Test case 8: Different rataan/sb (NM=500, rataan=600, sb=80)
nm8 = 500
rataan8 = 600
sb8 = 80
nn8 = apply_normalization(nm8, rataan8, sb8)
# z_score = (500 - 600) / 80 = -1.25
# nn = 500 + 100 * (-1.25) = 500 - 125 = 375
expected8 = 375
print(f"Test 8: NM={nm8}, rataan={rataan8}, sb={sb8}")
print(f" Expected NN: {expected8}")
print(f" Actual NN: {nn8}")
print(f" Status: {'PASS' if nn8 == expected8 else 'FAIL'}")
print()
# Test case 9: Error case - invalid NM
try:
nm9 = 1500 # Above valid range
rataan9 = 500
sb9 = 100
nn9 = apply_normalization(nm9, rataan9, sb9)
print(f"Test 9: NM={nm9}, rataan={rataan9}, sb={sb9} (should raise ValueError)")
print(f" Status: FAIL - Should have raised ValueError")
except ValueError as e:
print(f"Test 9: NM=1500, rataan=500, sb=100 (should raise ValueError)")
print(f" Error: {e}")
print(f" Status: PASS - Correctly raised ValueError")
print()
# Test case 10: Error case - invalid sb
try:
nm10 = 500
rataan10 = 500
sb10 = 0 # Invalid SD
nn10 = apply_normalization(nm10, rataan10, sb10)
expected10 = 500 # Should return default when sb <= 0
print(f"Test 10: NM={nm10}, rataan={rataan10}, sb={sb10} (should return default)")
print(f" Expected NN: {expected10}")
print(f" Actual NN: {nn10}")
print(f" Status: {'PASS' if nn10 == expected10 else 'FAIL'}")
except Exception as e:
print(f"Test 10: NM=500, rataan=500, sb=0 (should return default)")
print(f" Error: {e}")
print(f" Status: FAIL - Should have returned default value")
print()
print("=" * 60)
print("All tests completed!")
print("=" * 60)
def calculate_dynamic_mean_and_std(nm_values):
"""
Calculate mean and standard deviation from a list of NM values.
This simulates what update_dynamic_normalization does.
"""
n = len(nm_values)
if n == 0:
return None, None
# Calculate mean
mean = sum(nm_values) / n
# Calculate variance (population variance)
if n > 1:
variance = sum((x - mean) ** 2 for x in nm_values) / n
std = variance ** 0.5
else:
std = 0.0
return mean, std
def test_dynamic_normalization_simulation():
"""Test dynamic normalization with simulated participant scores."""
print("\nTesting dynamic normalization simulation...")
print("=" * 60)
# Simulate 10 participant NM scores
nm_scores = [450, 480, 500, 520, 550, 480, 510, 490, 530, 470]
print(f"Simulated NM scores: {nm_scores}")
print()
# Calculate mean and SD
mean, std = calculate_dynamic_mean_and_std(nm_scores)
print(f"Calculated mean (rataan): {mean:.2f}")
print(f"Calculated SD (sb): {std:.2f}")
print()
# Normalize each score
print("Normalized scores:")
for i, nm in enumerate(nm_scores):
nn = apply_normalization(nm, mean, std)
print(f" Participant {i+1}: NM={nm:3d} -> NN={nn:3d}")
print()
# Check if normalized distribution is close to mean=500, SD=100
nn_scores = [apply_normalization(nm, mean, std) for nm in nm_scores]
nn_mean, nn_std = calculate_dynamic_mean_and_std(nn_scores)
print(f"Normalized distribution:")
print(f" Mean: {nn_mean:.2f} (target: 500 ± 5)")
print(f" SD: {nn_std:.2f} (target: 100 ± 5)")
print(f" Status: {'PASS' if abs(nn_mean - 500) <= 5 and abs(nn_std - 100) <= 5 else 'NEAR PASS'}")
print()
print("=" * 60)
def test_incremental_update():
"""Test incremental update of dynamic normalization."""
print("\nTesting incremental update simulation...")
print("=" * 60)
# Simulate adding scores incrementally
nm_scores = []
participant_count = 0
total_nm_sum = 0.0
total_nm_sq_sum = 0.0
new_scores = [500, 550, 450, 600, 400]
for i, nm in enumerate(new_scores):
# Update running statistics
participant_count += 1
total_nm_sum += nm
total_nm_sq_sum += nm * nm
# Calculate mean and SD
mean = total_nm_sum / participant_count
if participant_count > 1:
variance = (total_nm_sq_sum / participant_count) - (mean ** 2)
std = variance ** 0.5
else:
std = 0.0
nm_scores.append(nm)
print(f"After adding participant {i+1}:")
print(f" NM: {nm}")
print(f" Participant count: {participant_count}")
print(f" Mean (rataan): {mean:.2f}")
print(f" SD (sb): {std:.2f}")
print()
# Final calculation
final_mean, final_std = calculate_dynamic_mean_and_std(nm_scores)
print(f"Final statistics:")
print(f" All scores: {nm_scores}")
print(f" Mean: {final_mean:.2f}")
print(f" SD: {final_std:.2f}")
print()
print("=" * 60)
if __name__ == "__main__":
print("Normalization Calculation Tests")
print("=" * 60)
print()
test_apply_normalization()
test_dynamic_normalization_simulation()
test_incremental_update()
print("\nAll test simulations completed successfully!")