more cid user anatomy testing
This commit is contained in:
+9
-1
@@ -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
@@ -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
@@ -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):
|
||||
|
||||
@@ -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
@@ -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
@@ -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 %}
|
||||
|
||||
@@ -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 %}
|
||||
|
||||
Reference in New Issue
Block a user