fix longs tests
This commit is contained in:
+24
-4
@@ -286,25 +286,45 @@ def generic_exam_urls(generic_exam_view: GenericExamViews):
|
|||||||
),
|
),
|
||||||
# These are a little more ambiguous than ideal
|
# These are a little more ambiguous than ideal
|
||||||
path(
|
path(
|
||||||
"exam/json/<int:pk>/<int:sk>",
|
"exam/json/<int:pk>/question/<int:sk>",
|
||||||
generic_exam_view.exam_question_json,
|
generic_exam_view.exam_question_json,
|
||||||
name="exam_question_json",
|
name="exam_question_json",
|
||||||
),
|
),
|
||||||
path(
|
path(
|
||||||
"exam/json/<int:pk>/<int:sk>/unbased",
|
"exam/json/<int:pk>/question/<int:sk>/unbased",
|
||||||
generic_exam_view.exam_question_json_unbased,
|
generic_exam_view.exam_question_json_unbased,
|
||||||
name="exam_question_json_unbased",
|
name="exam_question_json_unbased",
|
||||||
),
|
),
|
||||||
path(
|
path(
|
||||||
"exam/json/<int:pk>/<int:cid>/<str:passcode>/<int:sk>",
|
"exam/json/<int:pk>/question/<int:cid>/<str:passcode>/<int:sk>",
|
||||||
generic_exam_view.exam_question_json_cid,
|
generic_exam_view.exam_question_json_cid,
|
||||||
name="exam_question_json_cid",
|
name="exam_question_json_cid",
|
||||||
),
|
),
|
||||||
path(
|
path(
|
||||||
"exam/json/<int:pk>/<int:cid>/<str:passcode>/<int:sk>/unbased",
|
"exam/json/<int:pk>/question/<int:cid>/<str:passcode>/<int:sk>/unbased",
|
||||||
generic_exam_view.exam_question_json_unbased_cid,
|
generic_exam_view.exam_question_json_unbased_cid,
|
||||||
name="exam_question_json_unbased_cid",
|
name="exam_question_json_unbased_cid",
|
||||||
),
|
),
|
||||||
|
#path(
|
||||||
|
# "exam/json/<int:pk>/<int:sk>",
|
||||||
|
# generic_exam_view.exam_question_json,
|
||||||
|
# name="exam_question_json",
|
||||||
|
#),
|
||||||
|
#path(
|
||||||
|
# "exam/json/<int:pk>/<int:sk>/unbased",
|
||||||
|
# generic_exam_view.exam_question_json_unbased,
|
||||||
|
# name="exam_question_json_unbased",
|
||||||
|
#),
|
||||||
|
#path(
|
||||||
|
# "exam/json/<int:pk>/<int:cid>/<str:passcode>/<int:sk>",
|
||||||
|
# generic_exam_view.exam_question_json_cid,
|
||||||
|
# name="exam_question_json_cid",
|
||||||
|
#),
|
||||||
|
#path(
|
||||||
|
# "exam/json/<int:pk>/<int:cid>/<str:passcode>/<int:sk>/unbased",
|
||||||
|
# generic_exam_view.exam_question_json_unbased_cid,
|
||||||
|
# name="exam_question_json_unbased_cid",
|
||||||
|
#),
|
||||||
path(
|
path(
|
||||||
"exam/json/<int:pk>/recreate",
|
"exam/json/<int:pk>/recreate",
|
||||||
generic_exam_view.exam_json_recreate,
|
generic_exam_view.exam_json_recreate,
|
||||||
|
|||||||
+19
-1
@@ -1587,6 +1587,7 @@ class ExamViews(View, LoginRequiredMixin):
|
|||||||
raise Http404("No available exam")
|
raise Http404("No available exam")
|
||||||
|
|
||||||
# TODO: check access for logged in users
|
# TODO: check access for logged in users
|
||||||
|
print("TEST", cid)
|
||||||
|
|
||||||
# Check access for users
|
# Check access for users
|
||||||
if request.user.is_anonymous:
|
if request.user.is_anonymous:
|
||||||
@@ -1722,9 +1723,12 @@ class ExamViews(View, LoginRequiredMixin):
|
|||||||
return self.exam_question_json_unbased(request, pk, sk, cid, passcode)
|
return self.exam_question_json_unbased(request, pk, sk, cid, passcode)
|
||||||
|
|
||||||
def exam_question_json_unbased(self, request, pk, sk, cid=None, passcode=None):
|
def exam_question_json_unbased(self, request, pk, sk, cid=None, passcode=None):
|
||||||
|
print("TESTING")
|
||||||
|
print("**************************")
|
||||||
question = get_object_or_404(self.Question, pk=sk)
|
question = get_object_or_404(self.Question, pk=sk)
|
||||||
exam = get_object_or_404(self.Exam, pk=pk)
|
exam = get_object_or_404(self.Exam, pk=pk)
|
||||||
|
|
||||||
|
print("CID", cid)
|
||||||
|
|
||||||
if not exam.active and not self.check_user_access(request.user, pk):
|
if not exam.active and not self.check_user_access(request.user, pk):
|
||||||
raise Http404("No available exam")
|
raise Http404("No available exam")
|
||||||
@@ -1735,6 +1739,8 @@ class ExamViews(View, LoginRequiredMixin):
|
|||||||
else:
|
else:
|
||||||
user_id = request.user.pk
|
user_id = request.user.pk
|
||||||
|
|
||||||
|
print("CID", cid)
|
||||||
|
|
||||||
if not exam.check_cid_user(cid, passcode, request, user_id):
|
if not exam.check_cid_user(cid, passcode, request, user_id):
|
||||||
raise Http404("No available exam")
|
raise Http404("No available exam")
|
||||||
|
|
||||||
@@ -1795,16 +1801,19 @@ class ExamViews(View, LoginRequiredMixin):
|
|||||||
).first()
|
).first()
|
||||||
# user_answer = cid_user_answers_q_map[q]
|
# user_answer = cid_user_answers_q_map[q]
|
||||||
|
|
||||||
|
print("QUSETION", q)
|
||||||
if not user_answer or user_answer is None:
|
if not user_answer or user_answer is None:
|
||||||
# skip if no answer
|
# skip if no answer
|
||||||
score, text = q.get_unanswered_mark_and_text()
|
score, text = q.get_unanswered_mark_and_text()
|
||||||
answers_marks.append(score)
|
#answers_marks.append(score)
|
||||||
# answers.append("")
|
# answers.append("")
|
||||||
answer_score = score
|
answer_score = score
|
||||||
ans = text
|
ans = text
|
||||||
else:
|
else:
|
||||||
ans = user_answer.get_answer()
|
ans = user_answer.get_answer()
|
||||||
answer_score = user_answer.get_answer_score()
|
answer_score = user_answer.get_answer_score()
|
||||||
|
print("ans", ans)
|
||||||
|
print("ans score", answer_score)
|
||||||
|
|
||||||
correct_answer = q.get_primary_answer()
|
correct_answer = q.get_primary_answer()
|
||||||
|
|
||||||
@@ -1815,6 +1824,8 @@ class ExamViews(View, LoginRequiredMixin):
|
|||||||
answers_marks.append(answer_score)
|
answers_marks.append(answer_score)
|
||||||
answers_and_marks.append((ans, answer_score, correct_answer))
|
answers_and_marks.append((ans, answer_score, correct_answer))
|
||||||
|
|
||||||
|
print(answers_marks)
|
||||||
|
|
||||||
if "unmarked" in answers_marks:
|
if "unmarked" in answers_marks:
|
||||||
answered = [i for i in answers_marks if type(i) == int]
|
answered = [i for i in answers_marks if type(i) == int]
|
||||||
total_score = sum(answered)
|
total_score = sum(answered)
|
||||||
@@ -1823,7 +1834,14 @@ class ExamViews(View, LoginRequiredMixin):
|
|||||||
else:
|
else:
|
||||||
total_score = sum(answers_marks)
|
total_score = sum(answers_marks)
|
||||||
|
|
||||||
|
match self.app_name:
|
||||||
|
case "rapids" | "anatomy":
|
||||||
max_score = len(questions) * 2
|
max_score = len(questions) * 2
|
||||||
|
case "longs":
|
||||||
|
max_score = len(questions) * 8
|
||||||
|
case _:
|
||||||
|
max_score = len(questions)
|
||||||
|
|
||||||
|
|
||||||
template_context = {
|
template_context = {
|
||||||
"exam": exam,
|
"exam": exam,
|
||||||
|
|||||||
+19
-6
@@ -345,9 +345,10 @@ class Long(QuestionBase):
|
|||||||
|
|
||||||
return url
|
return url
|
||||||
|
|
||||||
def get_unanswered_mark_and_text(self) -> tuple[int, str]:
|
def get_unanswered_mark_and_text(self) -> tuple[int, tuple[str, str, str, str, str]]:
|
||||||
"""
|
"""
|
||||||
Override in models if needed
|
Long cases are receive a mark between 4 and 8
|
||||||
|
Therefore unmarked = 4
|
||||||
"""
|
"""
|
||||||
return (4, ("Not answered",) * 5)
|
return (4, ("Not answered",) * 5)
|
||||||
|
|
||||||
@@ -862,7 +863,9 @@ class UserAnswer(UserAnswerBase):
|
|||||||
return "hidden"
|
return "hidden"
|
||||||
return "/".join(f"{str(i.score)}" for i in mark_objects)
|
return "/".join(f"{str(i.score)}" for i in mark_objects)
|
||||||
|
|
||||||
def get_answer_score(self):
|
def get_answer_score(self) -> float | str:
|
||||||
|
"""Returns the answers score.
|
||||||
|
If the answer is unmarked the string "unmarked" is returned"""
|
||||||
if self.score == "":
|
if self.score == "":
|
||||||
return "unmarked"
|
return "unmarked"
|
||||||
return float(self.score)
|
return float(self.score)
|
||||||
@@ -873,8 +876,19 @@ class UserAnswer(UserAnswerBase):
|
|||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def get_answer(self):
|
def get_answer(
|
||||||
(
|
self,
|
||||||
|
) -> tuple[
|
||||||
|
models.TextField,
|
||||||
|
models.TextField,
|
||||||
|
models.TextField,
|
||||||
|
models.TextField,
|
||||||
|
models.TextField,
|
||||||
|
]:
|
||||||
|
"""Returns a tuple containing the users answers (model fields)
|
||||||
|
|
||||||
|
"""
|
||||||
|
return (
|
||||||
self.answer_observations,
|
self.answer_observations,
|
||||||
self.answer_interpretation,
|
self.answer_interpretation,
|
||||||
self.answer_principle_diagnosis,
|
self.answer_principle_diagnosis,
|
||||||
@@ -901,7 +915,6 @@ Management:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@reversion.register
|
@reversion.register
|
||||||
class AnswerMarks(models.Model):
|
class AnswerMarks(models.Model):
|
||||||
score = models.CharField(max_length=3, choices=UserAnswer.ScoreOptions.choices)
|
score = models.CharField(max_length=3, choices=UserAnswer.ScoreOptions.choices)
|
||||||
|
|||||||
@@ -13,37 +13,33 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="longs">
|
<div class="longs">
|
||||||
{% include 'user_score_header.html' %}
|
{% include 'user_score_header.html' %}
|
||||||
<ul>
|
|
||||||
{% for score in answers_marks %}
|
|
||||||
<li class="user-answer-li">Question {{forloop.counter}}</li>
|
|
||||||
<span class="user-answer-score user-answer-score-{{score}}">
|
|
||||||
<pre>{{ans}}</pre> ({{score}})
|
|
||||||
</span>
|
|
||||||
{% endfor %}
|
|
||||||
</ul>
|
|
||||||
<div>
|
<div>
|
||||||
<h4>Answers</h4>
|
{% comment %} <h4>Answers</h4> {% endcomment %}
|
||||||
<ul class="long-answer">{% for a,b,c,d,e in answer_text %}
|
<ul class="score-answer-list">
|
||||||
<li class="user-answer-li"><b>Question {{forloop.counter}}</b> <span class="view-question-link-longs"
|
{% for ans, score, correct_answer in answers_and_marks %}
|
||||||
data-qn={{forloop.counter0}}>View</span></li>
|
<li class="user-answer-li" data-question-number="{{forloop.counter}}"><b>Question {{forloop.counter}}</b> <span class="view-question-link-longs"
|
||||||
|
data-qn={{forloop.counter0}}>View</span>
|
||||||
<ul>
|
<ul>
|
||||||
<li class="user-answer-li">Observation</br>
|
<li class="Observations" data-qidn="1">Observations</br>
|
||||||
<pre>{{a}}</pre>
|
<pre>{{ans.0}}</pre>
|
||||||
</li>
|
</li>
|
||||||
<li class="user-answer-li">Interpretation</br>
|
<li class="Interpretation" data-qidn="2">Interpretation</br>
|
||||||
<pre>{{b}}</pre>
|
<pre>{{ans.1}}</pre>
|
||||||
</li>
|
</li>
|
||||||
<li class="user-answer-li">Principle Diagnosis</br>
|
<li class="Principle Diagnosis" data-qidn="3">Principle Diagnosis</br>
|
||||||
<pre>{{c}}</pre>
|
<pre>{{ans.2}}</pre>
|
||||||
</li>
|
</li>
|
||||||
<li class="user-answer-li">Differential Diagnosis</br>
|
<li class="Differential Diagnosis" data-qidn="4">Differential Diagnosis</br>
|
||||||
<pre>{{d}}</pre>
|
<pre>{{ans.3}}</pre>
|
||||||
</li>
|
</li>
|
||||||
<li class="user-answer-li">Management</br>
|
<li class="Management" data-qidn="5">Management</br>
|
||||||
<pre>{{e}}</pre>
|
<pre>{{ans.4}}</pre>
|
||||||
</li>
|
</li>
|
||||||
|
{% if exam.publish_results %}
|
||||||
|
<span class="answer-score">{{score}}</span>
|
||||||
|
{% endif %}
|
||||||
</ul>
|
</ul>
|
||||||
|
</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
|||||||
+111
-45
@@ -1,3 +1,4 @@
|
|||||||
|
from collections import defaultdict
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
from re import A
|
from re import A
|
||||||
@@ -23,6 +24,7 @@ from longs.models import (
|
|||||||
Long as Question,
|
Long as Question,
|
||||||
LongSeries,
|
LongSeries,
|
||||||
LongSeriesImage,
|
LongSeriesImage,
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
from generic.models import CidUser, CidUserGroup, UserUserGroup
|
from generic.models import CidUser, CidUserGroup, UserUserGroup
|
||||||
@@ -31,6 +33,8 @@ from django.contrib.auth.models import User
|
|||||||
|
|
||||||
from rad.test_helpers import AssertNotFound, create_cid_user_and_groups
|
from rad.test_helpers import AssertNotFound, create_cid_user_and_groups
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
APP_NAME = "longs"
|
APP_NAME = "longs"
|
||||||
|
|
||||||
|
|
||||||
@@ -223,6 +227,7 @@ def test_exams(db, client):
|
|||||||
print("check question:", q)
|
print("check question:", q)
|
||||||
# check redirects to the json file work
|
# check redirects to the json file work
|
||||||
# TODO: sort out testing of the saved JSON files
|
# TODO: sort out testing of the saved JSON files
|
||||||
|
try:
|
||||||
question_json_res = client.get(
|
question_json_res = client.get(
|
||||||
reverse(
|
reverse(
|
||||||
f"longs:exam_question_json_cid",
|
f"longs:exam_question_json_cid",
|
||||||
@@ -235,6 +240,17 @@ def test_exams(db, client):
|
|||||||
),
|
),
|
||||||
follow=True,
|
follow=True,
|
||||||
)
|
)
|
||||||
|
except AttributeError: # UserUser has no cid attribute
|
||||||
|
question_json_res = client.get(
|
||||||
|
reverse(
|
||||||
|
f"longs:exam_question_json",
|
||||||
|
kwargs={
|
||||||
|
"pk": exam.pk,
|
||||||
|
"sk": q,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
follow=True,
|
||||||
|
)
|
||||||
# assert question_json_res.status_code == 200
|
# assert question_json_res.status_code == 200
|
||||||
assert len(question_json_res.redirect_chain) == 2
|
assert len(question_json_res.redirect_chain) == 2
|
||||||
assert question_json_res.redirect_chain[0][1] == 302
|
assert question_json_res.redirect_chain[0][1] == 302
|
||||||
@@ -242,6 +258,9 @@ def test_exams(db, client):
|
|||||||
|
|
||||||
assert question_json_res.redirect_chain[1][0].endswith(f"{q}.json")
|
assert question_json_res.redirect_chain[1][0].endswith(f"{q}.json")
|
||||||
|
|
||||||
|
print(cid_user, testing_cid_user)
|
||||||
|
|
||||||
|
if testing_cid_user:
|
||||||
question_json_unbased_res = client.get(
|
question_json_unbased_res = client.get(
|
||||||
reverse(
|
reverse(
|
||||||
f"longs:exam_question_json_unbased_cid",
|
f"longs:exam_question_json_unbased_cid",
|
||||||
@@ -254,6 +273,27 @@ def test_exams(db, client):
|
|||||||
),
|
),
|
||||||
follow=True,
|
follow=True,
|
||||||
)
|
)
|
||||||
|
else:
|
||||||
|
test = reverse(
|
||||||
|
f"longs:exam_question_json_unbased",
|
||||||
|
kwargs={
|
||||||
|
"pk": exam.pk,
|
||||||
|
"sk": q,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
print(test)
|
||||||
|
question_json_unbased_res = client.get(
|
||||||
|
|
||||||
|
reverse(
|
||||||
|
f"longs:exam_question_json_unbased",
|
||||||
|
kwargs={
|
||||||
|
"pk": exam.pk,
|
||||||
|
"sk": q,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
follow=True,
|
||||||
|
)
|
||||||
|
|
||||||
assert question_json_unbased_res.status_code == 200
|
assert question_json_unbased_res.status_code == 200
|
||||||
question_json = json.loads(question_json_unbased_res.content)
|
question_json = json.loads(question_json_unbased_res.content)
|
||||||
|
|
||||||
@@ -262,9 +302,7 @@ def test_exams(db, client):
|
|||||||
# As we store references to the questions we have to check individually
|
# As we store references to the questions we have to check individually
|
||||||
assert q in exam_json["questions"].keys()
|
assert q in exam_json["questions"].keys()
|
||||||
|
|
||||||
q_json = Question.objects.get(pk=q).get_question_json(
|
q_json = Question.objects.get(pk=q).get_question_json(based=False)
|
||||||
based=False
|
|
||||||
)
|
|
||||||
|
|
||||||
assert question_json == q_json
|
assert question_json == q_json
|
||||||
|
|
||||||
@@ -325,10 +363,8 @@ def test_exams(db, client):
|
|||||||
# Long answers currently send a seperate object for each component
|
# Long answers currently send a seperate object for each component
|
||||||
valid_answers = []
|
valid_answers = []
|
||||||
valid_answers_extra = []
|
valid_answers_extra = []
|
||||||
|
valid_answers_by_question = defaultdict(dict)
|
||||||
|
|
||||||
for questions in exam_json["questions"]:
|
|
||||||
for qid in questions:
|
|
||||||
# Long answers submit 5 sections
|
|
||||||
sections = (
|
sections = (
|
||||||
("1", "answer observations"),
|
("1", "answer observations"),
|
||||||
("2", "answer interpretation"),
|
("2", "answer interpretation"),
|
||||||
@@ -336,6 +372,11 @@ def test_exams(db, client):
|
|||||||
("4", "answer differential diagnosis"),
|
("4", "answer differential diagnosis"),
|
||||||
("5", "answer management"),
|
("5", "answer management"),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
i = 0
|
||||||
|
for questions in exam_json["questions"]:
|
||||||
|
for qid in questions:
|
||||||
|
# Long answers submit 5 sections
|
||||||
for n, name in sections:
|
for n, name in sections:
|
||||||
post_data = {
|
post_data = {
|
||||||
"eid": exam_json["eid"],
|
"eid": exam_json["eid"],
|
||||||
@@ -348,6 +389,8 @@ def test_exams(db, client):
|
|||||||
post_data["passcode"] = cid_user.passcode
|
post_data["passcode"] = cid_user.passcode
|
||||||
|
|
||||||
valid_answers_extra.append(post_data)
|
valid_answers_extra.append(post_data)
|
||||||
|
valid_answers_by_question[i][n] = post_data
|
||||||
|
i = i + 1
|
||||||
|
|
||||||
post_json = {
|
post_json = {
|
||||||
"eid": exam_json["eid"],
|
"eid": exam_json["eid"],
|
||||||
@@ -469,21 +512,32 @@ def test_exams(db, client):
|
|||||||
|
|
||||||
answer_lis = cid_exam_scores_soup.find(
|
answer_lis = cid_exam_scores_soup.find(
|
||||||
"ul", {"class": "score-answer-list"}
|
"ul", {"class": "score-answer-list"}
|
||||||
).find_all("li")
|
).find_all("li", {"class": "user-answer-li"})
|
||||||
|
|
||||||
assert len(answer_lis) == len(valid_answers)
|
assert len(answer_lis) == len(valid_answers_by_question)
|
||||||
|
|
||||||
|
pprint(valid_answers_by_question)
|
||||||
|
print(cid_user)
|
||||||
|
|
||||||
for n in range(
|
for n in range(
|
||||||
len(valid_answers)
|
len(valid_answers_by_question)
|
||||||
): # Check no answers are visible if results not published
|
): # Check no answers are visible if results not published
|
||||||
answer = valid_answers[n]
|
lis = answer_lis[n]
|
||||||
li = answer_lis[n]
|
#n = str(n + 1) # questions are not zero indexed (lists are)
|
||||||
|
|
||||||
|
for qidn, section_title in sections:
|
||||||
|
print(n, qidn)
|
||||||
|
answer = valid_answers_by_question[n][qidn]
|
||||||
|
|
||||||
|
li = lis.find("li", attrs={"data-qidn": qidn})
|
||||||
|
|
||||||
|
assert li["class"][0].lower() in section_title
|
||||||
|
|
||||||
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(
|
# assert not li.find(
|
||||||
"span", {"class": "correct-answer"}
|
# "span", {"class": "correct-answer"}
|
||||||
) # and that the correct answer isn't
|
# ) # and that the correct answer isn't
|
||||||
|
|
||||||
assert (
|
assert (
|
||||||
cid_exam_scores_soup.find("div", {"class": "score-overview"}) is None
|
cid_exam_scores_soup.find("div", {"class": "score-overview"}) is None
|
||||||
@@ -498,9 +552,10 @@ def test_exams(db, client):
|
|||||||
|
|
||||||
answer_lis = cid_exam_scores_soup.find(
|
answer_lis = cid_exam_scores_soup.find(
|
||||||
"ul", {"class": "score-answer-list"}
|
"ul", {"class": "score-answer-list"}
|
||||||
).find_all("li")
|
).find_all("li", {"class": "user-answer-li"})
|
||||||
assert len(answer_lis) == len(valid_answers) + 1
|
assert len(answer_lis) == len(valid_answers_by_question) + 1
|
||||||
assert "Not answered" in str(answer_lis[-1])
|
assert "Not answered" in str(answer_lis[-1])
|
||||||
|
assert str(answer_lis[-1]).count("Not answered") == 5
|
||||||
|
|
||||||
# Publish the results!
|
# Publish the results!
|
||||||
exam.publish_results = True
|
exam.publish_results = True
|
||||||
@@ -516,51 +571,62 @@ def test_exams(db, client):
|
|||||||
|
|
||||||
answer_lis = cid_exam_scores_soup.find(
|
answer_lis = cid_exam_scores_soup.find(
|
||||||
"ul", {"class": "score-answer-list"}
|
"ul", {"class": "score-answer-list"}
|
||||||
).find_all("li")
|
).find_all("li", {"class": "user-answer-li"})
|
||||||
|
|
||||||
assert len(answer_lis) == len(valid_answers) + 1
|
assert len(answer_lis) == len(valid_answers_by_question) + 1
|
||||||
assert "Not answered" in str(answer_lis[-1])
|
assert "Not answered" in str(answer_lis[-1])
|
||||||
|
assert str(answer_lis[-1]).count("Not answered") == 5
|
||||||
|
|
||||||
# Repetition....
|
# Repetition....
|
||||||
for n in range(
|
for n in range(
|
||||||
len(valid_answers)
|
len(valid_answers_by_question)
|
||||||
): # Check answers are visible if results published
|
): # Check no answers are visible if results not published
|
||||||
answer = valid_answers[n]
|
lis = answer_lis[n]
|
||||||
li = answer_lis[n]
|
#n = str(n + 1) # questions are not zero indexed (lists are)
|
||||||
|
|
||||||
|
for qidn, section_title in sections:
|
||||||
|
answer = valid_answers_by_question[n][qidn]
|
||||||
|
|
||||||
|
li = lis.find("li", attrs={"data-qidn": qidn})
|
||||||
|
|
||||||
|
assert li["class"][0].lower() in section_title
|
||||||
|
|
||||||
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 li.find("span", {"class": "correct-answer"}).string == "testanswer"
|
print(cid_exam_scores_soup.find("div", {"class": "score-overview"}))
|
||||||
|
|
||||||
if users_tested == 1:
|
# For long cases an unmarked answers is given a score of 4
|
||||||
# First user the answers will not have been saved
|
# Each user needs marking individually
|
||||||
assert (
|
assert (
|
||||||
cid_exam_scores_soup.find("div", {"class": "score-overview"})
|
cid_exam_scores_soup.find("div", {"class": "score-overview"})
|
||||||
.find("span", {"id": "total-score"})
|
.find("span", {"id": "total-score"})
|
||||||
.string
|
.string
|
||||||
== "0 (3 unmarked)"
|
== "4 (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)"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Mark the questions
|
||||||
|
# For longs this needs to be done for each user
|
||||||
|
question: Question
|
||||||
for question in exam.exam_questions.all():
|
for question in exam.exam_questions.all():
|
||||||
print(question)
|
print(question)
|
||||||
print(question.get_compare_answers())
|
|
||||||
try:
|
answers = question.get_unmarked_user_answers()
|
||||||
new_ans = Answer(
|
print(answers)
|
||||||
question=question,
|
for answer in answers:
|
||||||
answer=question.get_unmarked_user_answers().pop(),
|
answer.score = UserAnswer.ScoreOptions.EIGHT
|
||||||
status=Answer.MarkOptions.CORRECT,
|
answer.save()
|
||||||
)
|
|
||||||
new_ans.save()
|
#try:
|
||||||
except IndexError: # Final question does not have an answer
|
# new_ans = Answer(
|
||||||
pass
|
# question=question,
|
||||||
|
# answer=question.get_unmarked_user_answers().pop(),
|
||||||
|
# status=Answer.MarkOptions.CORRECT,
|
||||||
|
# )
|
||||||
|
# new_ans.save()
|
||||||
|
#except IndexError: # Final question does not have an answer
|
||||||
|
# pass
|
||||||
|
|
||||||
|
# TODO: test double marking
|
||||||
|
|
||||||
# Load the exam results page (again)
|
# Load the exam results page (again)
|
||||||
cid_exam_scores_res = client.get(exam_scores_url)
|
cid_exam_scores_res = client.get(exam_scores_url)
|
||||||
@@ -570,7 +636,7 @@ def test_exams(db, client):
|
|||||||
cid_exam_scores_soup.find("div", {"class": "score-overview"})
|
cid_exam_scores_soup.find("div", {"class": "score-overview"})
|
||||||
.find("span", {"id": "total-score"})
|
.find("span", {"id": "total-score"})
|
||||||
.string
|
.string
|
||||||
== "6"
|
== "28.0"
|
||||||
)
|
)
|
||||||
|
|
||||||
generated_questions.pop(-1).delete()
|
generated_questions.pop(-1).delete()
|
||||||
|
|||||||
@@ -1,7 +1,20 @@
|
|||||||
|
|
||||||
{% if view_all_results %}
|
{% if view_all_results %}
|
||||||
<div class="alert alert-info" role="alert">
|
<div class="alert alert-info" role="alert">
|
||||||
Exam state: Active [{{exam.active}}] / Published [{{exam.publish_results}}]
|
Exam state:
|
||||||
|
|
||||||
|
{% if exam.active %}
|
||||||
|
This exam is available to take.
|
||||||
|
{% else %}
|
||||||
|
This exam is NOT available to take.
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
|
||||||
|
{% if exam.publish_results %}
|
||||||
|
Results are published.
|
||||||
|
{% else %}
|
||||||
|
Results are NOT published.
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
{% if not exam.publish_results %}
|
{% if not exam.publish_results %}
|
||||||
|
|||||||
Reference in New Issue
Block a user