Skip to content

checks: make suite failure reporting configurable#2418

Open
harsh21234i wants to merge 3 commits into
Giskard-AI:mainfrom
harsh21234i:fix/suite-result-log-limit
Open

checks: make suite failure reporting configurable#2418
harsh21234i wants to merge 3 commits into
Giskard-AI:mainfrom
harsh21234i:fix/suite-result-log-limit

Conversation

@harsh21234i
Copy link
Copy Markdown
Contributor

@harsh21234i harsh21234i commented Apr 20, 2026

#2417

Summary

This PR makes SuiteResult failure reporting configurable instead of hard-coding the rich-report output to 20 failed/errored
scenarios.

Changes

  • Added max_reported_failures to Suite with a default of 20
  • Added max_reported_failures to SuiteResult with support for None to show all failures
  • Updated Suite.run() to propagate the configured value into the returned SuiteResult
  • Updated SuiteResult.__rich_console__ to honor the configured limit in both the detailed and summary sections
  • Added tests for:
    • propagation from Suite.run()
    • bounded rich rendering
    • unbounded rich rendering when set to None

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a configurable max_reported_failures parameter to the Suite and SuiteResult classes, allowing users to control the number of failed scenarios displayed in reports. The default is set to 20, and the logic in rich_console has been updated to respect this setting. Feedback includes suggestions to allow a minimum value of 0 for complete suppression of failure details, refactoring duplicated logic in the reporting output, and merging redundant imports in the test suite.

"Maximum number of failed or errored scenarios to show in the rich "
"report. Use None to show all."
),
ge=1,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Consider changing the minimum value to 0. Setting max_reported_failures=0 is a valid way to suppress detailed failure logs while still showing the summary count (e.g., '... and 20 more').

Suggested change
ge=1,
ge=0,

Comment on lines +578 to +608
if failures_and_errors:
n_loggable_failures = 20 # TODO: make this configurable
max_reported_failures = self.max_reported_failures
reported_failures = (
failures_and_errors
if max_reported_failures is None
else failures_and_errors[:max_reported_failures]
)

# Details
yield Rule("FAILURES", characters="=", style="grey")
for f in failures_and_errors[:n_loggable_failures]:
for f in reported_failures:
yield Panel(
f,
title=f.scenario_name,
border_style=f"{STATUS_MAPPING[f.status]['color']} bold",
)
if len(failures_and_errors) > n_loggable_failures:
yield f" ... and {len(failures_and_errors) - n_loggable_failures} more"
if len(failures_and_errors) > len(reported_failures):
yield f" ... and {len(failures_and_errors) - len(reported_failures)} more"

# Summary
yield Rule("SUMMARY", characters="=", style="grey")
for f in failures_and_errors[:n_loggable_failures]:
for f in reported_failures:
status = STATUS_MAPPING[f.status]
yield f"[{status['color']} bold]{f.scenario_name}[/{status['color']} bold]\t[{status['color']}]{f.status.value.upper()}[/{status['color']}]"
for tc in f.failures_and_errors:
for c in tc.failures_and_errors:
yield from (
f"\t{line}" for line in c.__rich_console__(console, options)
)
if len(failures_and_errors) > n_loggable_failures:
yield f" ... and {len(failures_and_errors) - n_loggable_failures} more"
if len(failures_and_errors) > len(reported_failures):
yield f" ... and {len(failures_and_errors) - len(reported_failures)} more"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The logic for calculating the number of hidden failures and yielding the 'more' message is duplicated. Extracting this into a variable improves maintainability and readability.

        if failures_and_errors:
            max_reported_failures = self.max_reported_failures
            reported_failures = (
                failures_and_errors
                if max_reported_failures is None
                else failures_and_errors[:max_reported_failures]
            )
            n_hidden = len(failures_and_errors) - len(reported_failures)

            # Details
            yield Rule("FAILURES", characters="=", style="grey")
            for f in reported_failures:
                yield Panel(
                    f,
                    title=f.scenario_name,
                    border_style=f"{STATUS_MAPPING[f.status]['color']} bold",
                )
            if n_hidden > 0:
                yield f"  ... and {n_hidden} more"

            # Summary
            yield Rule("SUMMARY", characters="=", style="grey")
            for f in reported_failures:
                status = STATUS_MAPPING[f.status]
                yield f"[{status['color']} bold]{f.scenario_name}[/{status['color']} bold]\t[{status['color']}]{f.status.value.upper()}[/{status['color']}]"
                for tc in f.failures_and_errors:
                    for c in tc.failures_and_errors:
                        yield from (
                            f"\t{line}" for line in c.__rich_console__(console, options)
                        )
            if n_hidden > 0:
                yield f"  ... and {n_hidden} more"

"Maximum number of failed or errored scenarios to show in suite "
"reports. Use None to show all."
),
ge=1,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Consider changing the minimum value to 0 to allow users to suppress failure details entirely if desired, consistent with the suggested change in SuiteResult.

Suggested change
ge=1,
ge=0,

Comment on lines +3 to +11
from giskard.checks.core.interaction import Trace
from giskard.checks.core.result import (
CheckResult,
ScenarioResult,
SuiteResult,
)
from giskard.checks.core.result import (
TestCaseResult as CheckTestCaseResult,
)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

These imports from the same module can be merged for better readability.

from giskard.checks.core.interaction import Trace
from giskard.checks.core.result import (
    CheckResult,
    ScenarioResult,
    SuiteResult,
    TestCaseResult as CheckTestCaseResult,
)

Copy link
Copy Markdown
Member

@davidberenstein1957 davidberenstein1957 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instead of this argument, could you define this as an overridable environment variable and simplify the code implementation and tests?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Development

Successfully merging this pull request may close these issues.

2 participants