diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 6a044637f34bbf992b4f89946599c92e96946182..955750958d170e723e9714295750d0e1204e878f 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,6 +1,8 @@
 include:
     - project: "AlekSIS/official/AlekSIS"
       file: /ci/general.yml
+    - project: "AlekSIS/official/AlekSIS"
+      file: /ci/test.yml
     - project: "AlekSIS/official/AlekSIS"
       file: /ci/build_dist.yml
     - project: "AlekSIS/official/AlekSIS"
diff --git a/aleksis/apps/alsijil/forms.py b/aleksis/apps/alsijil/forms.py
index 6024b8581642073064c9c20e965f4ae5d9269638..08638432ebd3e7bb64139c0312f6830e40a9c576 100644
--- a/aleksis/apps/alsijil/forms.py
+++ b/aleksis/apps/alsijil/forms.py
@@ -106,7 +106,8 @@ class SelectForm(forms.Form):
 
         # Filter selectable teachers by permissions
         if not check_global_permission(self.request.user, "alsijil.view_week"):
-            # If the user hasn't the global permission, the user is only allowed to see his own person
+            # If the user hasn't the global permission,
+            # the user is only allowed to see his own person
             teacher_qs = teacher_qs.filter(pk=person.pk)
 
         self.fields["teacher"].queryset = teacher_qs
