Pamela Fox
commited on
Commit
·
6768aaa
1
Parent(s):
f243d4f
tests
Browse files- quizsite/production.py +1 -1
- quizzes/models.py +1 -16
- quizzes/templates/quizzes/display.html +4 -2
- quizzes/tests.py +113 -2
- quizzes/urls.py +1 -1
- quizzes/views.py +5 -4
quizsite/production.py
CHANGED
@@ -1,4 +1,4 @@
|
|
1 |
-
from .settings import *
|
2 |
import os
|
3 |
|
4 |
# Configure the domain name using the environment variable
|
|
|
1 |
+
from .settings import * # noqa
|
2 |
import os
|
3 |
|
4 |
# Configure the domain name using the environment variable
|
quizzes/models.py
CHANGED
@@ -6,22 +6,7 @@ class Quiz(models.Model):
|
|
6 |
name = models.CharField(max_length=100)
|
7 |
|
8 |
def __str__(self):
|
9 |
-
return
|
10 |
-
|
11 |
-
def display(self):
|
12 |
-
# Display the quiz name
|
13 |
-
print(f"Welcome to the quiz on {self.name}!")
|
14 |
-
# Initialize the correct counter to 0
|
15 |
-
correct_count = 0
|
16 |
-
# Iterate through the questions
|
17 |
-
# Display each question
|
18 |
-
# Increment the correct counter accordingly
|
19 |
-
for question in self.questions:
|
20 |
-
question.display()
|
21 |
-
if question.answer_status == "correct":
|
22 |
-
correct_count += 1
|
23 |
-
# Print the ratio of correct/total
|
24 |
-
print(f"You got {correct_count}/{len(self.questions)} correct.")
|
25 |
|
26 |
|
27 |
class Question(models.Model):
|
|
|
6 |
name = models.CharField(max_length=100)
|
7 |
|
8 |
def __str__(self):
|
9 |
+
return self.name
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
10 |
|
11 |
|
12 |
class Question(models.Model):
|
quizzes/templates/quizzes/display.html
CHANGED
@@ -11,6 +11,7 @@
|
|
11 |
<h1>Quiz: {{ quiz.name }}</h1>
|
12 |
|
13 |
<section class="bg-warning" style="padding:12px">
|
|
|
14 |
<form id="question-form" action="{% url 'quizzes:grade_question' question.id %}" method="post">
|
15 |
{% csrf_token %}
|
16 |
|
@@ -41,10 +42,11 @@
|
|
41 |
<button type="submit" class="btn btn-primary">Check answers</button>
|
42 |
</form>
|
43 |
|
44 |
-
|
45 |
<div id="question-feedback" style="margin-top:16px">
|
46 |
</div>
|
47 |
-
|
|
|
|
|
48 |
</section>
|
49 |
|
50 |
{% if next_question %}
|
|
|
11 |
<h1>Quiz: {{ quiz.name }}</h1>
|
12 |
|
13 |
<section class="bg-warning" style="padding:12px">
|
14 |
+
{% if question %}
|
15 |
<form id="question-form" action="{% url 'quizzes:grade_question' question.id %}" method="post">
|
16 |
{% csrf_token %}
|
17 |
|
|
|
42 |
<button type="submit" class="btn btn-primary">Check answers</button>
|
43 |
</form>
|
44 |
|
|
|
45 |
<div id="question-feedback" style="margin-top:16px">
|
46 |
</div>
|
47 |
+
{% else %}
|
48 |
+
Sorry, that question doesn't exist in this quiz.
|
49 |
+
{% endif %}
|
50 |
</section>
|
51 |
|
52 |
{% if next_question %}
|
quizzes/tests.py
CHANGED
@@ -1,3 +1,114 @@
|
|
1 |
-
|
|
|
2 |
|
3 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from django.test import TestCase
|
2 |
+
from django.urls import reverse
|
3 |
|
4 |
+
from .models import Quiz, Question, FreeTextAnswer, MultipleChoiceAnswer
|
5 |
+
|
6 |
+
|
7 |
+
def create_quiz():
|
8 |
+
quiz = Quiz.objects.create(name="Butterflies")
|
9 |
+
question = Question.objects.create(quiz=quiz, prompt="What plant do Swallowtail caterpillars eat?")
|
10 |
+
answer = MultipleChoiceAnswer.objects.create(
|
11 |
+
question=question, correct_answer="Dill", choices=["Thistle", "Milkweed", "Dill"]
|
12 |
+
)
|
13 |
+
return quiz, question, answer
|
14 |
+
|
15 |
+
|
16 |
+
class FreeTextAnswerModelTests(TestCase):
|
17 |
+
def test_case_insensitive(self):
|
18 |
+
ans = FreeTextAnswer(correct_answer="Milkweed", case_sensitive=False)
|
19 |
+
self.assertTrue(ans.is_correct("Milkweed"))
|
20 |
+
self.assertTrue(ans.is_correct("milkweed"))
|
21 |
+
self.assertFalse(ans.is_correct("thistle"))
|
22 |
+
|
23 |
+
def test_case_sensitive(self):
|
24 |
+
ans = FreeTextAnswer(correct_answer="Armeria Maritima", case_sensitive=True)
|
25 |
+
self.assertFalse(ans.is_correct("armeria maritima"))
|
26 |
+
self.assertTrue(ans.is_correct("Armeria Maritima"))
|
27 |
+
|
28 |
+
|
29 |
+
class MultipleChoiceAnswerModelTests(TestCase):
|
30 |
+
def test_choices(self):
|
31 |
+
ans = MultipleChoiceAnswer(correct_answer="Dill", choices=["Milkweed", "Dill", "Thistle"])
|
32 |
+
self.assertTrue(ans.is_correct("Dill"))
|
33 |
+
self.assertFalse(ans.is_correct("dill"))
|
34 |
+
self.assertFalse(ans.is_correct("Milkweed"))
|
35 |
+
|
36 |
+
|
37 |
+
class QuizModelTests(TestCase):
|
38 |
+
def test_quiz_relations(self):
|
39 |
+
quiz = Quiz.objects.create(name="Butterflies")
|
40 |
+
q1 = Question.objects.create(quiz=quiz, prompt="What plant do Swallowtail caterpillars eat?")
|
41 |
+
a1 = MultipleChoiceAnswer.objects.create(
|
42 |
+
question=q1, correct_answer="Dill", choices=["Thistle", "Milkweed", "Dill"]
|
43 |
+
)
|
44 |
+
q2 = Question.objects.create(quiz=quiz, prompt="What plant do Monarch caterpillars eat?")
|
45 |
+
a2 = FreeTextAnswer.objects.create(question=q2, correct_answer="Milkweed", case_sensitive=False)
|
46 |
+
self.assertEqual(len(quiz.question_set.all()), 2)
|
47 |
+
self.assertEqual(q1.multiplechoiceanswer, a1)
|
48 |
+
self.assertEqual(q2.freetextanswer, a2)
|
49 |
+
|
50 |
+
|
51 |
+
class IndexViewTests(TestCase):
|
52 |
+
def test_no_quizzes(self):
|
53 |
+
response = self.client.get(reverse("quizzes:index"))
|
54 |
+
self.assertEqual(response.status_code, 200)
|
55 |
+
self.assertContains(response, "No quizzes are available.")
|
56 |
+
self.assertQuerysetEqual(response.context["quiz_list"], [])
|
57 |
+
|
58 |
+
def test_one_quiz(self):
|
59 |
+
quiz, _, _ = create_quiz()
|
60 |
+
response = self.client.get(reverse("quizzes:index"))
|
61 |
+
self.assertQuerysetEqual(
|
62 |
+
response.context["quiz_list"],
|
63 |
+
[quiz],
|
64 |
+
)
|
65 |
+
|
66 |
+
|
67 |
+
class DisplayQuizViewTests(TestCase):
|
68 |
+
def test_quiz_404(self):
|
69 |
+
url = reverse("quizzes:display_quiz", args=(12,))
|
70 |
+
response = self.client.get(url)
|
71 |
+
self.assertEqual(response.status_code, 404)
|
72 |
+
|
73 |
+
def test_quiz_redirects(self):
|
74 |
+
quiz, question, _ = create_quiz()
|
75 |
+
url = reverse("quizzes:display_quiz", args=(quiz.pk,))
|
76 |
+
response = self.client.get(url)
|
77 |
+
self.assertRedirects(response, reverse("quizzes:display_question", args=(quiz.pk, question.pk)))
|
78 |
+
|
79 |
+
|
80 |
+
class DisplayQuestionViewTests(TestCase):
|
81 |
+
def test_quiz_404(self):
|
82 |
+
url = reverse("quizzes:display_question", args=(12, 1))
|
83 |
+
response = self.client.get(url)
|
84 |
+
self.assertEqual(response.status_code, 404)
|
85 |
+
|
86 |
+
def test_question_404(self):
|
87 |
+
quiz, question, _ = create_quiz()
|
88 |
+
url = reverse("quizzes:display_question", args=(quiz.pk, question.pk + 100))
|
89 |
+
response = self.client.get(url)
|
90 |
+
self.assertContains(response, "that question doesn't exist")
|
91 |
+
|
92 |
+
def test_quiz_question_exists(self):
|
93 |
+
quiz, question, answer = create_quiz()
|
94 |
+
|
95 |
+
url = reverse("quizzes:display_question", args=(quiz.pk, question.pk))
|
96 |
+
response = self.client.get(url)
|
97 |
+
self.assertContains(response, quiz.name)
|
98 |
+
self.assertContains(response, question.prompt)
|
99 |
+
self.assertContains(response, answer.choices[0])
|
100 |
+
|
101 |
+
|
102 |
+
class GradeQuestionViewTests(TestCase):
|
103 |
+
def test_question_404(self):
|
104 |
+
url = reverse("quizzes:grade_question", args=(12,))
|
105 |
+
response = self.client.get(url)
|
106 |
+
self.assertEqual(response.status_code, 404)
|
107 |
+
|
108 |
+
def test_question_correct(self):
|
109 |
+
_, question, answer = create_quiz()
|
110 |
+
|
111 |
+
url = reverse("quizzes:grade_question", args=(question.pk,))
|
112 |
+
response = self.client.post(url, {"answer": answer.correct_answer})
|
113 |
+
self.assertTrue(response.context["is_correct"])
|
114 |
+
self.assertEqual(response.context["correct_answer"], answer.correct_answer)
|
quizzes/urls.py
CHANGED
@@ -5,7 +5,7 @@ from . import views
|
|
5 |
app_name = "quizzes"
|
6 |
|
7 |
urlpatterns = [
|
8 |
-
path("", views.
|
9 |
path("<int:quiz_id>/", views.display_quiz, name="display_quiz"),
|
10 |
path("<int:quiz_id>/questions/<int:question_id>", views.display_question, name="display_question"),
|
11 |
path("questions/<int:question_id>/grade/", views.grade_question, name="grade_question"),
|
|
|
5 |
app_name = "quizzes"
|
6 |
|
7 |
urlpatterns = [
|
8 |
+
path("", views.IndexView.as_view(), name="index"),
|
9 |
path("<int:quiz_id>/", views.display_quiz, name="display_quiz"),
|
10 |
path("<int:quiz_id>/questions/<int:question_id>", views.display_question, name="display_question"),
|
11 |
path("questions/<int:question_id>/grade/", views.grade_question, name="grade_question"),
|
quizzes/views.py
CHANGED
@@ -1,13 +1,13 @@
|
|
1 |
from django.shortcuts import get_object_or_404, render, redirect
|
2 |
from django.urls import reverse
|
|
|
3 |
|
4 |
from .models import Quiz, Question
|
5 |
|
6 |
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
return render(request, "quizzes/index.html", context)
|
11 |
|
12 |
|
13 |
def display_quiz(request, quiz_id):
|
@@ -26,6 +26,7 @@ def display_question(request, quiz_id, question_id):
|
|
26 |
current_question = question
|
27 |
if ind != len(questions) - 1:
|
28 |
next_question = questions[ind + 1]
|
|
|
29 |
return render(
|
30 |
request,
|
31 |
"quizzes/display.html",
|
|
|
1 |
from django.shortcuts import get_object_or_404, render, redirect
|
2 |
from django.urls import reverse
|
3 |
+
from django.views import generic
|
4 |
|
5 |
from .models import Quiz, Question
|
6 |
|
7 |
|
8 |
+
class IndexView(generic.ListView):
|
9 |
+
model = Quiz
|
10 |
+
template_name = "quizzes/index.html"
|
|
|
11 |
|
12 |
|
13 |
def display_quiz(request, quiz_id):
|
|
|
26 |
current_question = question
|
27 |
if ind != len(questions) - 1:
|
28 |
next_question = questions[ind + 1]
|
29 |
+
|
30 |
return render(
|
31 |
request,
|
32 |
"quizzes/display.html",
|