diff --git a/.DS_Store b/.DS_Store index d33561525..67419bc12 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 000000000..86b58d041 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "python.testing.unittestArgs": ["-v", "-s", "./App", "-p", "test_*.py"], + "python.testing.pytestEnabled": false, + "python.testing.unittestEnabled": true +} diff --git a/App/.DS_Store b/App/.DS_Store index 611dedb96..876c08ef7 100644 Binary files a/App/.DS_Store and b/App/.DS_Store differ diff --git a/App/controllers/coursePlan.py b/App/controllers/coursePlan.py index fe123573d..50ffab72a 100644 --- a/App/controllers/coursePlan.py +++ b/App/controllers/coursePlan.py @@ -17,10 +17,12 @@ isCourseOffered, programCourses_SortedbyRating, programCourses_SortedbyHighestCredits, - get_all_courses_by_planid + get_all_courses_by_planid, + ) + def create_CoursePlan(id): plan = CoursePlan(id) db.session.add(plan) @@ -50,10 +52,12 @@ def addCourseToPlan(Student, courseCode): if plan: createPlanCourse(plan.planId, courseCode) print("Course successfully added to course plan") + return plan else: plan = create_CoursePlan(Student.id) createPlanCourse(plan.planId, courseCode) print("Plan successfully created and Course was successfully added to course plan") + return plan else: print("Course is not offered") else: @@ -63,7 +67,7 @@ def addCourseToPlan(Student, courseCode): def removeCourse(Student, courseCode): plan=getCoursePlan(Student.id) if plan: - deleteCourseFromCoursePlan(plan.planid, courseCode) + deleteCourseFromCoursePlan(plan.planId, courseCode) def getRemainingCourses(completed, required): # Check if either 'completed' or 'required' is None diff --git a/App/controllers/courses.py b/App/controllers/courses.py index 3d285f0f1..a8df358b8 100644 --- a/App/controllers/courses.py +++ b/App/controllers/courses.py @@ -46,6 +46,7 @@ def createCoursesfromFile(file_path): return False print("Courses added successfully.") + return course def get_course_by_courseCode(code): return Course.query.filter_by(courseCode=code).first() diff --git a/App/controllers/student.py b/App/controllers/student.py index 273ebd065..e3248e4b3 100644 --- a/App/controllers/student.py +++ b/App/controllers/student.py @@ -8,6 +8,7 @@ def create_student(student_id, password, name, programname): new_student = Student(student_id, password, name, program.id) db.session.add(new_student) db.session.commit() + return new_student print("Student successfully created") else: print("Program doesn't exist") @@ -15,6 +16,9 @@ def create_student(student_id, password, name, programname): def get_student_by_id(ID): return Student.query.filter_by(id=ID).first() +def get_student(id): + return Student.query.get(id) + def get_all_students(): return Student.query.all() @@ -28,7 +32,7 @@ def get_all_students_json(): def update_student(id, username): student = get_student_by_id(id) if student: - student.username = username + student.name = username db.session.add(student) db.session.commit() return student @@ -41,6 +45,7 @@ def enroll_in_programme(student_id, programme_id): student.program_id = programme_id db.session.add(student) db.session.commit() + return student.program_id def verify_student(username): student=Student.query.filter_by(id=username).first() diff --git a/App/controllers/studentCourseHistory.py b/App/controllers/studentCourseHistory.py index bc98e95f5..1f0001549 100644 --- a/App/controllers/studentCourseHistory.py +++ b/App/controllers/studentCourseHistory.py @@ -10,7 +10,8 @@ def addCoursetoHistory(studentid, code): completed = StudentCourseHistory(studentid, code) db.session.add(completed) db.session.commit() - #print("Course added successfully") + print("Course added successfully") + return else: print("Course doesn't exist") else: diff --git a/App/models/student.py b/App/models/student.py index e53516163..a0445ecb1 100644 --- a/App/models/student.py +++ b/App/models/student.py @@ -2,7 +2,7 @@ from App.database import db class Student(User): - id = db.Column( db.ForeignKey('user.id'), primary_key=True) + id = db.Column(db.String(10), db.ForeignKey('user.id'), primary_key=True) name = db.Column(db.String(50)) program_id = db.Column(db.ForeignKey('program.id')) @@ -16,9 +16,9 @@ def __init__(self, username, password, name, program_id): self.program_id = program_id def get_json(self): - return{ - 'student_id': self.id, + return{'student_id': self.id, 'name': self.name, 'program' : self.program_id + } diff --git a/App/models/studentCourseHistory.py b/App/models/studentCourseHistory.py index e93b623c1..b5d9e8528 100644 --- a/App/models/studentCourseHistory.py +++ b/App/models/studentCourseHistory.py @@ -15,6 +15,6 @@ def __init__(self, id, courseCode): def get_json(self): return{ - 'Program ID:': self.program_id, - 'Course Code: ': self.code + 'Program ID': self.id, #is this suppose to be id or program_id alone + 'Course Code': self.code } \ No newline at end of file diff --git a/App/tests/student.py b/App/tests/student.py new file mode 100644 index 000000000..768033673 --- /dev/null +++ b/App/tests/student.py @@ -0,0 +1,128 @@ +import os +import tempfile +import pytest +import logging +import unittest +from werkzeug.security import check_password_hash, generate_password_hash + +from App.main import create_app +from App.database import db, create_db +from App.models import User, Student, Program, StudentCourseHistory +from App.controllers import ( + create_user, + get_all_users_json, + login, + get_user, + update_user, + create_student, + addCoursetoHistory, + create_program, + create_course, + enroll_in_programme, + get_all_students_json, + update_student, + getCompletedCourses, +) + + +LOGGER = logging.getLogger(__name__) + + +class StudentUnitTest(unittest.TestCase): + + def test_new_student(self): + student = Student("01234", "johnpass", "John Doe", 1) + assert student.name == "John Doe" + + def test_student_toJSON(self): + student = Student("01234", "johnpass", "John Doe", 1) + student_json = student.get_json() + self.assertDictEqual( + {"name": "John Doe", "student_id": "01234", "program": 1}, student_json) + + +class StudentIntegrationTests(unittest.TestCase): + + def setUp(self): + app = create_app( + {'TESTING': True, 'SQLALCHEMY_DATABASE_URI': 'sqlite:///test.db'}) + self.app = app.test_client() + + with app.app_context(): + create_db() + db.create_all() + + def tearDown(self): + with self.app: + db.session.remove() + db.drop_all() + db.engine.dispose() + + def test_create_student(self): + program = create_program("Computer Science Major", 3, 4, 5) + student = create_student( + "01234", "johnpass", "John Doe", program.name) + assert student.name == "John Doe" + + def test_get_all_student_json(self): + program = create_program("Computer Science Major", 3, 4, 5) + create_student("01234", "johnpass", "John Doe", program.name) + users_json = get_all_students_json() + self.assertListEqual( + [{"name": "John Doe", "student_id": "01234", "program": 1}], users_json) + + def test_update_student(self): + program = create_program("Computer Science Major", 3, 4, 5) + create_student("01234", "johnpass", "John Doe", program.name) + student = update_student("01234", "Bill") + assert student.name == "Bill" + + # def test_add_course_to_plan(self): + # course_code = "INFO2605" + # prereqs = [] + # create_course("INFO2605", "Professional Ethics and Law", 3, 4, prereqs) + # addSemesterCourses(course_code) + # program = create_program("Computer Science Major", 3, 4, 5) + # student = create_student( + # "01234", "johnpass", "John Doe", program.name) + # self.assertTrue(addCourseToPlan(student, course_code)) + + # def test_remove_course_from_plan(self): + # course_code = "INFO2605" + # prereqs = [] + # create_course("INFO2605", "Professional Ethics and Law", 3, 4, prereqs) + # addSemesterCourses(course_code) + # program = create_program("Computer Science Major", 3, 4, 5) + # student = create_student( + # "01234", "johnpass", "John Doe", program.name) + # plan = create_CoursePlan(1) + # addSemesterCourses(course_code) + # addCourseToPlan(student, course_code) + # enroll_in_programme(student.id, 1) + # removeCourse(student, course_code) + # course_from_course_plan = getCourseFromCoursePlan(plan.planId, course_code) + # self.assertEqual(course_from_course_plan.planId, 1) + # self.assertEqual(course_from_course_plan.code, "INFO2605") + + def test_enroll_in_programme(self): + program = create_program("Computer Science Major", 3, 4, 5) + student = create_student( + "01234", "johnpass", "John Doe", program.name) + enroll_in_programme(student.id, 1) + assert enroll_in_programme(student.id, 1) == 1 + + # def test_view_course_plan(self): + # course_code = "MATH2250" + # create_course( + # "/Users/jervalthomas/Desktop/Programming /Year 4 Sem 1/COMP 3613/flaskmvc/testData/courseData.csv") + # addSemesterCourses(course_code) + # program = create_program("Computer Science Major", 3, 4, 5) + # student = create_student( + # "816025522", "Password", "Jerval", program.name) + # create_CoursePlan(1) + # addSemesterCourses(course_code) + # addCourseToPlan(student, course_code) + # enroll_in_programme(student.id, 1) + # plan_json = view_course_plan(student) + # self.assertListEqual( + # [{"name": "Jerval", "student_id": "816025522", "program": 1}], plan_json) \ No newline at end of file diff --git a/App/tests/studentCourseHistory.py b/App/tests/studentCourseHistory.py new file mode 100644 index 000000000..abf7e473b --- /dev/null +++ b/App/tests/studentCourseHistory.py @@ -0,0 +1,72 @@ +import os +import tempfile +import pytest +import logging +import unittest +from werkzeug.security import check_password_hash, generate_password_hash + +from App.main import create_app +from App.database import db, create_db +from App.models import User, Student, Program, StudentCourseHistory +from App.controllers import ( + create_user, + get_all_users_json, + login, + get_user, + update_user, + create_student, + addCoursetoHistory, + create_program, + create_course, + enroll_in_programme, + get_all_students_json, + update_student, + getCompletedCourses, +) + + +LOGGER = logging.getLogger(__name__) + +class CourseHistoryUnitTest(unittest.TestCase): + + def test_create_course_history(self): + student_course_history = StudentCourseHistory(123, "INFO2605") + self.assertEqual(student_course_history.studentID, 123) + self.assertEqual(student_course_history.code, "INFO2605") + + def test_course_history_toJSON(self): + student_course_history = StudentCourseHistory(123, 'MATH1115') + result = student_course_history.get_json() + expected_result = {"Program ID": None, "Course Code": "MATH1115"} + self.assertDictEqual(expected_result, result) + + +class CourseHistoryIntegrationTests(unittest.TestCase): + + def setUp(self): + app = create_app( + {'TESTING': True, 'SQLALCHEMY_DATABASE_URI': 'sqlite:///test.db'}) + self.app = app.test_client() + + with app.app_context(): + create_db() + db.create_all() + + def tearDown(self): + with self.app: + db.session.remove() + db.drop_all() + db.engine.dispose() + + def test_add_Course_to_History(self): + program = create_program("Computer Science Major", 3, 4, 5) + student = create_student( + "01234", "johnpass", "John Doe", program.name) + prereqs = [] + create_course("INFO2605", "Professional Ethics and Law", 3, 4, prereqs) + addCoursetoHistory(student.id, "INFO2605") + completed_courses = getCompletedCourses(student.id) + assert len(completed_courses) == 1 + for course_history in completed_courses: + self.assertIsInstance(course_history, StudentCourseHistory) + self.assertEqual(course_history.studentID, student.id) diff --git a/App/tests/test_app.py b/App/tests/test_app.py index ed1fac9b1..154d04b48 100644 --- a/App/tests/test_app.py +++ b/App/tests/test_app.py @@ -1,16 +1,27 @@ -import os, tempfile, pytest, logging, unittest +import os +import tempfile +import pytest +import logging +import unittest from werkzeug.security import check_password_hash, generate_password_hash from App.main import create_app from App.database import db, create_db -from App.models import User +from App.models import User, Student, Program, StudentCourseHistory from App.controllers import ( create_user, get_all_users_json, login, get_user, - get_user_by_username, - update_user + update_user, + create_student, + addCoursetoHistory, + create_program, + create_course, + enroll_in_programme, + get_all_students_json, + update_student, + getCompletedCourses, ) @@ -19,6 +30,8 @@ ''' Unit Tests ''' + + class UserUnitTests(unittest.TestCase): def test_new_user(self): @@ -29,8 +42,8 @@ def test_new_user(self): def test_get_json(self): user = User("bob", "bobpass") user_json = user.get_json() - self.assertDictEqual(user_json, {"id":None, "username":"bob"}) - + self.assertDictEqual(user_json, {"id": None, "username": "bob"}) + def test_hashed_password(self): password = "mypass" hashed = generate_password_hash(password, method='sha256') @@ -42,15 +55,19 @@ def test_check_password(self): user = User("bob", password) assert user.check_password(password) + ''' Integration Tests ''' # This fixture creates an empty database for the test and deletes it after the test # scope="class" would execute the fixture once and resued for all methods in the class + + @pytest.fixture(autouse=True, scope="module") def empty_db(): - app = create_app({'TESTING': True, 'SQLALCHEMY_DATABASE_URI': 'sqlite:///test.db'}) + app = create_app( + {'TESTING': True, 'SQLALCHEMY_DATABASE_URI': 'sqlite:///test.db'}) create_db() yield app.test_client() db.drop_all() @@ -60,6 +77,7 @@ def test_authenticate(): user = create_user("bob", "bobpass") assert login("bob", "bobpass") != None + class UsersIntegrationTests(unittest.TestCase): def test_create_user(self): @@ -68,10 +86,10 @@ def test_create_user(self): def test_get_all_users_json(self): users_json = get_all_users_json() - self.assertListEqual([{"id":1, "username":"bob"}, {"id":2, "username":"rick"}], users_json) + self.assertListEqual([{"id": 1, "username": "bob"}, { + "id": 2, "username": "rick"}], users_json) - # Tests data changes in the database def test_update_user(self): update_user(1, "ronnie") user = get_user(1) - assert user.username == "ronnie" + assert user.username == "ronnie" \ No newline at end of file diff --git a/wsgi.py b/wsgi.py index fa2eab189..dc6f4db3d 100644 --- a/wsgi.py +++ b/wsgi.py @@ -244,6 +244,26 @@ def courses_tests_command(type): else: sys.exit(pytest.main(["App/tests/staff.py"])) +@test.command("student", help="Run Program tests") +@click.argument("type", default="all") +def courses_tests_command(type): + if type == "unit": + sys.exit(pytest.main(["App/tests/student.py::StudentUnitTest"])) + elif type == "int": + sys.exit(pytest.main(["App/tests/student.py::StudentIntegrationTests"])) + else: + sys.exit(pytest.main(["App/tests/student.py"])) + +@test.command("studentCH", help="Run Student Course History tests") +@click.argument("type", default="all") +def courses_tests_command(type): + if type == "unit": + sys.exit(pytest.main(["App/tests/studentCourseHistory.py::CourseHistoryUnitTest"])) + elif type == "int": + sys.exit(pytest.main(["App/tests/studentCourseHistory.py::CourseHistoryIntegrationTests"])) + else: + sys.exit(pytest.main(["App/tests/studentCourseHistory.py"])) + app.cli.add_command(test) #################################################################