diff --git a/SAS/TMSS/backend/test/t_reports.py b/SAS/TMSS/backend/test/t_reports.py
index bedd0bedca50a69570ceaf7f381c187c19c54e35..2c2c591907444221d88b5889e23c0b3d7e138132 100755
--- a/SAS/TMSS/backend/test/t_reports.py
+++ b/SAS/TMSS/backend/test/t_reports.py
@@ -1,5 +1,5 @@
 #!/usr/bin/env python3
-
+import datetime
 # Copyright (C) 2018    ASTRON (Netherlands Institute for Radio Astronomy)
 # P.O. Box 2, 7990 AA Dwingeloo, The Netherlands
 #
@@ -21,6 +21,7 @@ import os
 import time
 import unittest
 import requests
+from datetime import datetime
 
 import logging
 logger = logging.getLogger('lofar.'+__name__)
@@ -57,6 +58,9 @@ from lofar.common.json_utils import get_default_json_object_for_schema
 from dateutil.relativedelta import relativedelta
 from lofar.sas.tmss.test.test_utils import set_subtask_state_following_allowed_transitions
 
+from django.contrib.auth import get_user_model
+User = get_user_model()
+
 
 class ReportTest(unittest.TestCase):
     @classmethod
@@ -183,7 +187,7 @@ class ReportTest(unittest.TestCase):
         set_subtask_state_following_allowed_transitions(subtask, status)
 
     @classmethod
-    def _create_simple_finished_observation_SUB_for_project(cls, project:models.Project, duration=600, start_time=None, accepted=None) -> None:
+    def _create_simple_finished_observation_SUB_for_project(cls, project:models.Project, duration=600, start_time=None, accepted=None) -> models.SchedulingUnitBlueprint:
         """
         Help method to create a SUB with an observation with a default duration of 600s set to finished.
         """
@@ -226,6 +230,7 @@ class ReportTest(unittest.TestCase):
                                                                                       dataformat=models.Dataformat.objects.get(value="Beamformed"),
                                                                                       datatype=models.Datatype.objects.get(value="time series")))
         cls._set_dataproducts_size_and_set_subtask_status(obs_subtask)
+        return su_blueprint
 
     @classmethod
     def setup_project_report(cls, project:models.Project) -> None:
@@ -571,6 +576,100 @@ class ReportTest(unittest.TestCase):
         # Assert contains_overlapping_observations is False
         self.assertEqual(result['contains_overlapping_observations'], False)
 
