Newer
Older
""" This module tests all our quiz models"""
import os
import shutil
import tempfile
from django.core.files.uploadedfile import SimpleUploadedFile
from django.core.management import call_command
from django.utils.translation import get_language, activate
from django.test import TestCase, override_settings
from rest_framework.test import APITestCase
from .models import (
Sport,
Criterion,
CriterionRating,
CallToMove,
KnowledgeSnack,
Question,
)
class SportModelTest(TestCase):
def setUp(self):
self.name = "HIIT"
self.url = (
"https://www.buchsys.de/fu-berlin/angebote/aktueller_zeitraum/_HIIT_"
"-_High_Intensity_Interval_Training___HOME.html "
)
name=self.name,
url=self.url,
)
def test_sport_can_be_created(self):
"""New sport is written to the database"""
test_sport = Sport.objects.first()
self.assertEqual(test_sport.name, self.name)
self.assertEqual(test_sport.url, self.url)
class CriterionRatingTest(TestCase):
"""Tests the Relation between Sport and Criterion"""
def setUp(self):
self.name = "HIIT"
self.url = (
"https://www.buchsys.de/fu-berlin/angebote/aktueller_zeitraum/_HIIT_"
"-_High_Intensity_Interval_Training___HOME.html "
)
name=self.name,
url=self.url,
)
self.criterion = Criterion(name="Einzelsport")
self.criterion.save()
def test_can_rate_criterion_for_sport(self):
"""A rating for a specific criterion can be added to a sport"""
self.test_sport.rate(self.criterion, 10)
self.assertEqual(self.test_sport.criteria_ratings.first(), self.criterion)
self.assertEqual(self.test_sport.get_rating(self.criterion), 10)
def test_rating_can_be_changed(self):
"""
If a sport is rated again then the corresponding relation is changed,
instead of recreated
"""
first_rating_object = self.test_sport.rate(self.criterion, 10)
second_rating_object = self.test_sport.rate(self.criterion, 8)
self.assertEqual(first_rating_object, second_rating_object)
self.assertEqual(self.test_sport.get_rating(criterion=self.criterion), 8)
FIXTURE_IMAGES = os.path.join(settings.BASE_DIR, "quiz", "fixtures", "images")
MEDIA_ROOT = tempfile.mkdtemp(
suffix="testing"
) # Create a temp directory for files created during tests
@override_settings(MEDIA_ROOT=MEDIA_ROOT)
class CallToMoveTest(TestCase):
"""Tests the Model for Call To Move"""
def setUp(self):
tempfile.mkdtemp(suffix="testing") # recreate tmp folder before each test
self.text = "Kreise deine Arme vor der nächsten Frage 3x nach hinten"
self.image_name = "test_image.png"
self.image_path = os.path.join(FIXTURE_IMAGES, self.image_name)
self.image = SimpleUploadedFile(
name=self.image_name,
content=open(self.image_path, "rb").read(),
content_type="image/png",
)
self.call_to_move = CallToMove(text=self.text, image=self.image)
self.call_to_move.save()
def tearDown(self) -> None:
"""Delete the temp dir after each test"""
shutil.rmtree(MEDIA_ROOT, ignore_errors=True)
def test_can_create_call_to_move(self):
"""A call to move can be correctly created"""
self.assertEqual(self.call_to_move.text, self.text)
self.assertEqual(self.call_to_move.image.name, self.image.name)
def test_can_save_and_load_call_to_move(self):
"""A saved Call to Move can be loaded"""
call_to_move = CallToMove.objects.first()
self.assertEqual(call_to_move.text, self.text)
self.assertEqual(call_to_move.image.name, self.image.name)
@override_settings(MEDIA_ROOT=MEDIA_ROOT)
class KnowledgeSnackTest(TestCase):
"""Tests the Model for Knowledge Snack"""
def setUp(self):
tempfile.mkdtemp(suffix="testing") # recreate tmp folder before each test
self.text = (
"Dass Treppensteigen fast 5x so viele Kalorien verbrennt,"
"als bei der Nutzung des Aufzuges?"
)
self.image_name = "test_image.png"
self.image_path = os.path.join(FIXTURE_IMAGES, self.image_name)
self.image = SimpleUploadedFile(
name=self.image_name,
content=open(self.image_path, "rb").read(),
content_type="image/png",
)
self.knowledge_snack = KnowledgeSnack(text=self.text, image=self.image)
self.knowledge_snack.save()
def tearDown(self) -> None:
"""Delete the temp dir after each test"""
shutil.rmtree(MEDIA_ROOT, ignore_errors=True)
def test_can_create_knowledge_snack(self):
"""A knowledge snack can be correctly created"""
self.assertEqual(self.knowledge_snack.text, self.text)
self.assertEqual(self.knowledge_snack.image.name, self.image.name)
def test_can_save_and_load_call_to_move(self):
"""A saved Knowledge Snack can be loaded"""
knowledge_snack = KnowledgeSnack.objects.first()
self.assertEqual(knowledge_snack.text, self.text)
self.assertEqual(knowledge_snack.image.name, self.image.name)
class CriterionAndQuestionModelTest(TestCase):
"""Tests the Criterion and the Question model which have a One to One Relation"""
def setUp(self):
self.name = "Einzelsport"
self.criterion = Criterion(name=self.name)
self.criterion.save()
def test_criterion_can_be_saved_and_loaded(self):
"""New criterion can be loaded from the db"""
test_criterion = Criterion.objects.first()
self.assertEqual(test_criterion.name, self.name)
def test_question_can_be_added(self):
"""
If a question is added to a criterion, then it is accessible through the criterion.
"""
text = "Ich trainiere gerne mit anderen im Team"
question = Question(text=text, criterion=self.criterion)
question.save()
self.criterion.question = question
self.assertEqual(question, self.criterion.question)
def test_criterion_stays_if_question_deleted(self):
"""If assigned question is deleted the foreign key is set None"""
text = "Ich trainiere gerne mit anderen im Team"
question = Question(text=text, criterion=self.criterion)
question.save()
question.delete()
self.criterion = Criterion.objects.first()
with self.assertRaises(Criterion.question.RelatedObjectDoesNotExist):
self.criterion.question
def test_question_can_be_saved_and_loaded(self):
"""New Question is saved to the db and can be loaded"""
text = "Ich trainiere gerne mit anderen im Team"
Question(text=text, criterion=self.criterion).save()
test_question = Question.objects.first()
self.assertEqual(test_question.text, text)
class FixturesTest(TestCase):
"""
These are the tests for the fixtures in quiz/fixtures.
They can be used in automated tests, but also in development.
"""
fixtures = [
"sports.json",
"criteria.json",
"criterion_ratings.json",
"questions.json",
"calls_to_move.json",
"knowledge_snacks.json",
]
def test_sports_created_by_fixture(self):
"""If the sports fixture is loaded there exists a sport with the given data."""
sport = Sport.objects.get(pk=1)
self.assertEqual(sport.name, "Jiu Jitsu")
self.assertEqual(sport.url, "http://www.test.de")
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
def test_criterion_created_by_fixture(self):
"""If the criteria fixture is loaded there exists a criterion with the given data"""
criterion = Criterion.objects.get(pk=1)
self.assertEqual(criterion.name, "Outdoorsport")
def test_criterion_rating_created_by_fixture(self):
"""If the criterion_ratings fixture is loaded the given sport has a corresponding rating"""
criterion = Criterion.objects.get(name="Outdoorsport")
sport = Sport.objects.get(name="Jiu Jitsu")
self.assertEqual(sport.get_rating(criterion), 1)
def test_question_created_by_fixture(self):
"""If the questions fixture is loaded there exists a question with the given data"""
question = Question.objects.get(pk=1)
criterion = Criterion.objects.get(name="Outdoorsport")
self.assertEqual(question.text, "Ich mache am liebsten draußen Sport")
self.assertEqual(question.criterion, criterion)
def test_call_to_move_created_by_fixture(self):
"""If the call to move fixture is loaded there exists a call to move with the given data"""
call_to_move = CallToMove.objects.get(pk=1)
self.assertEqual(
call_to_move.text, "Kreise deine Arme vor der nächsten Frage 3x nach hinten"
)
self.assertEqual(call_to_move.image.name, "test_image.png")
def test_knowledge_snack_created_by_fixture(self):
"""
If the knowledge snack fixture is loaded there exists a knowledge snack with the given data
"""
knowledge_snack = KnowledgeSnack.objects.get(pk=1)
self.assertEqual(
knowledge_snack.text,
"Dass Treppensteigen fast 5x so viele Kalorien verbrennt, "
"als die Nutzung des Aufzuges?",
)
self.assertEqual(knowledge_snack.image.name, "logo.png")
class SeedingTest(TestCase):
"""Tests the seed_db command in quiz/management/commands"""
def test_seed_with_complete_data(self):
"""If seed_db is called then there exists a certain number of elements per model"""
# call the seed command without asking for confirmation
call_command("seed_db", ["--yes", "--no-superuser"])
n_sports = 5
n_criteria = 5
self.assertEqual(Sport.objects.count(), n_sports)
self.assertEqual(Criterion.objects.count(), n_criteria)
self.assertEqual(CriterionRating.objects.count(), n_sports * n_criteria)
self.assertEqual(Question.objects.count(), n_criteria)
self.assertEqual(CallToMove.objects.count(), 3)
self.assertEqual(KnowledgeSnack.objects.count(), 3)
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
class ModeltranslationFallbackTest(TestCase):
"""
Tests Behaviour of Modeltranslation when no translation is given
Also tests Default Language
"""
def setUp(self):
"""
Creates a Question and fills the german Translation
"""
self.criterion = Criterion(name="test")
self.question = Question(text="", criterion=self.criterion)
self.criterion.save()
self.question.save()
def test_default_language(self):
"""
Checks whether the Default Language is German
"""
cur_language = get_language()
self.assertEqual(cur_language, "de")
def test_vallback_value(self):
"""
Checks whether if no Translation is set, the Fallbackvalue is used
"""
self.assertEqual(self.question.text, ("No Translation for this Field",))
class Modeltranslation_One_Language_Test(TestCase):
"""
Tests Behaviour when only one language is defined
"""
def setUp(self):
"""
Creates a Question and fills the german Translation
"""
self.criterion = Criterion(name="test")
self.question = Question(text="", criterion=self.criterion)
self.question.text = "de_text"
self.criterion.save()
self.question.save()
def test_german_translation(self):
"""
Check whether obj.text returns the German Translation
"""
self.assertEqual(self.question.text, "de_text")
def test_fallback_value_translations(self):
"""
English Translation is not filled out, check whether german text is returned
"""
activate("en")
self.assertNotEqual(self.question.text, self.question.text_en)
self.assertEqual(self.question.text, self.question.text_de)
class Modeltranslation_Two_Languages_Test(TestCase):
"""
Tests Behaviour when two languages are defined
"""
def setUp(self):
"""
Creates a Question and fills both the german and english Translations
"""
self.criterion = Criterion(name="test")
self.question = Question(text="", criterion=self.criterion)
activate("de")
self.question.text = "de_text"
activate("en")
self.question.text = "en_text"
activate("de")
self.criterion.save()
self.question.save()
def test_german_translation(self):
"""
Tests whether German Translation is returned
"""
activate("de")
self.assertEqual(self.question.text, self.question.text_de)
self.assertNotEqual(self.question.text, self.question.text_en)
def test_english_translation(self):
"""
Tests whether English Translation is returned
"""
activate("en")
self.assertEqual(self.question.text, self.question.text_en)
self.assertNotEqual(self.question.text, self.question.text_de)
class APITest(APITestCase):
"""Tests the Django API"""
fixtures = [
"sports.json",
"criteria.json",
"criterion_ratings.json",
"questions.json",
]
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
def test_get_sport_returns_correct_data(self):
"""Test the API endpoint /sport/{id}"""
response = self.client.get(reverse("small-sport-list-detail", kwargs={"pk": 1}))
sport_data = {
"id": 1,
"name": "Jiu Jitsu",
"url": "http://www.test.de",
"criteria": [{"id": 1, "name": "Outdoorsport", "value": 1}],
}
self.assertDictEqual(response.data, sport_data)
def test_put_sport_makes_correct_changes(self):
"""
Test the API endpoint /sport/{id} for put requests
"""
sport_data = {
"name": "Karate",
"url": "http://www.test2.de",
"criteria": [{"id": 1, "name": "Outdoorsport", "value": 1}],
}
response = self.client.put(
reverse("small-sport-list-detail", kwargs={"pk": 1}),
data=sport_data,
format="json",
)
self.assertEqual(response.data["name"], sport_data["name"])
self.assertEqual(response.data["url"], sport_data["url"])
self.assertEqual(len(response.data["criteria"]), Criterion.objects.count())
self.assertDictEqual(
response.data["criteria"][0], {"id": 1, "name": "Outdoorsport", "value": 1}
)
def test_patch_sport_makes_correct_changes(self):
"""
Test the API endpoint /sport/{id} for patch requests
"""
sport_data = {
"criteria": [{"id": 1, "value": 3}],
}
response = self.client.patch(
reverse("small-sport-list-detail", kwargs={"pk": 1}),
data=sport_data,
format="json",
)
self.assertEqual(response.data["name"], "Jiu Jitsu")
self.assertEqual(response.data["url"], "http://www.test.de")
self.assertEqual(len(response.data["criteria"]), Criterion.objects.count())
self.assertDictEqual(
response.data["criteria"][0], {"id": 1, "name": "Outdoorsport", "value": 3}
)
def test_get_sports_returns_correct_data(self):
"""Test if API endpoint /sport returns correct sports list"""
response = self.client.get(reverse("small-sport-list-list"))
sport_data = [
{
"id": 1,
"is_filled": True,
"name": "Jiu Jitsu",
"url": "http://www.test.de",
}
]
self.assertListEqual(response.data["results"], sport_data)
self.assertEqual(response.data["count"], 1)
def test_post_sports_creates_correct_entry(self):
"""Test if post to /sport creates a correct object"""
sport_data_new = {
"name": "Karate",
"url": "http://www.test2.de",
}
response = self.client.post(
reverse("small-sport-list-list"), data=sport_data_new
)
self.assertEqual(response.data["name"], sport_data_new["name"])
self.assertEqual(response.data["url"], sport_data_new["url"])
self.assertEqual(len(response.data["criteria"]), Criterion.objects.count())
self.assertEqual(Sport.objects.count(), 2)
def test_delete_sports_creates_correct_entry(self):
"""Test if delete to /sports deletes an object"""
response = self.client.delete(
reverse("small-sport-list-detail", kwargs={"pk": 1})
)
self.assertEqual(Sport.objects.count(), 0)
def test_get_incomplete_sport_list(self):
"""
Tests if get to /sport/incomplete/ returns a list of incomplete sports
"""
# Set Up Incomplete Sport
response = self.client.patch(
reverse("small-sport-list-detail", kwargs={"pk": 1}),
data={"criteria": [{"id": 1, "value": -1}]},
format="json",
)
response = self.client.get(reverse("incomplete"))
self.assertEqual(len(response.data["results"]), 1)
self.assertEqual(response.data["results"][0]["name"], "Jiu Jitsu")
def test_get_criteria(self):
"""
Tests if get /critera/ returns a list of all criteria
"""
# Set Up Values
response = self.client.patch(
reverse("small-sport-list-detail", kwargs={"pk": 1}),
data={"criteria": [{"id": 1, "value": 7}]},
format="json",
)
response = self.client.get(reverse("criteria"))
self.assertEqual(len(response.data), Criterion.objects.count())
self.assertEqual(response.data[0]["number_of_sports_active"], 1)
self.assertEqual(response.data[0]["sum_of_weights"], 7)