diff --git a/aleksis/apps/alsijil/model_extensions.py b/aleksis/apps/alsijil/model_extensions.py
index 0828272f1986f519f5d6b7d748a465b275ed6846..452de0fcbe5d2c99265219d70c4202e896e767ba 100644
--- a/aleksis/apps/alsijil/model_extensions.py
+++ b/aleksis/apps/alsijil/model_extensions.py
@@ -357,7 +357,7 @@ def generate_person_list_with_class_register_statistics(
                     "personal_notes",
                     filter=Q(
                         personal_notes__extra_marks=extra_mark,
-                        personal_notes__lesson_period__lesson__validity__school_term=self.school_term,
+                        personal_notes__lesson_period__lesson__validity__school_term=self.school_term,  # noqa
                     )
                     & (
                         Q(personal_notes__lesson_period__lesson__groups=self)
@@ -377,7 +377,7 @@ def generate_person_list_with_class_register_statistics(
                     filter=Q(
                         personal_notes__absent=True,
                         personal_notes__excuse_type=excuse_type,
-                        personal_notes__lesson_period__lesson__validity__school_term=self.school_term,
+                        personal_notes__lesson_period__lesson__validity__school_term=self.school_term,  # noqa
                     )
                     & (
                         Q(personal_notes__lesson_period__lesson__groups=self)
diff --git a/aleksis/apps/alsijil/models.py b/aleksis/apps/alsijil/models.py
index e2f234a596275f57c4427f916144f534f9092adf..e64bac1afd260f3571c17bfa6b2c639c03d5b915 100644
--- a/aleksis/apps/alsijil/models.py
+++ b/aleksis/apps/alsijil/models.py
@@ -1,9 +1,7 @@
 from django.db import models
 from django.utils.formats import date_format
-from django.utils.functional import classproperty
 from django.utils.translation import gettext_lazy as _
 
-from cache_memoize import cache_memoize
 from calendarweek import CalendarWeek
 
 from aleksis.apps.alsijil.managers import PersonalNoteManager
diff --git a/aleksis/apps/alsijil/preferences.py b/aleksis/apps/alsijil/preferences.py
index d5552c5e03a37d530d1355c99ef56706616e5380..be597c9e5627fcd58d0243077fdaa564cc24a79b 100644
--- a/aleksis/apps/alsijil/preferences.py
+++ b/aleksis/apps/alsijil/preferences.py
@@ -40,7 +40,8 @@ class CarryOverDataToNextPeriods(BooleanPreference):
     name = "carry_over"
     default = True
     verbose_name = _(
-        "Carry over data from first lesson period to the following lesson periods in lessons over multiple periods"
+        "Carry over data from first lesson period to the "
+        "following lesson periods in lessons over multiple periods"
     )
     help_text = _(
         "This will carry over data only if the data in the following periods are empty."
@@ -53,7 +54,8 @@ class AllowOpenPeriodsOnSameDay(BooleanPreference):
     name = "open_periods_same_day"
     default = False
     verbose_name = _(
-        "Allow teachers to open lesson periods on the same day and not just at the beginning of the period"
+        "Allow teachers to open lesson periods on the "
+        "same day and not just at the beginning of the period"
     )
     help_text = _(
         "Lessons in the past are not affected by this setting, you can open them whenever you want."
diff --git a/aleksis/apps/alsijil/rules.py b/aleksis/apps/alsijil/rules.py
index 23c22cbe340d1f27af1be11378623817eb360a8b..126ceea41a4979937843e18d0019a300d05e950c 100644
--- a/aleksis/apps/alsijil/rules.py
+++ b/aleksis/apps/alsijil/rules.py
@@ -9,7 +9,6 @@ from aleksis.core.util.predicates import (
 )
 
 from .util.predicates import (
-    has_any_object_absence,
     has_lesson_group_object_perm,
     has_person_group_object_perm,
     has_personal_note_group_perm,
diff --git a/aleksis/apps/alsijil/util/predicates.py b/aleksis/apps/alsijil/util/predicates.py
index 4bdd2a34ca1bf7ed1e81777e4f99e493d071905c..43889191baecaf3e196c0b776c869cf70bc40d4c 100644
--- a/aleksis/apps/alsijil/util/predicates.py
+++ b/aleksis/apps/alsijil/util/predicates.py
@@ -3,13 +3,11 @@ from typing import Any, Union
 from django.contrib.auth.models import Permission, User
 
 from guardian.models import UserObjectPermission
-from guardian.shortcuts import get_objects_for_user
 from rules import predicate
 
 from aleksis.apps.chronos.models import LessonPeriod
 from aleksis.core.models import Group, Person
-from aleksis.core.util.core_helpers import get_content_type_by_perm, get_site_preferences
-from aleksis.core.util.predicates import check_object_permission
+from aleksis.core.util.core_helpers import get_content_type_by_perm
 
 from ..models import PersonalNote
 
@@ -173,7 +171,7 @@ def has_lesson_group_object_perm(perm: str):
 
 
 def has_personal_note_group_perm(perm: str):
-    """Predicate builder for permissions on personal notes
+    """Predicate builder for permissions on personal notes.
 
     Checks whether a user has a permission on any group of a person of a PersonalNote.
     """
@@ -200,7 +198,7 @@ def has_personal_note_group_perm(perm: str):
 
 @predicate
 def is_own_personal_note(user: User, obj: PersonalNote) -> bool:
-    """Predicate for users referred to in a personal note
+    """Predicate for users referred to in a personal note.
 
     Checks whether the user referred to in a PersonalNote is the active user.
     """
@@ -233,7 +231,7 @@ def is_personal_note_lesson_teacher(user: User, obj: PersonalNote) -> bool:
 @predicate
 def is_personal_note_lesson_parent_group_owner(user: User, obj: PersonalNote) -> bool:
     """
-    Predicate for parent group owners of a lesson referred to in the lesson period of a personal note.
+    Predicate for parent group owners of a lesson referred to in the lesson of a personal note.
 
     Checks whether the person linked to the user is the owner of
     any parent groups of any groups of the given LessonPeriod lesson of the given PersonalNote.
@@ -247,21 +245,6 @@ def is_personal_note_lesson_parent_group_owner(user: User, obj: PersonalNote) ->
     return False
 
 
-@predicate
-def has_any_object_absence(user: User) -> bool:
-    """
-    Predicate which builds a query with all the persons the given users is allowed to register an absence for.
-    """
-    if Person.objects.filter(member_of__owners=user.person).exists():
-        return True
-    if get_objects_for_user(user, "core.register_absence_person", Person).exists():
-        return True
-    if Person.objects.filter(
-        member_of__in=get_objects_for_user(user, "core.register_absence_group", Group)
-    ).exists():
-        return True
-
-
 @predicate
 def is_teacher(user: User, obj: Person) -> bool:
     """Predicate which checks if the provided object is a teacher."""
diff --git a/aleksis/apps/alsijil/views.py b/aleksis/apps/alsijil/views.py
index a659b2e60f39b69598fde0e018727d325cbb50c9..c07c85ed13bbe6604972adf8aee6c5a29ad248fb 100644
--- a/aleksis/apps/alsijil/views.py
+++ b/aleksis/apps/alsijil/views.py
@@ -16,8 +16,7 @@ from reversion.views import RevisionMixin
 from rules.contrib.views import PermissionRequiredMixin, permission_required
 
 from aleksis.apps.chronos.managers import TimetableType
-from aleksis.apps.chronos.models import LessonPeriod, LessonSubstitution, TimePeriod
-from aleksis.apps.chronos.util.chronos_helpers import get_el_by_pk
+from aleksis.apps.chronos.models import LessonPeriod, TimePeriod
 from aleksis.apps.chronos.util.date import get_weeks_for_year, week_weekday_to_date
 from aleksis.core.mixins import AdvancedCreateView, AdvancedDeleteView, AdvancedEditView
 from aleksis.core.models import Group, Person, SchoolTerm
@@ -155,7 +154,8 @@ def lesson(
 
             messages.success(request, _("The personal notes have been saved."))
 
-            # Regenerate form here to ensure that programmatically changed data will be shown correctly
+            # Regenerate form here to ensure that programmatically
+            # changed data will be shown correctly
             personal_note_formset = PersonalNoteFormSet(
                 None, queryset=persons_qs, prefix="personal_notes"
             )
@@ -787,7 +787,7 @@ class ExtraMarkEditView(PermissionRequiredMixin, AdvancedEditView):
 
 
 class ExtraMarkDeleteView(PermissionRequiredMixin, RevisionMixin, AdvancedDeleteView):
-    """Delete view for extra marks"""
+    """Delete view for extra marks."""
 
     model = ExtraMark
     permission_required = "alsijil.delete_extramark"
@@ -828,7 +828,7 @@ class ExcuseTypeEditView(PermissionRequiredMixin, AdvancedEditView):
 
 
 class ExcuseTypeDeleteView(PermissionRequiredMixin, RevisionMixin, AdvancedDeleteView):
-    """Delete view for excuse types"""
+    """Delete view for excuse types."""
 
     model = ExcuseType
     permission_required = "alsijil.delete_excusetype"