Basic anatomy user integration testing

This commit is contained in:
Ross
2022-12-12 16:16:53 +00:00
parent 66f512f455
commit 300e74ec94
7 changed files with 263 additions and 132 deletions
@@ -23,7 +23,7 @@
<pre>{{ans}}</pre> <pre>{{ans}}</pre>
</span> </span>
{% if exam.publish_results %} {% if exam.publish_results %}
{{score}} <span class="answer-score">{{score}}</span>
{% endif %} {% endif %}
</span> </span>
<span class="view-question-link" data-qn={{forloop.counter0}}>View</span> <span class="view-question-link" data-qn={{forloop.counter0}}>View</span>
+191 -70
View File
@@ -15,36 +15,37 @@ from bs4 import BeautifulSoup
from anatomy.views import GenericExamViews as AnatomyExamViews from anatomy.views import GenericExamViews as AnatomyExamViews
from anatomy.models import Answer, Exam, AnatomyQuestion as Question, QuestionType, Structure from anatomy.models import (
Answer,
Exam,
AnatomyQuestion as Question,
QuestionType,
Structure,
)
from generic.models import CidUser, CidUserGroup from generic.models import CidUser, CidUserGroup, UserUserGroup
from rad.test_helpers import AssertNotFound, create_cid_user_and_groups
from django.contrib.auth.models import User
APP_NAME = "anatomy" APP_NAME = "anatomy"
def create_cid_user_and_groups(db):
group1 = CidUserGroup.objects.create(name="Group1")
group2 = CidUserGroup.objects.create(name="Group2")
cid_user_1000 = CidUser.objects.create(cid=1000, passcode="ABCD", group=group1)
cid_user_1001 = CidUser.objects.create(cid=1001, passcode="EFGH", group=group1)
cid_user_2001 = CidUser.objects.create(cid=2001, passcode="EFGH", group=group2)
assert cid_user_1000.cid == 1000
assert cid_user_1001.cid == 1001
def create_exam(db): def create_exam(db):
exam: Exam = AnatomyExamViews.Exam.objects.create( exam: Exam = AnatomyExamViews.Exam.objects.create(
name="Cid Exam", exam_mode=True, active=True name="Cid Exam", exam_mode=True, active=True
) )
group1: CidUserGroup = CidUserGroup.objects.get(name="Group1") group1: CidUserGroup = CidUserGroup.objects.get(name="Group1")
usergroup1: UserUserGroup = UserUserGroup.objects.get(name="Group1")
exam.cid_user_groups.add(group1) exam.cid_user_groups.add(group1)
exam.valid_cid_users.add(*group1.ciduser_set.all()) exam.valid_cid_users.add(*group1.ciduser_set.all())
exam.valid_user_users.add(*usergroup1.users.all())
assert exam in group1.anatomy_cid_user_groups.all() assert exam in group1.anatomy_cid_user_groups.all()
assert exam assert exam
@@ -85,7 +86,12 @@ def create_question(exam, answer=None):
answer_text = "testanswer" answer_text = "testanswer"
else: else:
answer_text = answer answer_text = answer
answer = Answer(question=question, answer=answer_text, answer_compare=answer_text, status=Answer.MarkOptions.CORRECT) answer = Answer(
question=question,
answer=answer_text,
answer_compare=answer_text,
status=Answer.MarkOptions.CORRECT,
)
answer.save() answer.save()
return question return question
@@ -99,34 +105,47 @@ def test_exams(db, client):
create_question_types(db) create_question_types(db)
question1 = create_question(exam) question1 = create_question(exam)
create_question(exam) generated_questions = [question1, create_question(exam), create_question(exam)]
create_question(exam)
active_exams = client.get(reverse(f"{APP_NAME}:active_exams")) active_exams = client.get(reverse(f"{APP_NAME}:active_exams"))
assert active_exams.status_code == 200 assert active_exams.status_code == 200
assert len(json.loads(active_exams.content)["exams"]) == 0 assert len(json.loads(active_exams.content)["exams"]) == 0
cid_user_1000 = CidUser.objects.get(cid=1000)
cid_user_1001 = CidUser.objects.get(cid=1001) cid_user_1001 = CidUser.objects.get(cid=1001)
cid_user_2001 = CidUser.objects.get(cid=2001)
user1 = User.objects.get(username="user1")
users_tested = 1
for cid_user in [cid_user_1001, cid_user_1000, user1]:
if isinstance(cid_user, CidUser):
testing_cid_user = True
else:
testing_cid_user = False
current_user = cid_user
client.force_login(cid_user)
exam.active = True
exam.publish_results = False
exam.save()
for cid_user in [cid_user_1001]:
# Test active exams sections works as intended # Test active exams sections works as intended
active_exams_cid = client.get( if testing_cid_user:
reverse( active_exams_url = reverse(
f"active_exams_cid", f"active_exams_cid",
kwargs={"cid": cid_user.cid, "passcode": cid_user.passcode}, kwargs={"cid": cid_user.cid, "passcode": cid_user.passcode},
) )
else:
active_exams_url = reverse(
f"active_exams",
) )
active_exams_cid = client.get(active_exams_url)
assert active_exams_cid.status_code == 200 assert active_exams_cid.status_code == 200
assert len(json.loads(active_exams_cid.content)["exams"]) == 1 assert len(json.loads(active_exams_cid.content)["exams"]) == 1
active_exams_cid = client.get( if testing_cid_user:
reverse(f"active_exams_cid", kwargs={"cid": 1001, "passcode": "EFGH"})
)
assert active_exams_cid.status_code == 200
assert len(json.loads(active_exams_cid.content)["exams"]) == 1
no_active_exams_cid = client.get( no_active_exams_cid = client.get(
reverse(f"active_exams_cid", kwargs={"cid": 2001, "passcode": "EGFH"}) reverse(f"active_exams_cid", kwargs={"cid": 2001, "passcode": "EGFH"})
) )
@@ -135,7 +154,10 @@ def test_exams(db, client):
assert json.loads(no_active_exams_cid.content)["status"] == "invalid" assert json.loads(no_active_exams_cid.content)["status"] == "invalid"
invalid_passcode = client.get( invalid_passcode = client.get(
reverse(f"active_exams_cid", kwargs={"cid": 1001, "passcode": "ABCD"}) reverse(
f"active_exams_cid",
kwargs={"cid": cid_user.cid, "passcode": "AAAA"},
)
) )
assert invalid_passcode.status_code == 401 assert invalid_passcode.status_code == 401
assert json.loads(invalid_passcode.content)["status"] == "invalid" assert json.loads(invalid_passcode.content)["status"] == "invalid"
@@ -166,9 +188,14 @@ def test_exams(db, client):
exam.active = True exam.active = True
exam.save() exam.save()
if testing_cid_user:
post_cid = cid_user.cid
else:
post_cid = f"u-{current_user.pk}"
post_json = { post_json = {
"eid": f"anatomy/{exam.pk}", "eid": f"anatomy/{exam.pk}",
"cid": cid_user_1001.cid, "cid": post_cid,
"start_time": "1659618141.731", "start_time": "1659618141.731",
"answers": [[]], "answers": [[]],
} }
@@ -184,7 +211,7 @@ def test_exams(db, client):
post_json = { post_json = {
"eid": f"anatomy/{exam.pk+10}", "eid": f"anatomy/{exam.pk+10}",
"cid": cid_user_1001.cid, "cid": post_cid,
"start_time": "1659618141.731", "start_time": "1659618141.731",
"answers": [[]], "answers": [[]],
} }
@@ -208,20 +235,21 @@ def test_exams(db, client):
for questions in exam_json["questions"]: for questions in exam_json["questions"]:
for qid in questions: for qid in questions:
valid_answers.append( post_data = {
{
"eid": exam_json["eid"], "eid": exam_json["eid"],
"cid": cid_user_1001.cid, "cid": post_cid,
"passcode": cid_user_1001.passcode,
"qid": qid, "qid": qid,
"qidn": "1", "qidn": "1",
"ans": f"answer {qid}", "ans": f"answer {qid}",
} }
) if testing_cid_user:
post_data["passcode"] = cid_user.passcode
valid_answers.append(post_data)
post_json = { post_json = {
"eid": exam_json["eid"], "eid": exam_json["eid"],
"cid": cid_user_1001.cid, "cid": post_cid,
"start_time": "1659618141.731", "start_time": "1659618141.731",
"answers": json.dumps(valid_answers), "answers": json.dumps(valid_answers),
} }
@@ -237,66 +265,130 @@ def test_exams(db, client):
# We can then check the answers have been submitted (and can be viewed by the user) # We can then check the answers have been submitted (and can be viewed by the user)
# Get overview scores page if testing_cid_user:
cid_scores_res = client.get( # Get overview scores page (invalid passcode)
reverse(f"cid_scores", kwargs={"cid": 1001, "passcode": "EFGH"}) AssertNotFound(
client,
reverse(
f"cid_scores", kwargs={"cid": cid_user.cid, "passcode": "AAAA"}
),
) )
cid_scores_url = reverse(
f"cid_scores",
kwargs={"cid": cid_user.cid, "passcode": cid_user.passcode},
)
else:
cid_scores_url = reverse(f"user_scores")
# Get overview scores page
cid_scores_res = client.get(cid_scores_url)
cid_scores_soup = BeautifulSoup(cid_scores_res.content, "html.parser") cid_scores_soup = BeautifulSoup(cid_scores_res.content, "html.parser")
print(cid_scores_soup.find("div", {"id" : "exam-assigned"})) search_exam = (
search_exam = cid_scores_soup.find("div", {"id" : "exam-assigned"}).find("ul", {"class" : exam.app_name}).find_all("li", attrs={"data-exam-id": exam.pk}) cid_scores_soup.find("div", {"id": "exam-assigned"})
.find("ul", {"class": exam.app_name})
.find_all("li", attrs={"data-exam-id": exam.pk})
)
assert search_exam assert search_exam
assert exam.name in str(search_exam) assert exam.name in str(search_exam)
assert "Active" in str(search_exam) assert "Active" in str(search_exam)
#assert "Active" in assigned_exams # check it is active # assert "Active" in assigned_exams # check it is active
invalid_exam = cid_scores_soup.find_all("li", attrs={"data-exam-id": exam.pk+5}) invalid_exam = cid_scores_soup.find_all(
"li", attrs={"data-exam-id": exam.pk + 5}
)
assert not invalid_exam # Check we can't find an invalid exam assert not invalid_exam # Check we can't find an invalid exam
# Check that we have a results link # Check that we have a results link
results_exam = cid_scores_soup.find("div", {"id" : "exam-results"}).find("ul", {"class" : exam.app_name}).find_all("li", attrs={"data-exam-id": exam.pk}) results_exam = (
cid_scores_soup.find("div", {"id": "exam-results"})
.find("ul", {"class": exam.app_name})
.find_all("li", attrs={"data-exam-id": exam.pk})
)
assert results_exam assert results_exam
assert exam.name in str(results_exam) assert exam.name in str(results_exam)
assert exam.name+" test" not in str(results_exam) assert exam.name + " test" not in str(results_exam)
assert "Results Published" not in str(results_exam) # It should not be published yet assert "Results Published" not in str(
results_exam
) # It should not be published yet
if testing_cid_user:
AssertNotFound(
client,
reverse(
f"{exam.app_name}:exam_scores_cid_user",
kwargs={"pk": exam.pk, "cid": cid_user.cid, "passcode": "AAAA"},
),
)
AssertNotFound(
client,
reverse(
f"{exam.app_name}:exam_scores_cid_user",
kwargs={
"pk": exam.pk,
"cid": cid_user_2001.cid,
"passcode": cid_user_2001.passcode,
},
),
)
exam_scores_url = reverse(
f"{exam.app_name}:exam_scores_cid_user",
kwargs={
"pk": exam.pk,
"cid": cid_user.cid,
"passcode": cid_user.passcode,
},
)
else:
exam_scores_url = reverse(
f"{exam.app_name}:exam_scores_user",
kwargs={"pk": exam.pk},
)
# Load the exam results page # Load the exam results page
cid_exam_scores_res = client.get( cid_exam_scores_res = client.get(exam_scores_url)
reverse(f"{exam.app_name}:exam_scores_cid_user", kwargs={"pk": exam.pk, "cid": 1001, "passcode": "EFGH"}) # Load the exam results page
)
cid_exam_scores_soup = BeautifulSoup(cid_exam_scores_res.content, "html.parser") cid_exam_scores_soup = BeautifulSoup(cid_exam_scores_res.content, "html.parser")
# Check that we have an alert that exams are not published # Check that we have an alert that exams are not published
alert = cid_exam_scores_soup.find("div", {"class": "alert"}) alert = cid_exam_scores_soup.find("div", {"class": "alert"})
assert "Results are not currently published." in str(alert) assert "Results are not currently published." in str(alert)
answer_lis = cid_exam_scores_soup.find(
answer_lis = cid_exam_scores_soup.find("ul", {"class": "score-answer-list"}).find_all("li") "ul", {"class": "score-answer-list"}
).find_all("li")
assert len(answer_lis) == len(valid_answers) assert len(answer_lis) == len(valid_answers)
for n in range(len(valid_answers)): # Check no answers are visible if results not published for n in range(
len(valid_answers)
): # Check no answers are visible if results not published
answer = valid_answers[n] answer = valid_answers[n]
li = answer_lis[n] li = answer_lis[n]
assert answer["ans"] in str(li) # Check that the saved answer is shown assert answer["ans"] in str(li) # Check that the saved answer is shown
assert not li.find("span", {"class": "correct-answer"}) # and that the correct answer isn't assert not li.find(
"span", {"class": "correct-answer"}
) # and that the correct answer isn't
assert cid_exam_scores_soup.find("div", {"class": "score-overview"}) is None # check we hide the score overview if not published assert (
cid_exam_scores_soup.find("div", {"class": "score-overview"}) is None
) # check we hide the score overview if not published
# Add another question to the exam # Add another question to the exam
create_question(exam) create_question(exam)
# Load the exam results page (again) # Load the exam results page (again)
cid_exam_scores_res = client.get( cid_exam_scores_res = client.get(exam_scores_url)
reverse(f"{exam.app_name}:exam_scores_cid_user", kwargs={"pk": exam.pk, "cid": 1001, "passcode": "EFGH"})
)
cid_exam_scores_soup = BeautifulSoup(cid_exam_scores_res.content, "html.parser") cid_exam_scores_soup = BeautifulSoup(cid_exam_scores_res.content, "html.parser")
answer_lis = cid_exam_scores_soup.find("ul", {"class": "score-answer-list"}).find_all("li") answer_lis = cid_exam_scores_soup.find(
"ul", {"class": "score-answer-list"}
).find_all("li")
assert len(answer_lis) == len(valid_answers) + 1 assert len(answer_lis) == len(valid_answers) + 1
assert "Not answered" in str(answer_lis[-1]) assert "Not answered" in str(answer_lis[-1])
@@ -305,20 +397,24 @@ def test_exams(db, client):
exam.save() exam.save()
# Load the exam results page (again) # Load the exam results page (again)
cid_exam_scores_res = client.get( cid_exam_scores_res = client.get(exam_scores_url)
reverse(f"{exam.app_name}:exam_scores_cid_user", kwargs={"pk": exam.pk, "cid": 1001, "passcode": "EFGH"})
)
cid_exam_scores_soup = BeautifulSoup(cid_exam_scores_res.content, "html.parser") cid_exam_scores_soup = BeautifulSoup(cid_exam_scores_res.content, "html.parser")
assert cid_exam_scores_soup.find("div", {"class": "alert"}) is None # Check our warning banner is gone assert (
cid_exam_scores_soup.find("div", {"class": "alert"}) is None
) # Check our warning banner is gone
answer_lis = cid_exam_scores_soup.find("ul", {"class": "score-answer-list"}).find_all("li") answer_lis = cid_exam_scores_soup.find(
"ul", {"class": "score-answer-list"}
).find_all("li")
assert len(answer_lis) == len(valid_answers) + 1 assert len(answer_lis) == len(valid_answers) + 1
assert "Not answered" in str(answer_lis[-1]) assert "Not answered" in str(answer_lis[-1])
# Repetition.... # Repetition....
for n in range(len(valid_answers)): # Check answers are visible if results published for n in range(
len(valid_answers)
): # Check answers are visible if results published
answer = valid_answers[n] answer = valid_answers[n]
li = answer_lis[n] li = answer_lis[n]
@@ -326,20 +422,45 @@ def test_exams(db, client):
assert li.find("span", {"class": "correct-answer"}).string == "testanswer" assert li.find("span", {"class": "correct-answer"}).string == "testanswer"
assert cid_exam_scores_soup.find("div", {"class": "score-overview"}).find("span", {"id": "total-score"}).string == "0 (3 unmarked)" if users_tested == 1:
# First user the answers will not have been saved
assert (
cid_exam_scores_soup.find("div", {"class": "score-overview"})
.find("span", {"id": "total-score"})
.string
== "0 (3 unmarked)"
)
else:
# Subsequent users should already have answers marked (apart from the last question which we have deleted)
assert (
cid_exam_scores_soup.find("div", {"class": "score-overview"})
.find("span", {"id": "total-score"})
.string
== "4 (1 unmarked)"
)
for question in exam.exam_questions.all(): for question in exam.exam_questions.all():
try: try:
new_ans = Answer(question=question, answer=question.get_unmarked_user_answers().pop(), status=Answer.MarkOptions.CORRECT) new_ans = Answer(
question=question,
answer=question.get_unmarked_user_answers().pop(),
status=Answer.MarkOptions.CORRECT,
)
new_ans.save() new_ans.save()
except KeyError: # Final question does not have an answer except KeyError: # Final question does not have an answer
pass pass
# Load the exam results page (again) # Load the exam results page (again)
cid_exam_scores_res = client.get( cid_exam_scores_res = client.get(exam_scores_url)
reverse(f"{exam.app_name}:exam_scores_cid_user", kwargs={"pk": exam.pk, "cid": 1001, "passcode": "EFGH"})
)
cid_exam_scores_soup = BeautifulSoup(cid_exam_scores_res.content, "html.parser") cid_exam_scores_soup = BeautifulSoup(cid_exam_scores_res.content, "html.parser")
assert cid_exam_scores_soup.find("div", {"class": "score-overview"}).find("span", {"id": "total-score"}).string == "6" assert (
cid_exam_scores_soup.find("div", {"class": "score-overview"})
.find("span", {"id": "total-score"})
.string
== "6"
)
generated_questions.pop(-1).delete()
users_tested = users_tested + 1
+2 -1
View File
@@ -2,6 +2,7 @@ from django.urls import path, include
from generic.models import Examination from generic.models import Examination
from . import views from . import views
from generic.views import ExamViews as GenericExamViews
app_name = "generic" app_name = "generic"
@@ -131,7 +132,7 @@ def generic_view_urls(generic_views):
return urlpatterns return urlpatterns
def generic_exam_urls(generic_exam_view): def generic_exam_urls(generic_exam_view: GenericExamViews):
urlpatterns = [ urlpatterns = [
path("", generic_exam_view.index, name="index"), path("", generic_exam_view.index, name="index"),
path("exam/<int:pk>/", generic_exam_view.exam_overview, name="exam_overview"), path("exam/<int:pk>/", generic_exam_view.exam_overview, name="exam_overview"),
+7 -4
View File
@@ -58,7 +58,7 @@ from .forms import (
UserUserGroupForm, UserUserGroupForm,
) )
from .models import CidUser, CidUserGroup, Examination, QuestionNote, Supervisor, UserGrades, UserProfile, UserUserGroup, get_next_cid from .models import CidUser, CidUserGroup, ExamBase, Examination, QuestionNote, Supervisor, UserGrades, UserProfile, UserUserGroup, get_next_cid
from rapids.models import Rapid as RapidQuestion from rapids.models import Rapid as RapidQuestion
from rapids.models import Exam as RapidExam from rapids.models import Exam as RapidExam
@@ -1319,9 +1319,11 @@ class ExamViews(View, LoginRequiredMixin):
eid = int(answer["eid"].split("/")[1]) eid = int(answer["eid"].split("/")[1])
uid = False uid = False
passcode = None
try: try:
cid = int(answer["cid"]) cid = int(answer["cid"])
passcode = answer["passcode"]
except ValueError: except ValueError:
if answer["cid"].startswith("u-"): if answer["cid"].startswith("u-"):
cid = False cid = False
@@ -1352,9 +1354,9 @@ class ExamViews(View, LoginRequiredMixin):
} }
) )
exam = get_object_or_404(self.Exam, pk=eid) exam: ExamBase = get_object_or_404(self.Exam, pk=eid)
if not exam.check_cid_user(cid, answer["passcode"], user_id=uid): if not exam.check_cid_user(cid, passcode, user_id=uid):
return JsonResponse( return JsonResponse(
{"success": False, "error": "invalid cid / passcode"} {"success": False, "error": "invalid cid / passcode"}
) )
@@ -1597,7 +1599,8 @@ class ExamViews(View, LoginRequiredMixin):
if not exam.exam_mode: if not exam.exam_mode:
raise Http404("Packet not in exam mode") raise Http404("Packet not in exam mode")
# TODO:Need some kind of test for cid if cid is not None and not exam.check_cid_user(cid, passcode, request):
raise Http404("Error accessing exam")
questions = ( questions = (
exam.exam_questions.all() exam.exam_questions.all()
+17 -35
View File
@@ -19,7 +19,7 @@ from physics.views import GenericExamViews as PhysicsExamViews
from physics.models import Category, CidUserAnswer, Exam, Question from physics.models import Category, CidUserAnswer, Exam, Question
from generic.models import CidUser, CidUserGroup, UserUserGroup from generic.models import CidUser, CidUserGroup, UserUserGroup
from rad.test_helpers import AssertNotFound from rad.test_helpers import AssertNotFound, create_cid_user_and_groups
from django.contrib.auth.models import User from django.contrib.auth.models import User
@@ -29,23 +29,6 @@ APP_NAME = "physics"
def create_cid_user_and_groups(db):
group1 = CidUserGroup.objects.create(name="Group1")
group2 = CidUserGroup.objects.create(name="Group2")
cid_user_1000 = CidUser.objects.create(cid=1000, passcode="ABCD", group=group1)
cid_user_1001 = CidUser.objects.create(cid=1001, passcode="EFGH", group=group1)
cid_user_2001 = CidUser.objects.create(cid=2001, passcode="EFGH", group=group2)
assert cid_user_1000.cid == 1000
assert cid_user_1001.cid == 1001
# Create UserUsers
user1 = User.objects.create_user(username="user1", email="test@email.com", password="test1234")
usergroup1 = UserUserGroup.objects.create(name="Group1")
usergroup1.users.add(user1)
usergroup2 = UserUserGroup.objects.create(name="Group2")
def create_exam(db): def create_exam(db):
@@ -122,7 +105,7 @@ def test_exams(db, client):
create_category(db) create_category(db)
questions = [create_question(exam), create_question(exam), create_question(exam)] generated_questions = [create_question(exam), create_question(exam), create_question(exam)]
active_exams = client.get(reverse(f"{APP_NAME}:active_exams")) active_exams = client.get(reverse(f"{APP_NAME}:active_exams"))
assert active_exams.status_code == 200 assert active_exams.status_code == 200
@@ -150,7 +133,6 @@ def test_exams(db, client):
exam.active = True exam.active = True
exam.publish_results = False exam.publish_results = False
exam.save() exam.save()
# Test active exams sections works as intended
start_page_res = client.get( start_page_res = client.get(
reverse(f"physics:exam_start", kwargs={"pk": exam.pk}) reverse(f"physics:exam_start", kwargs={"pk": exam.pk})
) )
@@ -161,7 +143,7 @@ def test_exams(db, client):
else: else:
assert "Start Exam" in str(start_page_soup) assert "Start Exam" in str(start_page_soup)
for n, question in enumerate(questions): for n, question in enumerate(generated_questions):
if testing_cid_user: if testing_cid_user:
take_url = reverse( take_url = reverse(
f"physics:exam_take", f"physics:exam_take",
@@ -203,7 +185,7 @@ def test_exams(db, client):
# Check that relevant buttons are being displayed # Check that relevant buttons are being displayed
assert cid_take_soup.find("button", {"name": "finish"}) is not None assert cid_take_soup.find("button", {"name": "finish"}) is not None
if n < len(questions) - 1: if n < len(generated_questions) - 1:
assert cid_take_soup.find("button", {"name": "next"}) is not None assert cid_take_soup.find("button", {"name": "next"}) is not None
if n > 0: if n > 0:
@@ -213,7 +195,7 @@ def test_exams(db, client):
n + 1 n + 1
) # + 1 for 0 offset ) # + 1 for 0 offset
assert cid_take_soup.find("span", {"id": "exam-length"}).string == str( assert cid_take_soup.find("span", {"id": "exam-length"}).string == str(
len(questions) len(generated_questions)
) )
# Check that stem text is displayed # Check that stem text is displayed
@@ -276,8 +258,8 @@ def test_exams(db, client):
# Loop through questions again to test submissions # Loop through questions again to test submissions
# All physics questions have 5 parts (and require a csrf token) # All physics questions have 5 parts (and require a csrf token)
questions_len = len(questions) - 1 questions_len = len(generated_questions) - 1
for n, question in enumerate(questions): for n, question in enumerate(generated_questions):
if testing_cid_user: if testing_cid_user:
question_url = reverse( question_url = reverse(
f"physics:exam_take", f"physics:exam_take",
@@ -388,8 +370,8 @@ def test_exams(db, client):
== 0 == 0
) )
# Get overview scores page (invalid passcode)
if testing_cid_user: if testing_cid_user:
# Get overview scores page (invalid passcode)
AssertNotFound(client, AssertNotFound(client,
reverse(f"cid_scores", kwargs={"cid": cid_user.cid, "passcode": "AAAA"}) reverse(f"cid_scores", kwargs={"cid": cid_user.cid, "passcode": "AAAA"})
) )
@@ -468,12 +450,12 @@ def test_exams(db, client):
# Check that we are showing enough questions / answers # Check that we are showing enough questions / answers
answer_lis = cid_exam_scores_soup.find_all("li", {"class": "question-part"}) answer_lis = cid_exam_scores_soup.find_all("li", {"class": "question-part"})
assert len(answer_lis) == 5 * len(questions) assert len(answer_lis) == 5 * len(generated_questions)
submitted_answers = cid_exam_scores_soup.find_all( submitted_answers = cid_exam_scores_soup.find_all(
"span", {"class": "submitted-user-answer"} "span", {"class": "submitted-user-answer"}
) )
assert len(submitted_answers) == 5 * len(questions) assert len(submitted_answers) == 5 * len(generated_questions)
for ans in submitted_answers: for ans in submitted_answers:
assert ans.text.strip() == "True" assert ans.text.strip() == "True"
@@ -483,7 +465,7 @@ def test_exams(db, client):
# Add another question to the exam # Add another question to the exam
extra_question = create_question(exam) extra_question = create_question(exam)
questions.append(extra_question) generated_questions.append(extra_question)
# Load the exam results page (again) # Load the exam results page (again)
cid_exam_scores_res = client.get( cid_exam_scores_res = client.get(
@@ -492,12 +474,12 @@ def test_exams(db, client):
cid_exam_scores_soup = BeautifulSoup(cid_exam_scores_res.content, "html.parser") cid_exam_scores_soup = BeautifulSoup(cid_exam_scores_res.content, "html.parser")
answer_lis = cid_exam_scores_soup.find_all("li", {"class": "question-part"}) answer_lis = cid_exam_scores_soup.find_all("li", {"class": "question-part"})
assert len(answer_lis) == 5 * len(questions) assert len(answer_lis) == 5 * len(generated_questions)
submitted_answers = cid_exam_scores_soup.find_all( submitted_answers = cid_exam_scores_soup.find_all(
"span", {"class": "submitted-user-answer"} "span", {"class": "submitted-user-answer"}
) )
assert len(submitted_answers) == 5 * len(questions) assert len(submitted_answers) == 5 * len(generated_questions)
for ans in submitted_answers[:-5]: for ans in submitted_answers[:-5]:
assert ans.text.strip() == "True" assert ans.text.strip() == "True"
@@ -524,10 +506,10 @@ def test_exams(db, client):
correct_answers = cid_exam_scores_soup.find_all( correct_answers = cid_exam_scores_soup.find_all(
"span", {"class": "correct-answer"} "span", {"class": "correct-answer"}
) )
assert len(correct_answers) == 5 * len(questions) assert len(correct_answers) == 5 * len(generated_questions)
n = 0 n = 0
for question in questions: for question in generated_questions:
for ans in question.get_answers(): for ans in question.get_answers():
assert correct_answers[n].text.strip() == f"Correct answer: {ans}" assert correct_answers[n].text.strip() == f"Correct answer: {ans}"
n = n + 1 n = n + 1
@@ -535,7 +517,7 @@ def test_exams(db, client):
submitted_answers = cid_exam_scores_soup.find_all( submitted_answers = cid_exam_scores_soup.find_all(
"span", {"class": "submitted-user-answer"} "span", {"class": "submitted-user-answer"}
) )
assert len(submitted_answers) == 5 * len(questions) assert len(submitted_answers) == 5 * len(generated_questions)
for ans in submitted_answers[:-5]: for ans in submitted_answers[:-5]:
assert ans.text.strip() == "True" assert ans.text.strip() == "True"
@@ -613,5 +595,5 @@ def test_exams(db, client):
cid_take_soup = BeautifulSoup(cid_take_res.content, "html.parser") cid_take_soup = BeautifulSoup(cid_take_res.content, "html.parser")
assert "Exam is currently inactive" in cid_take_soup.text assert "Exam is currently inactive" in cid_take_soup.text
questions.pop(-1).delete() generated_questions.pop(-1).delete()
users_tested = users_tested + 1 users_tested = users_tested + 1
+3
View File
@@ -102,6 +102,9 @@ def active_exams(request):
def exam_scores_cid_user(request, pk, cid=None, passcode=None): def exam_scores_cid_user(request, pk, cid=None, passcode=None):
exam = get_object_or_404(Exam, pk=pk) exam = get_object_or_404(Exam, pk=pk)
if not exam.exam_mode:
raise Http404("Packet not in exam mode")
if cid is not None and not exam.check_cid_user(cid, passcode, request): if cid is not None and not exam.check_cid_user(cid, passcode, request):
raise Http404("Error accessing exam") raise Http404("Error accessing exam")
+21
View File
@@ -1,6 +1,27 @@
from http import HTTPStatus from http import HTTPStatus
from generic.models import CidUser, CidUserGroup, UserUserGroup
from django.contrib.auth.models import User
def AssertNotFound(client, url): def AssertNotFound(client, url):
"""Helper to quickly test for urls that should return a 404 (NOT FOUND) error""" """Helper to quickly test for urls that should return a 404 (NOT FOUND) error"""
response = client.get(url) response = client.get(url)
assert response.status_code == HTTPStatus.NOT_FOUND, f"Response content: {response.content}" assert response.status_code == HTTPStatus.NOT_FOUND, f"Response content: {response.content}"
def create_cid_user_and_groups(db):
group1 = CidUserGroup.objects.create(name="Group1")
group2 = CidUserGroup.objects.create(name="Group2")
cid_user_1000 = CidUser.objects.create(cid=1000, passcode="ABCD", group=group1)
cid_user_1001 = CidUser.objects.create(cid=1001, passcode="EFGH", group=group1)
cid_user_2001 = CidUser.objects.create(cid=2001, passcode="EFGH", group=group2)
assert cid_user_1000.cid == 1000
assert cid_user_1001.cid == 1001
# Create UserUsers
user1 = User.objects.create_user(username="user1", email="test@email.com", password="test1234")
usergroup1 = UserUserGroup.objects.create(name="Group1")
usergroup1.users.add(user1)
usergroup2 = UserUserGroup.objects.create(name="Group2")