Jul 10 - Add test suite
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
"""
|
||||
Tests for the SLA engine (app/utils/sla.py).
|
||||
|
||||
sla_status/deadline/hours_remaining read only .status, .severity, .reported_at,
|
||||
so a lightweight stand-in object is enough — no DB or app context needed. Time
|
||||
is controlled by positioning reported_at relative to now_eastern().
|
||||
"""
|
||||
from datetime import timedelta
|
||||
from types import SimpleNamespace
|
||||
|
||||
import pytest
|
||||
|
||||
from app.utils.sla import (
|
||||
sla_status, sla_deadline, sla_hours_remaining, SLA_HOURS, AT_RISK_THRESHOLD,
|
||||
)
|
||||
from app.utils.time_utils import now_eastern
|
||||
|
||||
|
||||
def issue(severity='high', status='open', hours_ago=0):
|
||||
return SimpleNamespace(
|
||||
severity=severity,
|
||||
status=status,
|
||||
reported_at=now_eastern() - timedelta(hours=hours_ago),
|
||||
)
|
||||
|
||||
|
||||
def test_resolved_issue_has_no_sla():
|
||||
assert sla_status(issue(status='resolved', hours_ago=999)) is None
|
||||
|
||||
|
||||
def test_unknown_severity_returns_none():
|
||||
assert sla_status(issue(severity='nonsense', hours_ago=1)) is None
|
||||
|
||||
|
||||
def test_fresh_issue_is_ok():
|
||||
# high = 24h window, at-risk at 18h; 1h in is comfortably OK
|
||||
assert sla_status(issue(severity='high', hours_ago=1)) == 'ok'
|
||||
|
||||
|
||||
def test_issue_past_at_risk_threshold():
|
||||
# high at-risk at 18h; 20h in is at_risk but not yet breached (24h)
|
||||
assert sla_status(issue(severity='high', hours_ago=20)) == 'at_risk'
|
||||
|
||||
|
||||
def test_issue_past_deadline_is_breached():
|
||||
assert sla_status(issue(severity='high', hours_ago=25)) == 'breached'
|
||||
|
||||
|
||||
@pytest.mark.parametrize('severity', list(SLA_HOURS.keys()))
|
||||
def test_at_risk_boundary_for_each_severity(severity):
|
||||
window = SLA_HOURS[severity]
|
||||
# Just past the at-risk fraction, still before the deadline.
|
||||
at_risk_hours = window * AT_RISK_THRESHOLD
|
||||
assert sla_status(issue(severity=severity, hours_ago=at_risk_hours + 0.1)) == 'at_risk'
|
||||
# Just before the at-risk fraction is still OK.
|
||||
assert sla_status(issue(severity=severity, hours_ago=at_risk_hours - 0.5)) == 'ok'
|
||||
|
||||
|
||||
def test_deadline_is_reported_at_plus_window():
|
||||
iss = issue(severity='medium', hours_ago=0)
|
||||
expected = iss.reported_at + timedelta(hours=SLA_HOURS['medium'])
|
||||
assert sla_deadline(iss) == expected
|
||||
|
||||
|
||||
def test_hours_remaining_positive_when_within_window():
|
||||
remaining = sla_hours_remaining(issue(severity='critical', hours_ago=1))
|
||||
# critical window is 4h; ~3h should remain
|
||||
assert 2.5 < remaining < 3.5
|
||||
|
||||
|
||||
def test_hours_remaining_negative_when_overdue():
|
||||
remaining = sla_hours_remaining(issue(severity='critical', hours_ago=6))
|
||||
assert remaining < 0
|
||||
|
||||
|
||||
def test_hours_remaining_none_for_resolved():
|
||||
assert sla_hours_remaining(issue(status='resolved', hours_ago=1)) is None
|
||||
Reference in New Issue
Block a user