+class FailureReportTest(unittest.TestCase):
+
+    def test_create_failure_report(self):
+        # setup, create project with three SUs, each containing single observation
+        project = models.Project.objects.create(**Project_test_data(name='failure_report_project'))
+        su_1 = ReportTest._create_simple_finished_observation_SUB_for_project(project=project,
+                                                                              duration=6666,
+                                                                              start_time=datetime(2023, 1, 31, 23, 59))
+        su_2 = ReportTest._create_simple_finished_observation_SUB_for_project(project=project,
+                                                                              duration=3333,
+                                                                              start_time=datetime(2023, 3, 31, 23, 59))
+        su_3 = ReportTest._create_simple_finished_observation_SUB_for_project(project=project,
+                                                                              duration=4444,
+                                                                              start_time=datetime(2023, 5, 31, 23, 59))
+
+        # setup, add system events, each affecting one of the SUs
+        template = models.SystemEventTemplate.get_latest(name="affectedhardware")
+        event_1 = models.SystemEvent.objects.create(name='event 1',
+                                                    issue_type=models.SystemEventType.objects.get(value=models.SystemEventType.Choices.CEP.value),
+                                                    issue_subtype=models.SystemEventSubtype.objects.get(value=models.SystemEventSubtype.Choices.CRASH.value),
+                                                    severity=models.SystemEventSeverity.objects.get(value=models.SystemEventSeverity.Choices.FAILURE.value),
+                                                    start=datetime(year=2023, month=1, day=31, hour=23),
+                                                    stop=datetime(year=2023, month=2, day=1, hour=2),
+                                                    affected_hardware_doc={},
+                                                    affected_hardware_template=template,
+                                                    created_by=User.objects.first(),
+                                                    status=models.SystemEventStatus.objects.get(value=models.SystemEventStatus.Choices.OPEN.value),
+                                                    )
+        event_1.affected_tasks.set(su_1.task_blueprints.all())
+        event_1.save()
+
+        event_2 = models.SystemEvent.objects.create(name='event 2',
+                                                    issue_type=models.SystemEventType.objects.get(value=models.SystemEventType.Choices.HUMAN.value),
+                                                    issue_subtype=models.SystemEventSubtype.objects.get(value=models.SystemEventSubtype.Choices.DATALOSS.value),
+                                                    severity=models.SystemEventSeverity.objects.get(value=models.SystemEventSeverity.Choices.FAILURE.value),
+                                                    start=datetime(year=2023, month=3, day=31, hour=23),
+                                                    stop=datetime(year=2023, month=4, day=1, hour=2),
+                                                    affected_hardware_doc={},
+                                                    affected_hardware_template=template,
+                                                    created_by=User.objects.first(),
+                                                    status=models.SystemEventStatus.objects.get(value=models.SystemEventStatus.Choices.ANALYSED.value),
+                                                    )
+        event_2.affected_tasks.set(su_2.task_blueprints.all())
+        event_2.save()
+        
+        
+        event_3 = models.SystemEvent.objects.create(name='event 3',
+                                                    issue_type=models.SystemEventType.objects.get(value=models.SystemEventType.Choices.HUMAN.value),
+                                                    issue_subtype=models.SystemEventSubtype.objects.get(value=models.SystemEventSubtype.Choices.NOISY.value),
+                                                    severity=models.SystemEventSeverity.objects.get(value=models.SystemEventSeverity.Choices.MAJOR.value),
+                                                    start=datetime(year=2023, month=5, day=31, hour=23),
+                                                    stop=datetime(year=2023, month=6, day=1, hour=2),
+                                                    affected_hardware_doc={},
+                                                    affected_hardware_template=template,
+                                                    created_by=User.objects.first(),
+                                                    status=models.SystemEventStatus.objects.get(value=models.SystemEventStatus.Choices.CLOSED.value),
+                                                    )
+        event_3.affected_tasks.set(su_3.task_blueprints.all())
+        event_3.save()
+
+
+        # generate the report
+        with tmss_test_env.create_tmss_client() as client:
+            start = datetime(year=2023, month=1, day=1)
+            stop = datetime(year=2024, month=1, day=1)
+            report = client.get_path_as_json_object('/failure_report/?start=%s&stop=%s' % (start.isoformat(), stop.isoformat()))
+
+        # assertions, SUs 1 and 2 should be in here, SU 3 should be ignored due to lack of severity
+        # check grand total
+        self.assertIn('total_duration_lost', report)
+        self.assertEqual(report['total_duration_lost'], 21600)  # 2 failure events of 3 hours each
+        self.assertAlmostEqual(report['total_percent_of_wall_time_lost'], 0.0684931506849315)
+
+        # check aggregates
+        self.assertIn('human', str(report['system_event_summary']['by_issue_type']))   # event 1
+        for d in report['system_event_summary']['by_issue_type']:
+            self.assertEqual(d['count'], 1)   # only event 1 (but not 3) is accounted for
+        self.assertNotIn('noisy', str(report['system_event_summary']['by_issue_subtype']))  # event 3 missing
+
+        # check histogram (events get binned correctly?)
+        self.assertEqual(report['lost_observing_time_histogram']['2023-01-01'], 3600)  # event 1
+        self.assertEqual(report['lost_observing_time_histogram']['2023-02-01'], 7200)  # event 1
+        self.assertEqual(report['lost_observing_time_histogram']['2023-03-01'], 3600)  # event 2
+        self.assertEqual(report['lost_observing_time_histogram']['2023-04-01'], 7200)  # event 2
+        self.assertNotIn('2023-05-01', report['lost_observing_time_histogram'])   # event 3 missing
+        self.assertNotIn('2023-06-01', report['lost_observing_time_histogram'])   # event 3 missing
+
+        # check SUs
+        self.assertEqual(len(report['failed_scheduling_units']), 2)
+        for unit in report['failed_scheduling_units']:
+            self.assertIn(unit['on_sky_duration'], [6666, 3333])
+            self.assertEqual(unit['project'], 'failure_report_project')
+            self.assertEqual(len(unit['subtasks']), 1)
+
 
 if __name__ == "__main__":
     os.environ['TZ'] = 'UTC'