From d15b50298f600c8c5e3a2b4202c2799f1b9ffca6 Mon Sep 17 00:00:00 2001 From: Rathore-tech-code Date: Sun, 7 Dec 2025 21:19:28 +0530 Subject: [PATCH 1/3] Add unit tests for StudentManager --- tests/test_student_manager.py | 67 +++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 tests/test_student_manager.py diff --git a/tests/test_student_manager.py b/tests/test_student_manager.py new file mode 100644 index 0000000..fac074b --- /dev/null +++ b/tests/test_student_manager.py @@ -0,0 +1,67 @@ +import pytest +from student_manager import StudentManager +from datetime import datetime, timedelta + +def test_add_assignment(): + sm = StudentManager() + deadline = datetime.now() + timedelta(days=5) + + assignment = sm.add_assignment("Math HW", deadline, "Math") + + assert assignment in sm.assignments + assert assignment['title'] == "Math HW" + assert assignment['completed'] is False + +def test_mark_completed(): + sm = StudentManager() + deadline = datetime.now() + timedelta(days=5) + + sm.add_assignment("Physics HW", deadline) + result = sm.mark_completed("Physics HW") + + assert result is True + assert sm.assignments[0]['completed'] is True + + +def test_calculate_gpa(): + sm = StudentManager() + + sm.add_grade("Math", 90) + sm.add_grade("English", 80) + + assert sm.calculate_gpa() == 85 # average + +def test_invalid_grade(): + sm = StudentManager() + + with pytest.raises(ValueError): + sm.add_grade("Math", 120) # invalid + + +def test_statistics(): + sm = StudentManager() + deadline = datetime.now() + timedelta(days=5) + + sm.add_assignment("Chem", deadline) + sm.add_assignment("Bio", deadline) + sm.mark_completed("Chem") + sm.add_grade("Chem", 90) + + stats = sm.get_statistics() + + assert stats['total_assignments'] == 2 + assert stats['completed'] == 1 + assert stats['pending'] == 1 + assert stats['gpa'] == 90 + + +def test_upcoming_deadlines(): + sm = StudentManager() + deadline = datetime.now() + timedelta(days=3) + + sm.add_assignment("Task1", deadline) + + upcoming = sm.get_upcoming_deadlines(days=7) + + assert len(upcoming) == 1 + assert upcoming[0]['title'] == "Task1" From a2861b0056a9e647e1760a968472546ce5b8a9ed Mon Sep 17 00:00:00 2001 From: Rathore-tech-code Date: Mon, 8 Dec 2025 12:42:00 +0530 Subject: [PATCH 2/3] Improve StudentManager tests with fixtures, edge cases and better structure --- tests/test_student_manager.py | 182 +++++++++++++++++++++++++--------- 1 file changed, 136 insertions(+), 46 deletions(-) diff --git a/tests/test_student_manager.py b/tests/test_student_manager.py index fac074b..566e011 100644 --- a/tests/test_student_manager.py +++ b/tests/test_student_manager.py @@ -1,67 +1,157 @@ import pytest -from student_manager import StudentManager from datetime import datetime, timedelta +from student_manager import StudentManager + + +@pytest.fixture +def student_manager(): + """Provides a fresh StudentManager for each test.""" + return StudentManager() + + +class TestAssignments: + def test_add_assignment_basic(self, student_manager): + deadline = datetime.now() + timedelta(days=5) + + assignment = student_manager.add_assignment("Math HW", deadline, "Math") + + assert assignment in student_manager.assignments + assert assignment["title"] == "Math HW" + assert assignment["subject"] == "Math" + assert assignment["completed"] is False + + def test_add_assignment_with_empty_title(self, student_manager): + deadline = datetime.now() + timedelta(days=3) + + assignment = student_manager.add_assignment("", deadline, "Misc") + + # For now we just ensure it is added; behavior can be refined later. + assert assignment in student_manager.assignments + assert assignment["title"] == "" + + def test_list_assignments_empty_collection(self, student_manager): + # No assignments added yet + assert student_manager.list_assignments() == [] + assert student_manager.list_assignments(show_completed=True) == [] + + def test_list_assignments_shows_only_pending_by_default(self, student_manager): + deadline = datetime.now() + timedelta(days=5) + + student_manager.add_assignment("A1", deadline) + student_manager.add_assignment("A2", deadline) + student_manager.mark_completed("A1") + + pending = student_manager.list_assignments() + all_assignments = student_manager.list_assignments(show_completed=True) + + assert len(all_assignments) == 2 + assert len(pending) == 1 + assert pending[0]["title"] == "A2" + + def test_mark_completed_existing_assignment(self, student_manager): + deadline = datetime.now() + timedelta(days=5) + + student_manager.add_assignment("Physics HW", deadline) + result = student_manager.mark_completed("Physics HW") + + assert result is True + assert student_manager.assignments[0]["completed"] is True + + def test_mark_completed_non_existent_assignment(self, student_manager): + deadline = datetime.now() + timedelta(days=5) + + student_manager.add_assignment("Chem HW", deadline) + result = student_manager.mark_completed("Bio HW") # not present + + assert result is False # function should indicate failure + + def test_mark_completed_with_duplicate_titles(self, student_manager): + deadline = datetime.now() + timedelta(days=5) + + student_manager.add_assignment("Project", deadline) + student_manager.add_assignment("Project", deadline) + + result = student_manager.mark_completed("Project") + + assert result is True + # At least one of them should be completed + completed_count = sum(1 for a in student_manager.assignments if a["completed"]) + assert completed_count >= 1 + + +class TestUpcomingDeadlines: + def test_upcoming_deadlines_future_assignment(self, student_manager): + future_deadline = datetime.now() + timedelta(days=3) + + student_manager.add_assignment("Task1", future_deadline) + + upcoming = student_manager.get_upcoming_deadlines(days=7) + + assert len(upcoming) == 1 + assert upcoming[0]["title"] == "Task1" + # days_remaining and priority are added by get_upcoming_deadlines + assert "days_remaining" in upcoming[0] + assert "priority" in upcoming[0] -def test_add_assignment(): - sm = StudentManager() - deadline = datetime.now() + timedelta(days=5) - - assignment = sm.add_assignment("Math HW", deadline, "Math") + def test_upcoming_deadlines_excludes_past_deadline(self, student_manager): + past_deadline = datetime.now() - timedelta(days=2) - assert assignment in sm.assignments - assert assignment['title'] == "Math HW" - assert assignment['completed'] is False + student_manager.add_assignment("Old Task", past_deadline) -def test_mark_completed(): - sm = StudentManager() - deadline = datetime.now() + timedelta(days=5) - - sm.add_assignment("Physics HW", deadline) - result = sm.mark_completed("Physics HW") + upcoming = student_manager.get_upcoming_deadlines(days=7) - assert result is True - assert sm.assignments[0]['completed'] is True + # Past tasks should not appear in upcoming deadlines + assert upcoming == [] -def test_calculate_gpa(): - sm = StudentManager() +class TestGradesAndGPA: + def test_add_grade_valid(self, student_manager): + student_manager.add_grade("Math", 90) - sm.add_grade("Math", 90) - sm.add_grade("English", 80) + assert len(student_manager.grades) == 1 + assert student_manager.grades[0]["subject"] == "Math" + assert student_manager.grades[0]["grade"] == 90 - assert sm.calculate_gpa() == 85 # average + def test_add_grade_negative_value(self, student_manager): + with pytest.raises(ValueError): + student_manager.add_grade("Math", -10) -def test_invalid_grade(): - sm = StudentManager() - - with pytest.raises(ValueError): - sm.add_grade("Math", 120) # invalid + def test_add_grade_above_max_value(self, student_manager): + with pytest.raises(ValueError): + student_manager.add_grade("Math", 150) + def test_calculate_gpa_with_multiple_grades(self, student_manager): + student_manager.add_grade("Math", 80) + student_manager.add_grade("English", 90) + student_manager.add_grade("Science", 70) -def test_statistics(): - sm = StudentManager() - deadline = datetime.now() + timedelta(days=5) + # Average is (80 + 90 + 70) / 3 = 80 + assert student_manager.calculate_gpa() == pytest.approx(80.0) - sm.add_assignment("Chem", deadline) - sm.add_assignment("Bio", deadline) - sm.mark_completed("Chem") - sm.add_grade("Chem", 90) + def test_calculate_gpa_with_no_grades(self, student_manager): + assert student_manager.calculate_gpa() == 0.0 - stats = sm.get_statistics() - assert stats['total_assignments'] == 2 - assert stats['completed'] == 1 - assert stats['pending'] == 1 - assert stats['gpa'] == 90 +class TestStatistics: + def test_statistics_with_no_data(self, student_manager): + stats = student_manager.get_statistics() + assert stats["total_assignments"] == 0 + assert stats["completed"] == 0 + assert stats["pending"] == 0 + assert stats["gpa"] == 0.0 -def test_upcoming_deadlines(): - sm = StudentManager() - deadline = datetime.now() + timedelta(days=3) + def test_statistics_with_assignments_and_grades(self, student_manager): + deadline = datetime.now() + timedelta(days=5) - sm.add_assignment("Task1", deadline) + student_manager.add_assignment("Chem", deadline) + student_manager.add_assignment("Bio", deadline) + student_manager.mark_completed("Chem") + student_manager.add_grade("Chem", 90) - upcoming = sm.get_upcoming_deadlines(days=7) + stats = student_manager.get_statistics() - assert len(upcoming) == 1 - assert upcoming[0]['title'] == "Task1" + assert stats["total_assignments"] == 2 + assert stats["completed"] == 1 + assert stats["pending"] == 1 + assert stats["gpa"] == 90 From 358a597b9c82cc788cb09e6354868f8f39f0bebb Mon Sep 17 00:00:00 2001 From: Rathore-tech-code Date: Tue, 9 Dec 2025 10:02:29 +0530 Subject: [PATCH 3/3] Add tests for null title and past deadline assignments --- tests/test_student_manager.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/tests/test_student_manager.py b/tests/test_student_manager.py index 566e011..e7b8e4b 100644 --- a/tests/test_student_manager.py +++ b/tests/test_student_manager.py @@ -29,6 +29,28 @@ def test_add_assignment_with_empty_title(self, student_manager): assert assignment in student_manager.assignments assert assignment["title"] == "" + def test_add_assignment_with_null_title(self, student_manager): + """Assignment with None as title should still be stored.""" + deadline = datetime.now() + timedelta(days=3) + + assignment = student_manager.add_assignment(None, deadline, "Misc") + + assert assignment in student_manager.assignments + assert assignment["title"] is None + assert assignment["completed"] is False + + def test_add_assignment_with_past_deadline(self, student_manager): + """Assignments in the past should still be tracked.""" + past_deadline = datetime.now() - timedelta(days=1) + + assignment = student_manager.add_assignment( + "Old HW", past_deadline, "History" + ) + + assert assignment in student_manager.assignments + assert assignment["deadline"] == past_deadline + assert assignment["completed"] is False + def test_list_assignments_empty_collection(self, student_manager): # No assignments added yet assert student_manager.list_assignments() == []