improve test

This commit is contained in:
Ross
2023-07-03 09:00:45 +01:00
parent 100945478b
commit 1ade42d7ba
2 changed files with 534 additions and 468 deletions
+36 -463
View File
@@ -19,7 +19,7 @@ from physics.views import GenericExamViews as PhysicsExamViews
from physics.models import Category, UserAnswer, Exam, Question
from generic.models import CidUser, CidUserGroup, UserUserGroup
from rad.test_helpers import AssertNotFound, create_cid_user_and_groups
from rad.test_helpers import AssertNotFound, ExamTester, create_cid_user_and_groups, create_exam
from django.contrib.auth.models import User
@@ -27,27 +27,6 @@ from django.contrib.auth.models import User
APP_NAME = "physics"
def create_exam(db):
exam: Exam = PhysicsExamViews.Exam.objects.create(
name="Cid Exam", exam_mode=True, active=True
)
group1: CidUserGroup = CidUserGroup.objects.get(name="Group1")
usergroup1: UserUserGroup = UserUserGroup.objects.get(name="Group1")
exam.cid_user_groups.add(group1)
exam.valid_cid_users.add(*group1.ciduser_set.all())
# exam.valid_user_users.add(user1)
exam.valid_user_users.add(*usergroup1.users.all())
assert exam in group1.physics_cid_user_groups.all()
assert exam
return exam
def create_category(db):
category = Category.objects.create(category="test category")
@@ -96,193 +75,55 @@ def create_question(exam, answer=None):
def test_exams(db, client):
create_cid_user_and_groups(db)
exam = create_exam(db)
create_category(db)
generated_questions = [
create_question(exam),
create_question(exam),
create_question(exam),
]
exam_tester = ExamTester(db, client, APP_NAME, PhysicsExamViews)
active_exams = client.get(reverse(f"{APP_NAME}:active_exams"))
assert active_exams.status_code == 200
assert len(json.loads(active_exams.content)["exams"]) == 0
cid_user_1001 = CidUser.objects.get(cid=1001)
cid_user_1000 = CidUser.objects.get(cid=1000)
cid_user_2001 = CidUser.objects.get(cid=2001)
user1 = User.objects.get(username="user1")
user2 = User.objects.get(username="user2")
exam_tester.create_questions(create_question)
users_tested = 1
# for cid_user in [cid_user_1001, cid_user_1000, user1, user2]:
for cid_user in [cid_user_1001, cid_user_1000, user1, user2]:
if isinstance(cid_user, CidUser):
testing_cid_user = True
else:
testing_cid_user = False
current_user = cid_user
client.force_login(cid_user)
for cid_user in exam_tester.all_users:
exam_tester.load_user(cid_user)
exam = exam_tester.exam
exam.active = False
exam.save()
exam_tester.check_active_exams(0)
exam.active = True
exam.publish_results = False
exam.save()
start_page_res = client.get(
reverse(f"physics:exam_start", kwargs={"pk": exam.pk})
)
print(cid_user)
exam_tester.check_onsite_start_page()
# Check user access to the start page
assert start_page_res.status_code == HTTPStatus.OK
start_page_soup = BeautifulSoup(start_page_res.content, "html.parser")
print(start_page_soup)
if testing_cid_user or cid_user in [user2]:
assert "Enter your CID and passcode" in str(start_page_soup)
else:
assert "Start Exam" in str(start_page_soup)
#check_onsite_start_page
for n, question in enumerate(generated_questions):
if testing_cid_user:
take_url = reverse(
f"physics:exam_take",
kwargs={
"pk": exam.pk,
"sk": n,
"cid": cid_user.cid,
"passcode": cid_user.passcode,
},
)
else:
take_url = reverse(
f"physics:exam_take_user",
kwargs={
"pk": exam.pk,
"sk": n,
},
)
exam_tester.check_take_page()
cid_take_res = client.get(take_url)
exam_tester.check_take_overview(answered=0, total=3)
# Check that users that have not been added cannot access the take pages
if cid_user in [user2]:
assert cid_take_res.status_code == HTTPStatus.NOT_FOUND
continue
else:
assert cid_take_res.status_code == HTTPStatus.OK
cid_take_soup = BeautifulSoup(cid_take_res.content, "html.parser")
# Check correct user is displayed
if testing_cid_user:
display_user = str(cid_user.cid)
else:
display_user = current_user.username
assert display_user in cid_take_soup.find("span", {"id": "user-id"}).string
# Check review mode alert not visible
assert cid_take_soup.find("div", {"class": "review-mode-alert"}) is None
# Check that relevant buttons are being displayed
assert cid_take_soup.find("button", {"name": "finish"}) is not None
if n < len(generated_questions) - 1:
assert cid_take_soup.find("button", {"name": "next"}) is not None
if n > 0:
assert cid_take_soup.find("button", {"name": "previous"}) is not None
assert cid_take_soup.find("span", {"id": "question-number"}).string == str(
n + 1
) # + 1 for 0 offset
assert cid_take_soup.find("span", {"id": "exam-length"}).string == str(
len(generated_questions)
)
# Check that stem text is displayed
assert (
cid_take_soup.find("span", {"id": "question-stem"}).string
== question.stem
)
assert cid_take_soup.find("label", {"for": "id_a"}).string == question.a
assert cid_take_soup.find("label", {"for": "id_b"}).string == question.b
assert cid_take_soup.find("label", {"for": "id_c"}).string == question.c
assert cid_take_soup.find("label", {"for": "id_d"}).string == question.d
assert cid_take_soup.find("label", {"for": "id_e"}).string == question.e
# As we haven't submitted any answers they should all be blank
assert (
cid_take_soup.find("input", {"type": "checkbox", "checked": True})
is None
)
if testing_cid_user:
take_overview_url = reverse(
f"physics:exam_take_overview",
kwargs={
"pk": exam.pk,
"cid": cid_user.cid,
"passcode": cid_user.passcode,
},
)
else:
take_overview_url = reverse(
f"physics:exam_take_overview_user",
kwargs={
"pk": exam.pk,
},
)
cid_take_overview_res = client.get(take_overview_url)
# Check that users that have not been added cannot access the take pages
if cid_user in [user2]:
assert cid_take_overview_res.status_code == HTTPStatus.NOT_FOUND
else:
assert cid_take_overview_res.status_code == HTTPStatus.OK
cid_take_overview_soup = BeautifulSoup(
cid_take_overview_res.content, "html.parser"
)
assert (
"0 out of 3 questions answered"
in cid_take_overview_soup.find(
"div", attrs={"class": "overview-text"}
).string
)
assert (
len(
cid_take_overview_soup.find_all(
"button", attrs={"class": "unanswered"}
)
)
== 3
)
# Loop through questions again to test submissions
# All physics questions have 5 parts (and require a csrf token)
questions_len = len(generated_questions) - 1
for n, question in enumerate(generated_questions):
if testing_cid_user:
questions_len = len(exam_tester.generated_questions) - 1
for n, question in enumerate(exam_tester.generated_questions):
if exam_tester.testing_cid_user:
question_url = reverse(
f"physics:exam_take",
f"{APP_NAME}:exam_take",
kwargs={
"pk": exam.pk,
"sk": n,
"cid": cid_user.cid,
"passcode": cid_user.passcode,
"cid": exam_tester.current_user.cid,
"passcode": exam_tester.current_user.passcode,
},
)
else:
question_url = reverse(
f"physics:exam_take_user",
f"{APP_NAME}:exam_take_user",
kwargs={
"pk": exam.pk,
"sk": n,
@@ -291,7 +132,7 @@ def test_exams(db, client):
cid_take_res = client.get(question_url)
if cid_user in [user2]:
if cid_user in exam_tester.invalid_users:
assert cid_take_res.status_code == HTTPStatus.NOT_FOUND
continue
else:
@@ -341,255 +182,29 @@ def test_exams(db, client):
assert len(cid_user_answers) == users_tested
if testing_cid_user:
cid_user_answer = cid_user_answers.filter(cid=cid_user.cid)[0]
if exam_tester.testing_cid_user:
cid_user_answer = cid_user_answers.filter(cid=exam_tester.current_user.cid)[0]
else:
cid_user_answer = cid_user_answers.filter(user=current_user)[0]
cid_user_answer = cid_user_answers.filter(user=exam_tester.current_user)[0]
assert all(cid_user_answer.get_answers())
# Recheck the overview page (now that we have submitted answers)
if testing_cid_user:
take_overview_url = reverse(
f"physics:exam_take_overview",
kwargs={
"pk": exam.pk,
"cid": cid_user.cid,
"passcode": cid_user.passcode,
},
)
else:
take_overview_url = reverse(
f"physics:exam_take_overview_user",
kwargs={
"pk": exam.pk,
},
)
exam_tester.check_take_overview(3, 3)
cid_take_overview_res = client.get(take_overview_url)
if cid_user in [user2]:
assert cid_take_overview_res.status_code == HTTPStatus.NOT_FOUND
else:
assert cid_take_overview_res.status_code == HTTPStatus.OK
exam_tester.check_cid_scores_page()
cid_take_overview_soup = BeautifulSoup(
cid_take_overview_res.content, "html.parser"
)
assert (
"3 out of 3 questions answered"
in cid_take_overview_soup.find(
"div", attrs={"class": "overview-text"}
).string
)
assert (
len(
cid_take_overview_soup.find_all(
"button", attrs={"class": "unanswered"}
)
)
== 0
)
exam_tester.check_cid_scores_user_page()
if testing_cid_user:
# Get overview scores page (invalid passcode)
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)
assert cid_scores_res.status_code == HTTPStatus.OK
cid_scores_soup = BeautifulSoup(cid_scores_res.content, "html.parser")
if cid_user in [user2]:
# page should load but we shouldn't be able to find the exam
with pytest.raises(AttributeError):
search_exam = (
cid_scores_soup.find("div", {"id": "exam-assigned"})
.find("ul", {"class": exam.app_name.lower()})
.find_all("li", attrs={"data-exam-id": exam.pk})
)
else:
search_exam = (
cid_scores_soup.find("div", {"id": "exam-assigned"})
.find("ul", {"class": exam.app_name.lower()})
.find_all("li", attrs={"data-exam-id": exam.pk})
)
assert search_exam
assert exam.name in str(search_exam)
assert "Active" in str(search_exam)
# assert "Active" in assigned_exams # check it is active
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
# 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})
)
assert results_exam
assert exam.name 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
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
cid_exam_scores_res = client.get(exam_scores_url)
if cid_user in [user2]:
assert cid_exam_scores_res.status_code == HTTPStatus.NOT_FOUND
# The rest of the tests are for valid users
if exam_tester.current_user in exam_tester.invalid_users:
continue
else:
assert cid_exam_scores_res.status_code == HTTPStatus.OK
cid_exam_scores_soup = BeautifulSoup(cid_exam_scores_res.content, "html.parser")
# Check that we have an alert that exams are not published
alert = cid_exam_scores_soup.find("div", {"class": "alert"})
assert "Results are not currently published." in str(alert)
# Check that we are showing enough questions / answers
answer_lis = cid_exam_scores_soup.find_all("li", {"class": "question-part"})
assert len(answer_lis) == 5 * len(generated_questions)
submitted_answers = cid_exam_scores_soup.find_all(
"span", {"class": "submitted-user-answer"}
)
assert len(submitted_answers) == 5 * len(generated_questions)
for ans in submitted_answers:
assert ans.text.strip() == "True"
# Check no correct answers are shown
assert not cid_exam_scores_soup.find_all("span", {"class": "correct-answer"})
# Add another question to the exam
extra_question = create_question(exam)
generated_questions.append(extra_question)
# Load the exam results page (again)
cid_exam_scores_res = client.get(exam_scores_url)
cid_exam_scores_soup = BeautifulSoup(cid_exam_scores_res.content, "html.parser")
answer_lis = cid_exam_scores_soup.find_all("li", {"class": "question-part"})
assert len(answer_lis) == 5 * len(generated_questions)
submitted_answers = cid_exam_scores_soup.find_all(
"span", {"class": "submitted-user-answer"}
)
assert len(submitted_answers) == 5 * len(generated_questions)
for ans in submitted_answers[:-5]:
assert ans.text.strip() == "True"
# The new question will not have any answers
for ans in submitted_answers[-5:]:
assert ans.text.strip() == ""
# Publish the results!
exam.publish_results = True
exam.save()
# Load the exam results page (again)
cid_exam_scores_res = client.get(exam_scores_url)
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
# Check that we are displaying the correct answers (correctly)
correct_answers = cid_exam_scores_soup.find_all(
"span", {"class": "correct-answer"}
)
assert len(correct_answers) == 5 * len(generated_questions)
n = 0
for question in generated_questions:
for ans in question.get_answers():
assert correct_answers[n].text.strip() == f"Correct answer: {ans}"
n = n + 1
submitted_answers = cid_exam_scores_soup.find_all(
"span", {"class": "submitted-user-answer"}
)
assert len(submitted_answers) == 5 * len(generated_questions)
for ans in submitted_answers[:-5]:
assert ans.text.strip() == "True"
# The new question will not have any answers
for ans in submitted_answers[-5:]:
assert ans.text.strip() == ""
assert (
cid_exam_scores_soup.find("div", {"class": "score-overview"})
.find("span", {"id": "total-score"})
.string
== "9"
)
assert (
cid_exam_scores_soup.find("div", {"class": "score-overview"})
.find("span", {"id": "max-score"})
.string
== "20"
)
# answer the final question
if testing_cid_user:
extra_question = exam_tester.generated_questions[-1]
if exam_tester.testing_cid_user:
cid_user_answer = UserAnswer(
question=extra_question,
a=True,
@@ -608,54 +223,12 @@ def test_exams(db, client):
c=True,
d=False,
e=True,
user=current_user,
user=exam_tester.current_user,
exam=exam,
)
cid_user_answer.save()
cid_exam_scores_res = client.get(exam_scores_url)
cid_exam_scores_soup = BeautifulSoup(cid_exam_scores_res.content, "html.parser")
exam_tester.check_cid_scores_user_page2()
# As we have answered correctly the new score should be increased by 5
assert (
cid_exam_scores_soup.find("div", {"class": "score-overview"})
.find("span", {"id": "total-score"})
.string
== "14"
)
# Check what happens when exam is not active
exam.active = False
exam.save()
start_page_res = client.get(
reverse(f"physics:exam_start", kwargs={"pk": exam.pk})
)
start_page_soup = BeautifulSoup(start_page_res.content, "html.parser")
assert "Exam is currently inactive" in start_page_soup.text
if testing_cid_user:
cid_take_url = reverse(
f"physics:exam_take",
kwargs={
"pk": exam.pk,
"sk": 0,
"cid": cid_user.cid,
"passcode": cid_user.passcode,
},
)
else:
cid_take_url = reverse(
f"physics:exam_take_user",
kwargs={
"pk": exam.pk,
"sk": 0,
},
)
cid_take_res = client.get(cid_take_url)
cid_take_soup = BeautifulSoup(cid_take_res.content, "html.parser")
assert "Exam is currently inactive" in cid_take_soup.text
generated_questions.pop(-1).delete()
users_tested = users_tested + 1