Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion pyrit/analytics/scenario_statistics.py
Original file line number Diff line number Diff line change
Expand Up @@ -523,7 +523,13 @@ def combine_execution_counts(counts: Iterable[ScenarioProgressCounts]) -> Scenar

return ScenarioProgressCounts(
completed=completed,
planned=sum(value for value in planned if value is not None) if all(v is not None for v in planned) else None,
planned=(
# The empty group carries no plan at all, so it reports None rather
# than a vacuous sum() of 0.
sum(value for value in planned if value is not None)
if planned and all(v is not None for v in planned)
else None
),
succeeded=succeeded,
success_percentage=success_percentage(succeeded=succeeded, completed=completed),
errors=sum(item.errors for item in counts),
Expand Down
7 changes: 7 additions & 0 deletions tests/unit/analytics/test_scenario_statistics.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,13 @@ def test_combining_count_only_legacy_payloads_does_not_infer_failures_from_histo
assert "without an outcome breakdown" in caplog.text


def test_combining_an_empty_group_reports_no_planned_count() -> None:
"""An empty display group never learned a plan, so planned is unknown, not 0."""
combined = combine_execution_counts([])
assert combined.planned is None
assert combined.completed == 0


def test_combining_unequal_scenario_groups_recomputes_both_denominators() -> None:
result = make_scenario_result(
attack_results={
Expand Down