48 lines
2 KiB
Python
48 lines
2 KiB
Python
# Copyright (c) 2026 Patrick Motsch
|
|
# All rights reserved.
|
|
"""Pure-Python unit tests for the orphan detection in
|
|
``serviceRedmineStats._countOrphans``.
|
|
|
|
Snapshot in ``tests/fixtures/redmineSnapshot.json`` contains:
|
|
- 1x Userstory (1001) -- root
|
|
- 1x Feature (2001) related to 1001 -> reachable
|
|
- 1x Acc.Crit (3001) parent=2001 -> reachable
|
|
- 1x Bug (4001) blocks 2001 -> reachable via relation
|
|
- 2x Task (5001, 5002) -> orphan (no link to any User Story)
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from modules.features.redmine.serviceRedmineStats import _countOrphans
|
|
from tests.fixtures.loadRedmineSnapshot import loadSnapshot
|
|
|
|
|
|
class TestCountOrphans:
|
|
def test_orphansFromSnapshot(self) -> None:
|
|
schema, tickets = loadSnapshot()
|
|
orphans = _countOrphans(tickets, schema.rootTrackerId)
|
|
assert orphans == 2, "Two unrelated Tasks should be orphans"
|
|
|
|
def test_emptyListReturnsZero(self) -> None:
|
|
assert _countOrphans([], 1) == 0
|
|
|
|
def test_noRootTrackerCountsAllAsOrphan(self) -> None:
|
|
schema, tickets = loadSnapshot()
|
|
# Pretend there is no User Story tracker at all -- every ticket is orphan.
|
|
assert _countOrphans(tickets, None) == len(tickets)
|
|
|
|
def test_relationDirectionAgnostic(self) -> None:
|
|
"""A ticket reachable via the *target* side of a relation must not
|
|
be counted as orphan -- _countOrphans walks both directions."""
|
|
_, tickets = loadSnapshot()
|
|
bug = next(t for t in tickets if t.id == 4001)
|
|
# Bug 4001 -[blocks]-> 2001; it is the source. Reverse it: 2001 -[blocks]-> 4001
|
|
bug.relations = []
|
|
# Attach the relation on 2001 instead.
|
|
feature = next(t for t in tickets if t.id == 2001)
|
|
from modules.features.redmine.datamodelRedmine import RedmineRelationDto
|
|
feature.relations.append(
|
|
RedmineRelationDto(id=999, issueId=2001, issueToId=4001, relationType="blocks", delay=None)
|
|
)
|
|
orphans = _countOrphans(tickets, 1)
|
|
assert orphans == 2 # Tasks remain orphans, Bug is still reachable
|