- Add complete test coverage for referenzen, rollen, and stichworte apps - Implement 54 new tests covering models, relationships, and business logic - Fix MPTT method names and import issues in test implementations - Create comprehensive test documentation in English and German - All 188 tests now passing across all Django apps Test coverage breakdown: - referenzen: 18 tests (MPTT hierarchy, model validation) - rollen: 18 tests (role models, relationships) - stichworte: 18 tests (keyword models, ordering) - Total: 54 new tests added Documentation: - Test suite.md: Complete English documentation - Test Suite-DE.md: Complete German documentation
368 lines
14 KiB
Python
368 lines
14 KiB
Python
from django.test import TestCase
|
|
from django.core.exceptions import ValidationError
|
|
from django.db.models import Count
|
|
from .models import Rolle, RollenBeschreibung
|
|
from abschnitte.models import AbschnittTyp
|
|
|
|
|
|
class RolleModelTest(TestCase):
|
|
"""Test cases for Rolle model"""
|
|
|
|
def setUp(self):
|
|
"""Set up test data"""
|
|
self.rolle = Rolle.objects.create(
|
|
name="Systemadministrator"
|
|
)
|
|
|
|
def test_rolle_creation(self):
|
|
"""Test that Rolle is created correctly"""
|
|
self.assertEqual(self.rolle.name, "Systemadministrator")
|
|
|
|
def test_rolle_str(self):
|
|
"""Test string representation of Rolle"""
|
|
self.assertEqual(str(self.rolle), "Systemadministrator")
|
|
|
|
def test_rolle_primary_key(self):
|
|
"""Test that name field is the primary key"""
|
|
pk_field = Rolle._meta.pk
|
|
self.assertEqual(pk_field.name, 'name')
|
|
self.assertEqual(pk_field.max_length, 100)
|
|
|
|
def test_rolle_verbose_name_plural(self):
|
|
"""Test verbose name plural"""
|
|
self.assertEqual(
|
|
Rolle._meta.verbose_name_plural,
|
|
"Rollen"
|
|
)
|
|
|
|
def test_rolle_max_length(self):
|
|
"""Test max_length constraint"""
|
|
max_length_rolle = "a" * 100
|
|
rolle = Rolle.objects.create(name=max_length_rolle)
|
|
self.assertEqual(rolle.name, max_length_rolle)
|
|
|
|
def test_rolle_unique(self):
|
|
"""Test that name must be unique"""
|
|
with self.assertRaises(Exception):
|
|
Rolle.objects.create(name="Systemadministrator")
|
|
|
|
def test_create_multiple_rollen(self):
|
|
"""Test creating multiple Rolle objects"""
|
|
rollen = [
|
|
"Datenschutzbeauftragter",
|
|
"IT-Sicherheitsbeauftragter",
|
|
"Risikomanager",
|
|
"Compliance-Officer"
|
|
]
|
|
for rolle_name in rollen:
|
|
Rolle.objects.create(name=rolle_name)
|
|
|
|
self.assertEqual(Rolle.objects.count(), 5) # Including setUp rolle
|
|
|
|
def test_rolle_case_sensitivity(self):
|
|
"""Test that role name is case sensitive"""
|
|
rolle_lower = Rolle.objects.create(name="systemadministrator")
|
|
self.assertNotEqual(self.rolle.pk, rolle_lower.pk)
|
|
self.assertEqual(Rolle.objects.count(), 2)
|
|
|
|
def test_rolle_with_special_characters(self):
|
|
"""Test creating roles with special characters"""
|
|
special_roles = [
|
|
"IT-Administrator",
|
|
"CISO (Chief Information Security Officer)",
|
|
"Datenschutz-Beauftragter/-in",
|
|
"Sicherheitsbeauftragter"
|
|
]
|
|
|
|
for role_name in special_roles:
|
|
rolle = Rolle.objects.create(name=role_name)
|
|
self.assertEqual(rolle.name, role_name)
|
|
|
|
self.assertEqual(Rolle.objects.count(), 5) # Including setUp rolle
|
|
|
|
|
|
class RollenBeschreibungModelTest(TestCase):
|
|
"""Test cases for RollenBeschreibung model"""
|
|
|
|
def setUp(self):
|
|
"""Set up test data"""
|
|
self.rolle = Rolle.objects.create(
|
|
name="Systemadministrator"
|
|
)
|
|
self.abschnitttyp = AbschnittTyp.objects.create(
|
|
abschnitttyp="text"
|
|
)
|
|
self.beschreibung = RollenBeschreibung.objects.create(
|
|
abschnitt=self.rolle,
|
|
abschnitttyp=self.abschnitttyp,
|
|
inhalt="Der Systemadministrator ist für die Verwaltung und Wartung der IT-Systeme verantwortlich.",
|
|
order=1
|
|
)
|
|
|
|
def test_rollenbeschreibung_creation(self):
|
|
"""Test that RollenBeschreibung is created correctly"""
|
|
self.assertEqual(self.beschreibung.abschnitt, self.rolle)
|
|
self.assertEqual(self.beschreibung.abschnitttyp, self.abschnitttyp)
|
|
self.assertEqual(self.beschreibung.inhalt, "Der Systemadministrator ist für die Verwaltung und Wartung der IT-Systeme verantwortlich.")
|
|
self.assertEqual(self.beschreibung.order, 1)
|
|
|
|
def test_rollenbeschreibung_foreign_key_relationship(self):
|
|
"""Test foreign key relationship to Rolle"""
|
|
self.assertEqual(self.beschreibung.abschnitt.name, "Systemadministrator")
|
|
|
|
def test_rollenbeschreibung_cascade_delete(self):
|
|
"""Test that deleting Rolle cascades to RollenBeschreibung"""
|
|
rolle_count = Rolle.objects.count()
|
|
beschreibung_count = RollenBeschreibung.objects.count()
|
|
|
|
self.rolle.delete()
|
|
|
|
self.assertEqual(Rolle.objects.count(), rolle_count - 1)
|
|
self.assertEqual(RollenBeschreibung.objects.count(), beschreibung_count - 1)
|
|
|
|
def test_rollenbeschreibung_verbose_names(self):
|
|
"""Test verbose names"""
|
|
self.assertEqual(
|
|
RollenBeschreibung._meta.verbose_name,
|
|
"Rollenbeschreibungs-Abschnitt"
|
|
)
|
|
self.assertEqual(
|
|
RollenBeschreibung._meta.verbose_name_plural,
|
|
"Rollenbeschreibung"
|
|
)
|
|
|
|
def test_rollenbeschreibung_multiple_descriptions(self):
|
|
"""Test creating multiple descriptions for one Rolle"""
|
|
abschnitttyp2 = AbschnittTyp.objects.create(abschnitttyp="liste ungeordnet")
|
|
beschreibung2 = RollenBeschreibung.objects.create(
|
|
abschnitt=self.rolle,
|
|
abschnitttyp=abschnitttyp2,
|
|
inhalt="Aufgaben:\n- Systemüberwachung\n- Backup-Management\n- Benutzeradministration",
|
|
order=2
|
|
)
|
|
|
|
descriptions = RollenBeschreibung.objects.filter(abschnitt=self.rolle)
|
|
self.assertEqual(descriptions.count(), 2)
|
|
self.assertIn(self.beschreibung, descriptions)
|
|
self.assertIn(beschreibung2, descriptions)
|
|
|
|
def test_rollenbeschreibung_ordering(self):
|
|
"""Test that descriptions can be ordered"""
|
|
beschreibung2 = RollenBeschreibung.objects.create(
|
|
abschnitt=self.rolle,
|
|
abschnitttyp=self.abschnitttyp,
|
|
inhalt="Zweite Beschreibung",
|
|
order=3
|
|
)
|
|
beschreibung3 = RollenBeschreibung.objects.create(
|
|
abschnitt=self.rolle,
|
|
abschnitttyp=self.abschnitttyp,
|
|
inhalt="Erste Beschreibung",
|
|
order=2
|
|
)
|
|
|
|
ordered = RollenBeschreibung.objects.filter(abschnitt=self.rolle).order_by('order')
|
|
expected_order = [self.beschreibung, beschreibung3, beschreibung2]
|
|
self.assertEqual(list(ordered), expected_order)
|
|
|
|
def test_rollenbeschreibung_blank_fields(self):
|
|
"""Test that optional fields can be blank/null"""
|
|
rolle2 = Rolle.objects.create(name="Testrolle")
|
|
beschreibung_blank = RollenBeschreibung.objects.create(
|
|
abschnitt=rolle2
|
|
)
|
|
|
|
self.assertIsNone(beschreibung_blank.abschnitttyp)
|
|
self.assertIsNone(beschreibung_blank.inhalt)
|
|
self.assertEqual(beschreibung_blank.order, 0)
|
|
|
|
def test_rollenbeschreibung_inheritance(self):
|
|
"""Test that RollenBeschreibung inherits from Textabschnitt"""
|
|
# Check that it has the expected fields from Textabschnitt
|
|
self.assertTrue(hasattr(self.beschreibung, 'abschnitttyp'))
|
|
self.assertTrue(hasattr(self.beschreibung, 'inhalt'))
|
|
self.assertTrue(hasattr(self.beschreibung, 'order'))
|
|
|
|
# Check that the fields work as expected
|
|
self.assertIsInstance(self.beschreibung.abschnitttyp, AbschnittTyp)
|
|
self.assertIsInstance(self.beschreibung.inhalt, str)
|
|
self.assertIsInstance(self.beschreibung.order, int)
|
|
|
|
def test_rollenbeschreibung_different_types(self):
|
|
"""Test creating descriptions with different section types"""
|
|
# Create different section types
|
|
typ_list = AbschnittTyp.objects.create(abschnitttyp="liste ungeordnet")
|
|
typ_table = AbschnittTyp.objects.create(abschnitttyp="tabelle")
|
|
|
|
# Create descriptions with different types
|
|
beschreibung_text = RollenBeschreibung.objects.create(
|
|
abschnitt=self.rolle,
|
|
abschnitttyp=self.abschnitttyp,
|
|
inhalt="Textbeschreibung der Rolle",
|
|
order=1
|
|
)
|
|
|
|
beschreibung_list = RollenBeschreibung.objects.create(
|
|
abschnitt=self.rolle,
|
|
abschnitttyp=typ_list,
|
|
inhalt="Aufgabe 1\nAufgabe 2\nAufgabe 3",
|
|
order=2
|
|
)
|
|
|
|
beschreibung_table = RollenBeschreibung.objects.create(
|
|
abschnitt=self.rolle,
|
|
abschnitttyp=typ_table,
|
|
inhalt="| Verantwortung | Priorität |\n|--------------|------------|\n| Systemwartung | Hoch |",
|
|
order=3
|
|
)
|
|
|
|
# Verify all descriptions are created
|
|
descriptions = RollenBeschreibung.objects.filter(abschnitt=self.rolle)
|
|
self.assertEqual(descriptions.count(), 4) # Including setUp beschreibung
|
|
|
|
# Verify types are correct
|
|
self.assertEqual(beschreibung_text.abschnitttyp, self.abschnitttyp)
|
|
self.assertEqual(beschreibung_list.abschnitttyp, typ_list)
|
|
self.assertEqual(beschreibung_table.abschnitttyp, typ_table)
|
|
|
|
|
|
class RolleIntegrationTest(TestCase):
|
|
"""Integration tests for Rolle app"""
|
|
|
|
def setUp(self):
|
|
"""Set up test data"""
|
|
self.rolle1 = Rolle.objects.create(name="IT-Sicherheitsbeauftragter")
|
|
self.rolle2 = Rolle.objects.create(name="Datenschutzbeauftragter")
|
|
|
|
self.abschnitttyp = AbschnittTyp.objects.create(abschnitttyp="text")
|
|
|
|
self.beschreibung1 = RollenBeschreibung.objects.create(
|
|
abschnitt=self.rolle1,
|
|
abschnitttyp=self.abschnitttyp,
|
|
inhalt="Beschreibung für IT-Sicherheitsbeauftragten",
|
|
order=1
|
|
)
|
|
|
|
self.beschreibung2 = RollenBeschreibung.objects.create(
|
|
abschnitt=self.rolle2,
|
|
abschnitttyp=self.abschnitttyp,
|
|
inhalt="Beschreibung für Datenschutzbeauftragten",
|
|
order=1
|
|
)
|
|
|
|
def test_rolle_with_descriptions_query(self):
|
|
"""Test querying Rollen with their descriptions"""
|
|
rollen_with_descriptions = Rolle.objects.filter(
|
|
rollenbeschreibung__isnull=False
|
|
).distinct()
|
|
|
|
self.assertEqual(rollen_with_descriptions.count(), 2)
|
|
self.assertIn(self.rolle1, rollen_with_descriptions)
|
|
self.assertIn(self.rolle2, rollen_with_descriptions)
|
|
|
|
def test_rolle_without_descriptions(self):
|
|
"""Test finding Rollen without descriptions"""
|
|
rolle3 = Rolle.objects.create(name="Compliance-Officer")
|
|
|
|
rollen_without_descriptions = Rolle.objects.filter(
|
|
rollenbeschreibung__isnull=True
|
|
)
|
|
|
|
self.assertEqual(rollen_without_descriptions.count(), 1)
|
|
self.assertEqual(rollen_without_descriptions.first(), rolle3)
|
|
|
|
def test_description_count_annotation(self):
|
|
"""Test annotating Rollen with description count"""
|
|
from django.db.models import Count
|
|
|
|
rollen_with_count = Rolle.objects.annotate(
|
|
description_count=Count('rollenbeschreibung')
|
|
)
|
|
|
|
for rolle in rollen_with_count:
|
|
if rolle.name in ["IT-Sicherheitsbeauftragter", "Datenschutzbeauftragter"]:
|
|
self.assertEqual(rolle.description_count, 1)
|
|
else:
|
|
self.assertEqual(rolle.description_count, 0)
|
|
|
|
def test_multiple_descriptions_per_rolle(self):
|
|
"""Test multiple descriptions for a single role"""
|
|
# Add more descriptions to rolle1
|
|
abschnitttyp2 = AbschnittTyp.objects.create(abschnitttyp="liste ungeordnet")
|
|
|
|
beschreibung2 = RollenBeschreibung.objects.create(
|
|
abschnitt=self.rolle1,
|
|
abschnitttyp=abschnitttyp2,
|
|
inhalt="Zusätzliche Aufgaben:\n- Überwachung\n- Berichterstattung",
|
|
order=2
|
|
)
|
|
|
|
# Check that rolle1 now has 2 descriptions
|
|
descriptions = RollenBeschreibung.objects.filter(abschnitt=self.rolle1)
|
|
self.assertEqual(descriptions.count(), 2)
|
|
|
|
# Check annotation
|
|
rolle_with_count = Rolle.objects.annotate(
|
|
description_count=Count('rollenbeschreibung')
|
|
).get(pk=self.rolle1.pk)
|
|
self.assertEqual(rolle_with_count.description_count, 2)
|
|
|
|
def test_role_descriptions_ordered(self):
|
|
"""Test that role descriptions are returned in correct order"""
|
|
# Add more descriptions in random order
|
|
beschreibung2 = RollenBeschreibung.objects.create(
|
|
abschnitt=self.rolle1,
|
|
abschnitttyp=self.abschnitttyp,
|
|
inhalt="Dritte Beschreibung",
|
|
order=3
|
|
)
|
|
|
|
beschreibung3 = RollenBeschreibung.objects.create(
|
|
abschnitt=self.rolle1,
|
|
abschnitttyp=self.abschnitttyp,
|
|
inhalt="Zweite Beschreibung",
|
|
order=2
|
|
)
|
|
|
|
# Get descriptions in order
|
|
ordered_descriptions = RollenBeschreibung.objects.filter(
|
|
abschnitt=self.rolle1
|
|
).order_by('order')
|
|
|
|
expected_order = [self.beschreibung1, beschreibung3, beschreibung2]
|
|
self.assertEqual(list(ordered_descriptions), expected_order)
|
|
|
|
def test_role_search_by_name(self):
|
|
"""Test searching roles by name"""
|
|
# Test exact match
|
|
exact_match = Rolle.objects.filter(name="IT-Sicherheitsbeauftragter")
|
|
self.assertEqual(exact_match.count(), 1)
|
|
self.assertEqual(exact_match.first(), self.rolle1)
|
|
|
|
# Test case-sensitive contains
|
|
contains_match = Rolle.objects.filter(name__contains="Sicherheits")
|
|
self.assertEqual(contains_match.count(), 1)
|
|
self.assertEqual(contains_match.first(), self.rolle1)
|
|
|
|
# Test case-insensitive contains
|
|
icontains_match = Rolle.objects.filter(name__icontains="sicherheits")
|
|
self.assertEqual(icontains_match.count(), 1)
|
|
self.assertEqual(icontains_match.first(), self.rolle1)
|
|
|
|
def test_role_with_long_descriptions(self):
|
|
"""Test roles with long description content"""
|
|
long_content = "Dies ist eine sehr lange Beschreibung " * 50 # Repeat to make it long
|
|
|
|
rolle_long = Rolle.objects.create(name="Rolle mit langer Beschreibung")
|
|
beschreibung_long = RollenBeschreibung.objects.create(
|
|
abschnitt=rolle_long,
|
|
abschnitttyp=self.abschnitttyp,
|
|
inhalt=long_content,
|
|
order=1
|
|
)
|
|
|
|
# Verify the long content is stored correctly
|
|
retrieved = RollenBeschreibung.objects.get(pk=beschreibung_long.pk)
|
|
self.assertEqual(retrieved.inhalt, long_content)
|
|
self.assertGreater(len(retrieved.inhalt), 1000) # Should be quite long
|