add functional tests of students endpoint for coordinator view

This commit is contained in:
dominik24c 2023-01-08 17:15:02 +01:00
parent badbad7cf9
commit 89da56bcef
7 changed files with 361 additions and 59 deletions

View File

@ -4,8 +4,8 @@ from flask_sqlalchemy import get_debug_queries
from ...students.models import Group, Student, YearGroup, ProjectGradeSheet
from ...project_supervisor.models import ProjectSupervisor, YearGroupProjectSupervisors
from ..schemas import GroupSchema, GroupEditSchema, GroupsPaginationSchema, \
GroupCreateSchema, MessageSchema, GroupQuerySchema, DetailGroupSchema
from ..schemas import GroupEditSchema, GroupsPaginationSchema, GroupCreateSchema, MessageSchema, GroupQuerySchema, \
DetailGroupSchema
from ...dependencies import db
from ...base.utils import paginate_models
from ..utils import load_weight_for_project_grade_sheet, calculate_points_for_one_term
@ -47,7 +47,7 @@ def list_groups(year_group_id: int, query: dict) -> dict:
@bp.post("/<int:year_group_id>/")
@bp.input(GroupCreateSchema)
@bp.output(MessageSchema)
@bp.output(MessageSchema, status_code=201)
def create_group(year_group_id: int, data: dict) -> dict:
name = data['name']
students_indexes = data['students']
@ -105,7 +105,7 @@ def create_group(year_group_id: int, data: dict) -> dict:
def detail_group(id: int) -> Group:
group = Group.query.filter_by(id=id).first()
if group is None:
abort(400, f"Group with id {id} doesn't exist!")
abort(404, f"Not found group!")
return group
@ -114,7 +114,7 @@ def detail_group(id: int) -> Group:
def delete_group(id: int) -> dict:
group = Group.query.filter_by(id=id).first()
if group is None:
abort(400, f"Group with id {id} doesn't exist!")
abort(404, f"Not found group!")
group.students = []
db.session.delete(group)
@ -133,7 +133,7 @@ def edit_group(id: int, data: dict) -> dict:
group = group_query.first()
if group is None:
abort(400, f"Group with id {id} doesn't exist!")
abort(404, f"Not found group!")
students = db.session.query(Student).filter(Student.index.in_(data['students'])).all()
group.students = students

View File

