more cid user anatomy testing

This commit is contained in:
Ross
2022-12-05 12:22:26 +00:00
parent 2984f27249
commit a467f24e10
8 changed files with 170 additions and 51 deletions
+9 -1
View File
@@ -199,7 +199,15 @@ class AnatomyQuestion(models.Model):
)
)
def get_unmarked_user_answers(self, exam_pk=None):
def get_unmarked_user_answers(self, exam_pk: int|None = None):
"""_summary_
Args:
exam_pk (_type_, optional): _description_. Defaults to None.
Returns:
set: set of unmarked user strings
"""
if exam_pk is None:
user_answers = set([i.answer_compare for i in self.cid_user_answers.all()])
else:
@@ -14,13 +14,16 @@
</div>
<div class="anatomy">
{% include 'user_score_header.html' %}
<ul class="score-answer-list">{% for ans, score, correct_answer in answers_and_marks %}
<li class="user-answer-li">Question {{forloop.counter}} - Correct answer: <span class="correct-answer">{{correct_answer }}</span></li>
<span class="user-answer-score user-answer-score-{{score}} physics-ans">
<pre>{{ans}}</pre> ({{score}})
</span>
<span class="view-question-link" data-qn={{forloop.counter0}}>View</span>
{% endfor %}
<ul class="score-answer-list">
{% for ans, score, correct_answer in answers_and_marks %}
<li class="user-answer-li" data-question-number="{{forloop.counter}}">Question {{forloop.counter}} - Correct answer: <span class="correct-answer">{{correct_answer}}</span>
<br/>
<span class="user-answer-score user-answer-score-{{score}} physics-ans">
<pre>{{ans}}</pre> ({{score}})
</span>
<span class="view-question-link" data-qn={{forloop.counter0}}>View</span>
</li>
{% endfor %}
</ul>
{% include 'user_scores_footer.html' %}
</div>
+112 -6
View File
@@ -15,7 +15,7 @@ from bs4 import BeautifulSoup
from anatomy.views import GenericExamViews as AnatomyExamViews
from anatomy.models import Exam, AnatomyQuestion as Question, QuestionType, Structure
from anatomy.models import Answer, Exam, AnatomyQuestion as Question, QuestionType, Structure
from generic.models import CidUser, CidUserGroup
@@ -66,7 +66,7 @@ def create_question_types(db):
question_type.save()
def create_question(exam):
def create_question(exam, answer=None):
# Just assign random stuff
image = tempfile.NamedTemporaryFile(
@@ -79,6 +79,15 @@ def create_question(exam):
image=image.name,
)
question.exams.set([exam])
# Create an answer for the question
if answer is None:
answer_text = "testanswer"
else:
answer_text = answer
answer = Answer(question=question, answer=answer_text, answer_compare=answer_text, status=Answer.MarkOptions.CORRECT)
answer.save()
return question
@@ -219,21 +228,118 @@ def test_exams(db, client):
# Test submission
# give three answers
print("post_json", post_json)
res = client.post(reverse("global_exam_answers_submit"), data=post_json)
json_res = json.loads(res.content)
print(json_res)
assert json_res["success"] == True
assert json_res["question_count"] == 3
# We can then check the answers have been submitted (and can be viewed by the user)
# Get overview scores page
cid_scores_res = client.get(
reverse(f"cid_scores", kwargs={"cid": 1001, "passcode": "EFGH"})
)
cid_scores_soup = BeautifulSoup(cid_scores_res.content, "html.parser")
assigned_exams = cid_scores_soup.find(id="exam-assigned").find_all("li")
print(assigned_exams)
print(cid_scores_soup.find("div", {"id" : "exam-assigned"}))
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})
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
# Load the exam results page
cid_exam_scores_res = client.get(
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")
# 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)
answer_lis = cid_exam_scores_soup.find("ul", {"class": "score-answer-list"}).find_all("li")
assert len(answer_lis) == len(valid_answers)
for n in range(len(valid_answers)): # Check no answers are visible if results not published
answer = valid_answers[n]
li = answer_lis[n]
assert answer["ans"] in str(li) # Check that the saved answer is shown
assert li.find("span", {"class": "correct-answer"}).string == "*****" # 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
# Add another question to the exam
create_question(exam)
# Load the exam results page (again)
cid_exam_scores_res = client.get(
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")
answer_lis = cid_exam_scores_soup.find("ul", {"class": "score-answer-list"}).find_all("li")
assert len(answer_lis) == len(valid_answers) + 1
assert "Not answered" in str(answer_lis[-1])
# Publish the results!
exam.publish_results = True
exam.save()
# Load the exam results page (again)
cid_exam_scores_res = client.get(
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")
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")
assert len(answer_lis) == len(valid_answers) + 1
assert "Not answered" in str(answer_lis[-1])
# Repetition....
for n in range(len(valid_answers)): # Check answers are visible if results published
answer = valid_answers[n]
li = answer_lis[n]
assert answer["ans"] in str(li) # Check that the saved answer is shown
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)"
for question in exam.exam_questions.all():
try:
new_ans = Answer(question=question, answer=question.get_unmarked_user_answers().pop(), status=Answer.MarkOptions.CORRECT)
new_ans.save()
except KeyError: # Final question does not have an answer
pass
# Load the exam results page (again)
cid_exam_scores_res = client.get(
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")
assert cid_exam_scores_soup.find("div", {"class": "score-overview"}).find("span", {"id": "total-score"}).string == "6"
+6 -6
View File
@@ -423,12 +423,12 @@ class QuestionNote(models.Model):
return f"{self.note_type} - {self.note}"
EXAM_TYPES = (
("Physics", "physics_exams"),
("Rapids", "rapid_exams"),
("SBAs", "sba_exams"),
("Anatomy", "anatomy_exams"),
("Longs", "longs_exams"),
("CaseCollection", "casecollection_exams"),
("physics", "physics_exams"),
("rapids", "rapid_exams"),
("sbas", "sba_exams"),
("anatomy", "anatomy_exams"),
("longs", "longs_exams"),
("casecollection", "casecollection_exams"),
)
class CidUser(models.Model):
+1 -1
View File
@@ -29,7 +29,7 @@
<p>
{% with object.get_cid_exams as exam_map %}
{% for exam_type, exams in exam_map.items %}
{% for exam_type, exams in exam_map %}
<h4>{{exam_type}}</h4>
<ul>
{% for exam in exams %}
+1 -1
View File
@@ -151,7 +151,7 @@ handler500 = "rad.views.server_error"
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
#urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
urlpatterns += static("/rts/", document_root="rts")
import debug_toolbar
+28 -28
View File
@@ -7,44 +7,44 @@
<div id="exam-assigned">
The following exams will be available to take when active.
{% for exam_type, exams in available_exams %}
<h4>{{exam_type}}</h4>
<h4>{{exam_type|title}}</h4>
<ul class='{{exam_type}}'>
{% for exam in exams %}
<li class="exam"><a href="{{exam.get_take_url}}?cid={{cid}}&passcode={{passcode}}" target="_blank">{{exam.name}} {% if exam.active %}[Active]{% endif %}</a></li>
<li class="exam" data-exam-id="{{exam.pk}}"><a href="{{exam.get_take_url}}?cid={{cid}}&passcode={{passcode}}" target="_blank">{{exam.name}} {% if exam.active %}[Active]{% endif %}</a></li>
{% endfor %}
</ul>
{% endfor %}
</div>
{% if all_exams %}
</div>
<h3>Exam results</h3>
<div id="exam-results">
The following exam results been found. Click to view answers (and scores when the results are published):
{% for exam_type, exams in all_exams %}
{% if exams %}
<h4>{{exam_type|title}}</h4>
<ul class='{{exam_type}}'>
{% for exam in exams %}
<li class="exam"><a href="{% url exam_type|add:':exam_scores_cid_user' pk=exam.pk cid=cid passcode=passcode %}">{{exam.name}}</a> {% if exam.active %}[Active]{% endif %} {% if exam.publish_results %}[Results Published]{% endif %}</li>
{% endfor %}
</ul>
{% endif %}
{% endfor %}
</div>
{% endif %}
{% if all_exams %}
<h3>Exam results</h3>
<div id="exam-results">
The following exam results been found. Click to view answers (and scores when the results are published):
{% for exam_type, exams in all_exams %}
{% if exams %}
<h4>{{exam_type|title}}</h4>
<ul class='{{exam_type}}'>
{% for exam in exams %}
<li class="exam" data-exam-id="{{exam.pk}}"><a href="{% url exam_type|add:':exam_scores_cid_user' pk=exam.pk cid=cid passcode=passcode %}">{{exam.name}}</a> {% if exam.active %}[Active]{% endif %} {% if exam.publish_results %}[Results Published]{% endif %}</li>
{% endfor %}
</ul>
{% endif %}
{% endfor %}
</div>
{% endif %}
{% if case_collections %}
<div>
<h3>Case Collection</h3>
The following Case Collections have been found.
<ul>
{% if case_collections %}
<div>
<h3>Case Collection</h3>
The following Case Collections have been found.
<ul>
{% for collection in case_collections %}
<li><a href="{{collection.get_take_url}}?cid={{cid}}&passcode={{passcode}}">{{collection.name}}</a> {% if collection.active %}[Active]{% endif %} {% if collection.publish_results %}[Results Published]{% endif %}</li>
{% endfor %}
</ul>
</div>
{% endif %}
</ul>
</div>
{% endif %}
</div>
</div>
{% endblock %}
+3 -1
View File
@@ -1,8 +1,10 @@
{% if view_all_results or exam.publish_results %}
<br /> Total mark: {{ total_score }} / {{max_score}}
<div class="score-overview">
<br /> Total marks: <span id="total-score">{{ total_score }}</span> / <span id="max-score">{{max_score}}</span>
{% if normalised_score %}
<br /> Normalised score: {{ normalised_score }}
{% endif %}
</div>
{% endif %}
<div>
{% if cid %}