Skip to content
Snippets Groups Projects
Commit 527aaa41 authored by borzechof99's avatar borzechof99 :whale2:
Browse files

Add QuestionOrder-Model, Tests, and Seeding

parent 80033041
No related branches found
No related tags found
No related merge requests found
......@@ -15,6 +15,7 @@ from quiz.models import (
Question,
CallToMove,
KnowledgeSnack,
QuestionOrder,
)
......@@ -171,3 +172,12 @@ class Command(BaseCommand):
activate("en")
k_s.text = text[1]
k_s.save()
# Create Entries in the QuestionOrder DB
QuestionOrder.objects.create_entry_at_end("question", 1)
QuestionOrder.objects.create_entry_at_end("snack")
QuestionOrder.objects.create_entry_at_end("question", 3)
QuestionOrder.objects.create_entry_at_end("activity")
QuestionOrder.objects.create_entry_at_end("question", 2)
QuestionOrder.objects.create_entry_at_end("question", 4)
# Generated by Django 3.2 on 2021-06-27 14:00
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('quiz', '0006_auto_20210612_1230'),
]
operations = [
migrations.CreateModel(
name='QuestionOrder',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('order_id', models.IntegerField(null=True)),
('type_of_slot', models.TextField(choices=[('question', 'question'), ('snack', 'snack'), ('activity', 'activity')], default='snack')),
('question_id', models.IntegerField(default=-1)),
],
),
]
......@@ -92,3 +92,96 @@ class Question(models.Model):
def __str__(self):
return self.text
class QuestionOrderManager(models.Manager):
"""
Manages Handling of QuestionOrder Objects
Includes create_entry_at_end, which handles Creation of new Entries
and delete_entry, which deletes one entry and changes the order_id of the following entries
"""
def create_entry_at_end(self, type_of_slot, question_id=None):
if type_of_slot == "question" and question_id is None:
raise ValueError(
"A Question ID must be given if the Type of the Slot is Question"
)
elif type_of_slot not in ["question", "snack", "activity"]:
raise ValueError(
f'{type_of_slot} not in valid choice list ["question", "snack", "activity"]'
)
entry = QuestionOrder()
entry.type_of_slot = type_of_slot
# If question_id is None, fill it out as -1, else take the question_id value
if entry.type_of_slot == "question":
entry.question_id = question_id
# If no Entry exists, highest_current_order is 0, otherwise highest order_id
if self.count() == 0:
highest_current_order = 0
else:
# "latest" returns highest value (normally used for dates, I believe)
highest_current_order = self.latest("order_id").order_id
entry.order_id = highest_current_order + 1
entry.save()
return entry
def delete_entry(self, given_order_id):
# Delete must be called on an instance, not a queryset
entry = self.get(order_id = given_order_id)
entry.delete()
larger_entries = self.filter(order_id__gte=given_order_id)
# The Primary Key of an Object cannot be changed, really, instead a new Object is created when the PK changes
# This means that we need to delete the original Object so that we only have the new pk
for entry in larger_entries.iterator():
entry.order_id = entry.order_id - 1
entry.save()
def delete_entry_by_question_id(self, given_question_id):
queryset = self.filter(question_id = given_question_id)
if queryset.count() == 0:
# If the Question doesn't exist in the Order, we don't need to do anything
return
# If the question is in the Order more than once for some reason, sweat not, we will delete them all
for entry in queryset.iterator():
self.delete_entry(entry.order_id)
class QuestionOrder(models.Model):
"""
Defines the order of the Questions, Snacks, and Activities given in the Quiz
Default Choice for type_of_slot is "snack" instead of "question",
because "snack" doesn't need a question_id and is therefore a safer choice
"""
objects = QuestionOrderManager()
order_id = models.IntegerField(null=True)
type_of_slot = models.TextField(
choices=[
("question", "question"),
("snack", "snack"),
("activity", "activity"),
],
default="snack",
)
question_id = models.IntegerField(default=-1)
def __str__(self):
return f"Entry {self.order_id}: {self.type_of_slot}"
......@@ -10,6 +10,7 @@ from django.utils.translation import get_language, activate
from django.test import TestCase, override_settings
from django.conf import settings
from .models import (
QuestionOrder,
Sport,
Criterion,
CriterionRating,
......@@ -379,3 +380,153 @@ class Modeltranslation_Two_Languages_Test(TestCase):
self.assertEqual(self.question.text, self.question.text_en)
self.assertNotEqual(self.question.text, self.question.text_de)
class QuestionOrder_Test(TestCase):
"""
Tests the QuestionOrder Model and its Manager
"""
def setUp(self):
"""
Sets up DB with Five Default Questions from seed_db
"""
# Setup the Database with seeded values
call_command("seed_db", ["--yes", "--no-superuser"])
# We get Five Questions, that's all we need
# Also, we assume that we are working with an empty QuestionOrder Table
QuestionOrder.objects.all().delete()
def test_check_empty_oder_table(self):
"""
Checks Whether Initial QuestionOrder Table is Empty
"""
self.assertEqual(QuestionOrder.objects.count(), 0)
def test_add_question_to_table(self):
"""
Tests adding a Question to the Table
"""
entry = QuestionOrder.objects.create_entry_at_end("question", question_id=2)
self.assertEqual(QuestionOrder.objects.count(), 1)
self.assertEqual(entry.order_id, 1)
self.assertEqual(entry.type_of_slot, "question")
self.assertEqual(entry.question_id, 2)
def test_add_snack_activity_to_table(self):
"""
Tests adding a Snack and Activity to the Table
"""
entry = QuestionOrder.objects.create_entry_at_end("snack")
self.assertEqual(QuestionOrder.objects.count(), 1)
self.assertEqual(entry.order_id, 1)
self.assertEqual(entry.type_of_slot, "snack")
self.assertEqual(entry.question_id, -1)
# Add Question_ID to activity to see whether it is correctly ignored
entry = QuestionOrder.objects.create_entry_at_end("activity", question_id=3)
self.assertEqual(QuestionOrder.objects.count(), 2)
self.assertEqual(entry.order_id, 2)
self.assertEqual(entry.type_of_slot, "activity")
self.assertEqual(entry.question_id, -1)
def test_autoincrementing_id(self):
"""
When Entries are deleted, do the automatically generated PK-Fields reuse the IDs or do they stil increment?
"""
# Create First and Second Entry
entry = QuestionOrder.objects.create_entry_at_end("question", question_id=1)
self.assertEqual(QuestionOrder.objects.count(), 1)
self.assertEqual(entry.order_id, 1)
entry = QuestionOrder.objects.create_entry_at_end("question", question_id=2)
self.assertEqual(QuestionOrder.objects.count(), 2)
self.assertEqual(entry.order_id, 2)
# Check Second Entry
most_recent_entry = QuestionOrder.objects.get(order_id=2)
self.assertEqual(most_recent_entry.order_id, 2)
# Delete Second Entry
QuestionOrder.objects.delete_entry(2)
self.assertEqual(QuestionOrder.objects.count(), 1)
# Create Third Entry and Check whether the ID of the Second Entry is Reused (it should be)
entry = QuestionOrder.objects.create_entry_at_end("question", question_id=3)
self.assertEqual(QuestionOrder.objects.count(), 2)
self.assertEqual(entry.order_id, 2)
def test_removing_entry_in_middle(self):
"""
When an Entry in the Middle is Removed, the order_ids larger than the removed entry should be decremented
"""
# Create Three Questions
first_entry = QuestionOrder.objects.create_entry_at_end(
"question", question_id=1
)
self.assertEqual(QuestionOrder.objects.count(), 1)
self.assertEqual(first_entry.order_id, 1)
second_entry = QuestionOrder.objects.create_entry_at_end(
"question", question_id=2
)
self.assertEqual(QuestionOrder.objects.count(), 2)
self.assertEqual(second_entry.order_id, 2)
third_entry = QuestionOrder.objects.create_entry_at_end(
"question", question_id=3
)
self.assertEqual(QuestionOrder.objects.count(), 3)
self.assertEqual(third_entry.order_id, 3)
# Use Custom Deletion Method to remove second Entry
QuestionOrder.objects.delete_entry(2)
# Check whether Question Higher than the deleted one went down one slot
self.assertEqual(QuestionOrder.objects.count(), 2)
last_entry = QuestionOrder.objects.last()
self.assertEqual(last_entry.order_id, 2)
self.assertEqual(last_entry.question_id, 3)
def test_removing_entry_in_middle_by_question_id(self):
"""
When an Entry in the Middle is Removed, the order_ids larger than the removed entry should be decremented
"""
# Create Three Questions
first_entry = QuestionOrder.objects.create_entry_at_end(
"question", question_id=1
)
self.assertEqual(QuestionOrder.objects.count(), 1)
self.assertEqual(first_entry.order_id, 1)
second_entry = QuestionOrder.objects.create_entry_at_end(
"question", question_id=2
)
self.assertEqual(QuestionOrder.objects.count(), 2)
self.assertEqual(second_entry.order_id, 2)
third_entry = QuestionOrder.objects.create_entry_at_end(
"question", question_id=3
)
self.assertEqual(QuestionOrder.objects.count(), 3)
self.assertEqual(third_entry.order_id, 3)
# Use Custom Deletion Method to remove second Entry
QuestionOrder.objects.delete_entry_by_question_id(2)
# Check whether Question Higher than the deleted one went down one slot
self.assertEqual(QuestionOrder.objects.count(), 2)
last_entry = QuestionOrder.objects.last()
self.assertEqual(last_entry.order_id, 2)
self.assertEqual(last_entry.question_id, 3)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment