Spaces:
Sleeping
Sleeping
| """ | |
| Unit tests for ML prediction models | |
| """ | |
| import pytest | |
| import numpy as np | |
| import sys | |
| import os | |
| sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) | |
| from models import ( | |
| TaskCompletionPredictor, | |
| DifficultyClassifier, | |
| StressEstimator, | |
| DurationPredictor, | |
| ProductivityForecaster, | |
| EnsemblePredictor, | |
| ) | |
| class TestTaskCompletionPredictor: | |
| """Tests for TaskCompletionPredictor class""" | |
| def predictor(self): | |
| return TaskCompletionPredictor() | |
| def test_predict_probability_range(self, predictor): | |
| """Test that prediction is within valid range""" | |
| features = { | |
| "complexity_normalized": 0.6, | |
| "pri_attention_demand": 0.5, | |
| "trait_conscientiousness": 0.7, | |
| "completion_rate": 0.7, | |
| } | |
| probability = predictor.predict(features) | |
| assert 0 <= probability <= 1 | |
| def test_high_conscientiousness_improves_probability(self, predictor): | |
| """Test that high conscientiousness increases completion probability""" | |
| base_features = { | |
| "complexity_normalized": 0.6, | |
| "pri_attention_demand": 0.5, | |
| "completion_rate": 0.7, | |
| } | |
| low_consc = {**base_features, "trait_conscientiousness": 0.3} | |
| high_consc = {**base_features, "trait_conscientiousness": 0.9} | |
| prob_low = predictor.predict(low_consc) | |
| prob_high = predictor.predict(high_consc) | |
| assert prob_high > prob_low | |
| def test_high_complexity_reduces_probability(self, predictor): | |
| """Test that high complexity reduces completion probability""" | |
| base_features = { | |
| "pri_attention_demand": 0.5, | |
| "trait_conscientiousness": 0.7, | |
| "completion_rate": 0.7, | |
| } | |
| low_complex = {**base_features, "complexity_normalized": 0.2} | |
| high_complex = {**base_features, "complexity_normalized": 1.0} | |
| prob_low = predictor.predict(low_complex) | |
| prob_high = predictor.predict(high_complex) | |
| assert prob_low > prob_high | |
| class TestDifficultyClassifier: | |
| """Tests for DifficultyClassifier class""" | |
| def classifier(self): | |
| return DifficultyClassifier() | |
| def test_classify_returns_valid_level(self, classifier): | |
| """Test that classification returns valid difficulty level""" | |
| features = {"complexity_normalized": 0.6, "duration_normalized": 0.25} | |
| level, confidence = classifier.classify(features) | |
| assert level in ["EASY", "MODERATE", "HARD"] | |
| assert 0 <= confidence <= 1 | |
| def test_low_complexity_is_easy(self, classifier): | |
| """Test that low complexity tasks are classified as easy""" | |
| features = {"complexity_normalized": 0.1, "duration_normalized": 0.1} | |
| level, _ = classifier.classify(features) | |
| assert level == "EASY" | |
| def test_high_complexity_is_hard(self, classifier): | |
| """Test that high complexity tasks are classified as hard""" | |
| features = {"complexity_normalized": 1.0, "duration_normalized": 1.0, "time_pressure": 1.0} | |
| level, _ = classifier.classify(features) | |
| assert level == "HARD" | |
| class TestStressEstimator: | |
| """Tests for StressEstimator class""" | |
| def estimator(self): | |
| return StressEstimator() | |
| def test_estimate_returns_valid_range(self, estimator): | |
| """Test that stress estimate is within valid range""" | |
| features = { | |
| "complexity_normalized": 0.6, | |
| "pri_urgency_score": 0.5, | |
| "time_pressure": 0.14, | |
| } | |
| stress = estimator.estimate(features) | |
| assert 1 <= stress <= 10 | |
| def test_urgent_task_high_stress(self, estimator): | |
| """Test that urgent tasks have higher stress""" | |
| normal = { | |
| "complexity_normalized": 0.6, | |
| "pri_urgency_score": 0.5, | |
| "time_pressure": 0.1, | |
| } | |
| urgent = { | |
| "complexity_normalized": 0.6, | |
| "pri_urgency_score": 0.9, | |
| "time_pressure": 1.0, | |
| } | |
| stress_normal = estimator.estimate(normal) | |
| stress_urgent = estimator.estimate(urgent) | |
| assert stress_urgent > stress_normal | |
| def test_high_neuroticism_increases_stress(self, estimator): | |
| """Test that high neuroticism increases stress via personality""" | |
| base_features = { | |
| "complexity_normalized": 0.6, | |
| "pri_urgency_score": 0.5, | |
| "time_pressure": 0.3, | |
| } | |
| low_neuro_personality = {"neuroticism": 20} | |
| high_neuro_personality = {"neuroticism": 80} | |
| stress_low = estimator.estimate(base_features, low_neuro_personality) | |
| stress_high = estimator.estimate(base_features, high_neuro_personality) | |
| assert stress_high > stress_low | |
| class TestDurationPredictor: | |
| """Tests for DurationPredictor class""" | |
| def predictor(self): | |
| return DurationPredictor() | |
| def test_predict_returns_positive_duration(self, predictor): | |
| """Test that predicted duration is positive""" | |
| estimated_duration = 60 | |
| difficulty = "MODERATE" | |
| category = "WORK" | |
| duration = predictor.predict(estimated_duration, difficulty, category) | |
| assert duration > 0 | |
| def test_complex_tasks_take_longer(self, predictor): | |
| """Test that harder tasks have longer predicted duration""" | |
| estimated_duration = 30 | |
| category = "WORK" | |
| duration_easy = predictor.predict(estimated_duration, "EASY", category) | |
| duration_hard = predictor.predict(estimated_duration, "HARD", category) | |
| assert duration_hard > duration_easy | |
| class TestProductivityForecaster: | |
| """Tests for ProductivityForecaster class""" | |
| def forecaster(self): | |
| return ProductivityForecaster() | |
| def test_forecast_returns_correct_days(self, forecaster): | |
| """Test that forecast returns correct number of days""" | |
| historical_data = { | |
| "prod_monday": 70, | |
| "prod_tuesday": 75, | |
| } | |
| forecast = forecaster.forecast(historical_data, days=7) | |
| assert len(forecast) == 7 | |
| def test_forecast_valid_productivity_range(self, forecaster): | |
| """Test that forecasted productivity is valid""" | |
| historical_data = {} | |
| forecast = forecaster.forecast(historical_data, days=5) | |
| for day in forecast: | |
| assert 0 <= day["predicted_productivity"] <= 100 | |
| assert day["recommended_tasks"] >= 0 | |
| class TestEnsemblePredictor: | |
| """Tests for EnsemblePredictor class""" | |
| def ensemble(self): | |
| return EnsemblePredictor() | |
| def test_predict_returns_all_metrics(self, ensemble): | |
| """Test that ensemble returns all required metrics""" | |
| features = { | |
| "complexity_normalized": 0.6, | |
| "pri_attention_demand": 0.5, | |
| "trait_conscientiousness": 0.7, | |
| } | |
| task_data = { | |
| "estimated_duration": 60, | |
| "category": "WORK", | |
| } | |
| result = ensemble.predict(features, task_data) | |
| assert "completion_probability" in result | |
| assert "difficulty_level" in result | |
| assert "stress_level" in result | |
| assert "predicted_duration" in result | |
| def test_predictions_are_consistent(self, ensemble): | |
| """Test that predictions are consistent for same input""" | |
| features = { | |
| "complexity_normalized": 0.6, | |
| "pri_attention_demand": 0.5, | |
| "trait_conscientiousness": 0.7, | |
| } | |
| task_data = { | |
| "estimated_duration": 60, | |
| "category": "WORK", | |
| } | |
| result1 = ensemble.predict(features, task_data) | |
| result2 = ensemble.predict(features, task_data) | |
| assert result1["completion_probability"] == result2["completion_probability"] | |
| assert result1["difficulty_level"] == result2["difficulty_level"] | |
| if __name__ == "__main__": | |
| pytest.main([__file__, "-v"]) | |