@ -82,16 +82,16 @@ def detail_project_supervisor(id: int) -> ProjectSupervisor:
@bp.delete("/<int:id>/")
@bp.output(MessageSchema, status_code=202)
@bp.output(MessageSchema)
def delete_project_supervisor(id: int) -> dict:
project_supervisor = ProjectSupervisor.query.filter_by(id=id).first()
if project_supervisor is None:
abort(400, f"Project Supervisor with id {id} doesn't exist!")
abort(404, "Not found project supervisor!")
count_groups = db.session.query(db.func.count(ProjectSupervisor.id)).join(Group). \
filter(ProjectSupervisor.id == id).group_by(ProjectSupervisor.id)
filter(ProjectSupervisor.id == id).group_by(ProjectSupervisor.id).scalar()
if count_groups is not None:
if count_groups is not None and count_groups > 0:
abort(400, "Project Supervisor has at least one group!")
db.session.delete(project_supervisor)
@ -110,16 +110,16 @@ def edit_project_supervisor(id: int, data: dict) -> dict:
project_supervisor = project_supervisor_query.first()
if project_supervisor is None:
abort(400, f"Project Supervisor with id {id} doesn't exist!")
abort(404, f"Not found project supervisor!")
project_supervisor_query.update(data)
db.session.commit()
return {"message": "Project Supervisor was updated!"}
@bp.post("/<int:id>/year-group/<int:year_group_id>")
@bp.post("/<int:id>/year-group/<int:year_group_id>/")
@bp.input(ProjectSupervisorYearGroupSchema)
@bp.output(MessageSchema)
@bp.output(MessageSchema, status_code=201)
def add_project_supervisor_to_year_group(id: int, year_group_id: int, data: dict) -> dict:
if not data:
abort(400, 'You have passed empty data!')
@ -128,11 +128,11 @@ def add_project_supervisor_to_year_group(id: int, year_group_id: int, data: dict
project_supervisor = ProjectSupervisor.query.filter(ProjectSupervisor.id == id).first()
if project_supervisor is None:
abort(400, f"Project Supervisor with id {id} doesn't exist!")
abort(404, f"Not found project supervisor!")
year_group = YearGroup.query.filter(YearGroup.id == year_group_id).first()
if year_group is None:
abort(400, "Year group doesn't exist!")
abort(404, "Not found year group!")
ygps = YearGroupProjectSupervisors.query.filter(YearGroupProjectSupervisors.project_supervisor_id == id). \
filter(YearGroupProjectSupervisors.year_group_id == year_group_id).first()
@ -146,30 +146,33 @@ def add_project_supervisor_to_year_group(id: int, year_group_id: int, data: dict
return {"message": "Project Supervisor was added to year group!"}
@bp.delete("/<int:id>/year-group/<int:year_group_id>")
@bp.delete("/<int:id>/year-group/<int:year_group_id>/")
@bp.output(MessageSchema)
def delete_project_supervisor_to_year_group(id: int, year_group_id: int) -> dict:
project_supervisor = ProjectSupervisor.query.filter(ProjectSupervisor.id == id). \
filter(YearGroup.id == year_group_id).first()
project_supervisor = ProjectSupervisor.query.filter(ProjectSupervisor.id == id).first()
if project_supervisor is None:
abort(400, "Project Supervisor doesn't exist!")
abort(404, f"Not found project supervisor!")
year_group = YearGroup.query.filter(YearGroup.id == year_group_id).first()
if year_group is None:
abort(404, "Not found year group!")
ygps = YearGroupProjectSupervisors.query.filter(YearGroupProjectSupervisors.project_supervisor_id == id). \
filter(YearGroupProjectSupervisors.year_group_id == year_group_id).first()
db.session.delete(project_supervisor)
db.session.delete(ygps)
db.session.commit()
return {"message": "Project Supervisor was removed from this year group!"}
@bp.put("/<int:id>/year-group/<int:year_group_id>")
@bp.put("/<int:id>/year-group/<int:year_group_id>/")
@bp.input(ProjectSupervisorYearGroupSchema)
@bp.output(MessageSchema)
def update_limit_of_group_for_project_supervisor(id: int, year_group_id: int, data: dict) -> dict:
project_supervisor = ProjectSupervisor.query.filter(ProjectSupervisor.id == id). \
filter(YearGroup.id == year_group_id).first()
project_supervisor = ProjectSupervisor.query.filter(ProjectSupervisor.id == id).first()
if project_supervisor is None:
abort(400, "Project Supervisor doesn't exist!")
abort(404, f"Not found project supervisor!")
year_group = YearGroup.query.filter(YearGroup.id == year_group_id).first()
if year_group is None:
abort(404, "Not found year group!")
ygps = YearGroupProjectSupervisors.query.filter(YearGroupProjectSupervisors.project_supervisor_id == id). \
filter(YearGroupProjectSupervisors.year_group_id == year_group_id)

View File

@ -45,7 +45,7 @@ def list_students(year_group_id: int, query: dict) -> dict:
def detail_student(index: int) -> Student:
student = Student.query.filter_by(index=index).first()
if student is None:
abort(404, f"Student with {index} index doesn't exist!")
abort(404, "Not found student!")
return student
@ -54,7 +54,7 @@ def detail_student(index: int) -> Student:
def delete_student(index: int) -> dict:
student = Student.query.filter_by(index=index).first()
if student is None:
abort(404, f"Student with {index} index doesn't exist!")
abort(404, "Not found student!")
db.session.delete(student)
db.session.commit()
return {"message": "Student was deleted!"}
@ -88,8 +88,10 @@ def create_student(data: dict) -> dict:
del data['year_group_id']
student = Student.query.filter_by(index=index).join(Student.year_groups).first()
if student is None:
# if student is not None:
# abort(400, "Student has already exists!")
if student is None:
dummy_email = f'student{randint(1, 300_000)}@gmail.com'
student = Student(**data, email=dummy_email)
db.session.add(student)
@ -97,7 +99,7 @@ def create_student(data: dict) -> dict:
# add student to the chosen year group
year_group = YearGroup.query.filter(YearGroup.id == yg_id).first()
if year_group is None:
abort(400, "Year group doesn't exist!")
abort(404, "Not found year group!")
if any((year_group.id == yg.id for yg in student.year_groups)):
abort(400, "You are assigned to this year group!")
ygs = YearGroupStudents(student_index=student.index, year_group_id=year_group.id)

View File

@ -1,9 +1,9 @@
from factory import alchemy, Sequence
from factory.faker import Faker
from factory.fuzzy import FuzzyInteger, FuzzyChoice
from factory.fuzzy import FuzzyInteger
from ..app.dependencies import db
from ..app.students.models import Student, Group
from ..app.students.models import Student, Group, YearGroupStudents
from ..app.project_supervisor.models import ProjectSupervisor, YearGroupProjectSupervisors
@ -24,6 +24,7 @@ class YearGroupProjectSupervisorsFactory(alchemy.SQLAlchemyModelFactory):
limit_group = 4
class GroupFactory(alchemy.SQLAlchemyModelFactory):
class Meta:
model = Group
@ -33,15 +34,21 @@ class GroupFactory(alchemy.SQLAlchemyModelFactory):
points_for_first_term = FuzzyInteger(1, 5)
points_for_second_term = FuzzyInteger(1, 5)
#
# class StudentFactory(alchemy.SQLAlchemyModelFactory):
# class Meta:
# model = Student
# sqlalchemy_session = db.session
#
# first_name = Faker('first_name')
# last_name = Faker('last_name')
# email = Faker('email')
# index = Sequence(lambda n: 400_000 + n)
# # group = RelatedFactory(GroupFactory)
# mode = FuzzyChoice([True, False])
class StudentFactory(alchemy.SQLAlchemyModelFactory):
class Meta:
model = Student
sqlalchemy_session = db.session
first_name = Faker('first_name')
last_name = Faker('last_name')
email = Faker('email')
index = Sequence(lambda n: 400_000 + n)
class YearGroupStudentsFactory(alchemy.SQLAlchemyModelFactory):
class Meta:
model = YearGroupStudents
sqlalchemy_session = db.session
# year_group_id
# student_index

View File

@ -1,8 +1,10 @@
from typing import List
from .factory import ProjectSupervisorFactory, YearGroupProjectSupervisorsFactory
from .factory import ProjectSupervisorFactory, YearGroupProjectSupervisorsFactory, \
StudentFactory, YearGroupStudentsFactory
from ..app.dependencies import db
from ..app.project_supervisor.models import YearGroup
from ..app.project_supervisor.models import YearGroup, ProjectSupervisor
from ..app.students.models import Group, Student, YearGroupStudents
from ..app.base.mode import ModeGroups
@ -20,6 +22,39 @@ def create_project_supervisors(yg: YearGroup, amount: int) -> List[ProjectSuperv
db.session.add_all(ps)
db.session.commit()
db.session.add_all(
[YearGroupProjectSupervisorsFactory(limit_group=3, year_group_id=yg.id, project_supervisor_id=p.id) for p in ps])
[YearGroupProjectSupervisorsFactory(limit_group=3, year_group_id=yg.id, project_supervisor_id=p.id) for p in
ps])
db.session.commit()
return ps
def create_dummy_ps(data: dict) -> ProjectSupervisor:
ps = ProjectSupervisor(**data)
db.session.add(ps)
db.session.commit()
return ps
def create_dummy_group(data: dict, project_supervisor_id: int) -> Group:
group = Group(**data, project_supervisor_id=project_supervisor_id)
db.session.add(group)
db.session.commit()
return group
def create_students(yg: YearGroup, amount: int) -> List[StudentFactory]:
students = [StudentFactory() for _ in range(amount)]
db.session.add_all(students)
db.session.commit()
db.session.add_all([YearGroupStudentsFactory(year_group_id=yg.id, student_index=s.index) for s in students])
db.session.commit()
return students
def create_student(data: dict, year_group_id: int) -> Student:
st = Student(**data)
db.session.add(st)
db.session.commit()
db.session.add(YearGroupStudents(year_group_id=year_group_id, student_index=st.index))
db.session.commit()
return st

View File

@ -1,7 +1,7 @@
from ...utils import _test_case_client, _test_case_client_without_response, assert_model_changes
from ...fake_data import create_project_supervisors, create_year_group
from ...fake_data import create_project_supervisors, create_year_group, create_dummy_group, create_dummy_ps
from ....app.dependencies import db
from ....app.project_supervisor.models import ProjectSupervisor
from ....app.project_supervisor.models import YearGroupProjectSupervisors
valid_data = {
'first_name': 'John',
@ -9,12 +9,9 @@ valid_data = {
'email': 'johnsmith@gmail.com'
}
def create_dummy_ps() -> ProjectSupervisor:
ps = ProjectSupervisor(**valid_data)
db.session.add(ps)
db.session.commit()
return ps
year_group_ps_data = {
'limit_group': 3
}
def test_list_project_supervisors(test_app_with_context) -> None:
@ -59,14 +56,14 @@ def test_create_project_supervisors_with_invalid_data(test_app_with_context) ->
def test_create_project_supervisors_if_project_supervisor_has_already_exist(test_app_with_context) -> None:
with test_app_with_context.test_client() as client:
create_dummy_ps()
create_dummy_ps(valid_data)
_test_case_client(client, '/api/coordinator/project_supervisor/', valid_data,
'Project Supervisor has already exists!', 400, method='post', key='error')
def test_detail_project_supervisor(test_app_with_context) -> None:
with test_app_with_context.test_client() as client:
ps = create_dummy_ps()
ps = create_dummy_ps(valid_data)
data = _test_case_client_without_response(client, f'/api/coordinator/project_supervisor/{ps.id}/detail/',
None, 200, method='get')
assert_model_changes(ps, data)
@ -74,5 +71,143 @@ def test_detail_project_supervisor(test_app_with_context) -> None:
def test_detail_project_supervisor_if_project_supervisor_doesnt_exist(test_app_with_context) -> None:
with test_app_with_context.test_client() as client:
_test_case_client(client, f'/api/coordinator/project_supervisor/23/detail/', None,
_test_case_client(client, '/api/coordinator/project_supervisor/23/detail/', None,
'Not found project supervisor!', 404, method='get', key='error')
def test_delete_project_supervisor(test_app_with_context) -> None:
with test_app_with_context.test_client() as client:
ps = create_dummy_ps(valid_data)
_test_case_client(client, f'/api/coordinator/project_supervisor/{ps.id}/', None,
'Project Supervisor was deleted!', 200, method='delete')
def test_delete_project_supervisor_if_project_supervisor_doesnt_exist(test_app_with_context) -> None:
with test_app_with_context.test_client() as client:
_test_case_client(client, '/api/coordinator/project_supervisor/23/', None,
'Not found project supervisor!', 404, method='delete', key='error')
def test_delete_project_supervisor_if_project_supervisor_has_got_at_least_one_group(test_app_with_context) -> None:
with test_app_with_context.test_client() as client:
ps = create_dummy_ps(valid_data)
create_dummy_group({'name': 'new project'}, ps.id)
_test_case_client(client, f'/api/coordinator/project_supervisor/{ps.id}/', None,
'Project Supervisor has at least one group!', 400, method='delete', key='error')
def test_edit_project_supervisor(test_app_with_context) -> None:
new_data = {
'first_name': 'Albert',
'last_name': 'Einstein',
'email': 'albertmc2@gmail.com'
}
with test_app_with_context.test_client() as client:
ps = create_dummy_ps(valid_data)
_test_case_client(client, f'/api/coordinator/project_supervisor/{ps.id}/', new_data,
'Project Supervisor was updated!', 200, method='put')
assert_model_changes(ps, new_data)
def test_edit_project_supervisor_with_invalid_data(test_app_with_context) -> None:
invalid_data = {
'first_name': 'Mark',
'last_name': 'Smith',
'email': 'invalidemail'
}
with test_app_with_context.test_client() as client:
ps = create_dummy_ps(valid_data)
_test_case_client(client, f'/api/coordinator/project_supervisor/{ps.id}/', invalid_data,
'Validation error', 400, method='put')
def test_edit_project_supervisor_if_project_supervisor_doesnt_exist(test_app_with_context) -> None:
with test_app_with_context.test_client() as client:
_test_case_client(client, '/api/coordinator/project_supervisor/2332/', valid_data,
'Not found project supervisor!', 404, method='put', key='error')
def test_add_project_supervisor_to_year_group(test_app_with_context) -> None:
with test_app_with_context.test_client() as client:
ps = create_dummy_ps(valid_data)
yg = create_year_group()
_test_case_client(client, f'/api/coordinator/project_supervisor/{ps.id}/year-group/{yg.id}/',
year_group_ps_data, "Project Supervisor was added to year group!", 201, method='post')
def test_add_project_supervisor_to_year_group_if_project_supervisor_doesnt_exist(test_app_with_context) -> None:
with test_app_with_context.test_client() as client:
yg = create_year_group()
_test_case_client(client, f'/api/coordinator/project_supervisor/454/year-group/{yg.id}/', year_group_ps_data,
"Not found project supervisor!", 404, method='post', key='error')
def test_add_project_supervisor_to_year_group_if_year_group_doesnt_exist(test_app_with_context) -> None:
with test_app_with_context.test_client() as client:
ps = create_dummy_ps(valid_data)
_test_case_client(client, f'/api/coordinator/project_supervisor/{ps.id}/year-group/2/', year_group_ps_data,
"Not found year group!", 404, method='post', key='error')
def test_add_project_supervisor_to_year_group_if_project_supervisor_has_already_assigned_to_year_group(
test_app_with_context) -> None:
with test_app_with_context.test_client() as client:
ps = create_dummy_ps(valid_data)
yg = create_year_group()
ygps = YearGroupProjectSupervisors(project_supervisor_id=ps.id, year_group_id=yg.id, limit_group=2)
db.session.add(ygps)
db.session.commit()
_test_case_client(client, f'/api/coordinator/project_supervisor/{ps.id}/year-group/{yg.id}/',
year_group_ps_data, "Project supervisor is assigned to this year group!", 400, method='post',
key='error')
def test_delete_project_supervisor_to_year_group(test_app_with_context) -> None:
with test_app_with_context.test_client() as client:
ps = create_dummy_ps(valid_data)
yg = create_year_group()
_test_case_client(client, f'/api/coordinator/project_supervisor/{ps.id}/year-group/{yg.id}/', None,
"Project Supervisor was removed from this year group!", 200, method='delete')
assert len(YearGroupProjectSupervisors.query.all()) == 0
def test_delete_project_supervisor_to_year_group_if_project_supervisor_doesnt_exist(test_app_with_context) -> None:
with test_app_with_context.test_client() as client:
yg = create_year_group()
_test_case_client(client, f'/api/coordinator/project_supervisor/5/year-group/{yg.id}/', None,
"Not found project supervisor!", 404, method='delete', key='error')
def test_delete_project_supervisor_to_year_group_if_year_group_doesnt_exist(test_app_with_context) -> None:
with test_app_with_context.test_client() as client:
ps = create_dummy_ps(valid_data)
_test_case_client(client, f'/api/coordinator/project_supervisor/{ps.id}/year-group/23/', None,
"Not found year group!", 404, method='delete', key='error')
def test_update_limit_of_group_for_project_supervisor(test_app_with_context) -> None:
with test_app_with_context.test_client() as client:
ps = create_dummy_ps(valid_data)
yg = create_year_group()
ygps = YearGroupProjectSupervisors(project_supervisor_id=ps.id, year_group_id=yg.id, limit_group=6)
db.session.add(ygps)
db.session.commit()
_test_case_client(client, f'/api/coordinator/project_supervisor/{ps.id}/year-group/{yg.id}/',
year_group_ps_data, "Limit of group was changed!", 200, method='put')
assert_model_changes(ygps, year_group_ps_data)
def test_update_limit_of_group_for_project_supervisor_if_project_supervisor_doesnt_exist(test_app_with_context) -> None:
with test_app_with_context.test_client() as client:
yg = create_year_group()
_test_case_client(client, f'/api/coordinator/project_supervisor/34/year-group/{yg.id}/',
year_group_ps_data, "Not found project supervisor!", 404, method='put', key='error')
def test_update_limit_of_group_for_project_supervisor_if_year_group_doesnt_exist(test_app_with_context) -> None:
with test_app_with_context.test_client() as client:
ps = create_dummy_ps(valid_data)
_test_case_client(client, f'/api/coordinator/project_supervisor/{ps.id}/year-group/34/',
year_group_ps_data, "Not found year group!", 404, method='put', key='error')

View File

@ -0,0 +1,120 @@
import copy
from ...utils import _test_case_client, _test_case_client_without_response, assert_model_changes
from ...fake_data import create_project_supervisors, create_year_group, create_students, create_student
from ....app.dependencies import db
valid_data = {
'first_name': 'Albert',
'last_name': 'Rose',
'index': 234_343,
'email': 'albert@gmail.com'
}
new_data = {
'first_name': 'Martin',
'last_name': 'Green',
'pesel': '93030312894'
}
data_to_create_student = {
**new_data,
'index': 123_456
}
def test_list_students(test_app_with_context) -> None:
with test_app_with_context.test_client() as client:
yg = create_year_group()
create_students(yg, 45)
data = _test_case_client_without_response(client, f'/api/coordinator/students/{yg.id}/?per_page=10', None, 200,
method='get')
assert data.get('max_pages') == 5
assert len(data.get('students')) == 10
def test_detail_student(test_app_with_context) -> None:
with test_app_with_context.test_client() as client:
yg = create_year_group()
st = create_student(valid_data, yg.id)
data = _test_case_client_without_response(client, f'/api/coordinator/students/{st.index}/detail/', None, 200,
method='get')
assert_model_changes(st, data)
def test_detail_student_if_student_doesnt_exist(test_app_with_context) -> None:
with test_app_with_context.test_client() as client:
_test_case_client(client, '/api/coordinator/students/43/detail/', None, 'Not found student!', 404,
method='get', key='error')
def test_delete_student(test_app_with_context) -> None:
with test_app_with_context.test_client() as client:
yg = create_year_group()
st = create_student(valid_data, yg.id)
_test_case_client(client, f'/api/coordinator/students/{st.index}/', None, 'Student was deleted!', 202,
method='delete')
def test_delete_student_if_student_doesnt_exist(test_app_with_context) -> None:
with test_app_with_context.test_client() as client:
_test_case_client(client, '/api/coordinator/students/43/', None, 'Not found student!', 404,
method='delete', key='error')
def test_edit_student(test_app_with_context) -> None:
with test_app_with_context.test_client() as client:
yg = create_year_group()
st = create_student(valid_data, yg.id)
_test_case_client(client, f'/api/coordinator/students/{st.index}/', new_data, 'Student was updated!', 200,
method='put')
def test_edit_student_with_invalid_data(test_app_with_context) -> None:
data = copy.copy(new_data)
data['pesel'] = '43333333333433443'
with test_app_with_context.test_client() as client:
yg = create_year_group()
st = create_student(valid_data, yg.id)
_test_case_client(client, f'/api/coordinator/students/{st.index}/', data, 'Validation error', 400, method='put')
def test_edit_student_if_student_doesnt_exist(test_app_with_context) -> None:
with test_app_with_context.test_client() as client:
_test_case_client(client, '/api/coordinator/students/54/', new_data, 'Not found student!', 404, method='put',
key='error')
def test_create_student(test_app_with_context) -> None:
data = copy.copy(data_to_create_student)
with test_app_with_context.test_client() as client:
yg = create_year_group()
data['year_group_id'] = yg.id
_test_case_client(client, '/api/coordinator/students/', data, 'Student was created!', 200, method='post')
def test_create_student_with_invalid_data(test_app_with_context) -> None:
data = copy.copy(data_to_create_student)
data['pesel'] = '434343434343344'
with test_app_with_context.test_client() as client:
yg = create_year_group()
data['year_group_id'] = yg.id
_test_case_client(client, '/api/coordinator/students/', data, 'Validation error', 400, method='post')
def test_create_student_if_year_group_doesnt_exist(test_app_with_context) -> None:
data = copy.copy(data_to_create_student)
with test_app_with_context.test_client() as client:
data['year_group_id'] = 34
_test_case_client(client, '/api/coordinator/students/', data, 'Not found year group!', 404, method='post',
key='error')
def test_create_student_if_student_has_already_assigned_to_this_group(test_app_with_context) -> None:
data = copy.copy(data_to_create_student)
with test_app_with_context.test_client() as client:
yg = create_year_group()
create_student(data, yg.id)
data['year_group_id'] = yg.id
_test_case_client(client, '/api/coordinator/students/', data, 'You are assigned to this year group!', 400,
method='post', key='error')