Skip to content

Commit

Permalink
Fix per review comments
Browse files Browse the repository at this point in the history
  • Loading branch information
carl-baillargeon committed Aug 19, 2024
1 parent dc23513 commit 8918cd0
Show file tree
Hide file tree
Showing 11 changed files with 52 additions and 232 deletions.
11 changes: 2 additions & 9 deletions anta/cli/nrfu/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,15 +116,8 @@ def tpl_report(ctx: click.Context, template: pathlib.Path, output: pathlib.Path
required=True,
help="Path to save the report as a Markdown file",
)
@click.option(
"--only-failed-tests",
is_flag=True,
default=False,
show_envvar=True,
help="Only include failed tests in the report.",
)
def md_report(ctx: click.Context, md_output: pathlib.Path, *, only_failed_tests: bool = False) -> None:
def md_report(ctx: click.Context, md_output: pathlib.Path) -> None:
"""ANTA command to check network state with Markdown report."""
run_tests(ctx)
save_markdown_report(ctx, md_output=md_output, only_failed_tests=only_failed_tests)
save_markdown_report(ctx, md_output=md_output)
exit_with_code(ctx)
5 changes: 2 additions & 3 deletions anta/cli/nrfu/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,17 +135,16 @@ def save_to_csv(ctx: click.Context, csv_file: pathlib.Path) -> None:
ctx.exit(ExitCode.USAGE_ERROR)


def save_markdown_report(ctx: click.Context, md_output: pathlib.Path, *, only_failed_tests: bool = False) -> None:
def save_markdown_report(ctx: click.Context, md_output: pathlib.Path) -> None:
"""Save the markdown report to a file.
Parameters
----------
ctx: Click context containing the result manager.
md_output: Path to save the markdown report.
only_failed_tests: If True, only failed tests will be included in the report. Default is False.
"""
try:
MDReportGenerator.generate(results=_get_result_manager(ctx), md_filename=md_output, only_failed_tests=only_failed_tests)
MDReportGenerator.generate(results=_get_result_manager(ctx), md_filename=md_output)
console.print(f"Markdown report saved to {md_output} ✅", style="cyan")
except OSError:
console.print(f"Failed to save Markdown report to {md_output} ❌", style="cyan")
Expand Down
2 changes: 1 addition & 1 deletion anta/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,5 @@
- [Summary Totals](#summary-totals)
- [Summary Totals Device Under Test](#summary-totals-device-under-test)
- [Summary Totals Per Category](#summary-totals-per-category)
- [Failed Test Results Summary](#failed-test-results-summary)"""
- [Test Results](#test-results)"""
"""Table of Contents for the Markdown report."""
71 changes: 13 additions & 58 deletions anta/reporter/md_reporter.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,24 +32,17 @@ class MDReportGenerator:
The `generate` class method will loop over all the section subclasses and call their `generate_section` method.
The final report will be generated in the same order as the `sections` list of the method.
The class method also accepts an optional `only_failed_tests` flag to generate a report with only failed tests.
By default, the report will include all test results.
"""

@classmethod
def generate(cls, results: ResultManager, md_filename: Path, *, only_failed_tests: bool = False) -> None:
def generate(cls, results: ResultManager, md_filename: Path) -> None:
"""Generate and write the various sections of the markdown report.
Parameters
----------
results: The ResultsManager instance containing all test results.
md_filename: The path to the markdown file to write the report into.
only_failed_tests: Flag to generate a report with only failed tests. Defaults to False.
"""
MDReportBase.ONLY_FAILED_TESTS = only_failed_tests

try:
with md_filename.open("w", encoding="utf-8") as mdfile:
sections: list[MDReportBase] = [
Expand All @@ -58,8 +51,7 @@ def generate(cls, results: ResultManager, md_filename: Path, *, only_failed_test
SummaryTotals(mdfile, results),
SummaryTotalsDeviceUnderTest(mdfile, results),
SummaryTotalsPerCategory(mdfile, results),
FailedTestResultsSummary(mdfile, results),
AllTestResults(mdfile, results),
TestResults(mdfile, results),
]
for section in sections:
section.generate_section()
Expand All @@ -76,8 +68,6 @@ class MDReportBase(ABC):
to generate and write content to the provided markdown file.
"""

ONLY_FAILED_TESTS: ClassVar[bool] = False

def __init__(self, mdfile: TextIOWrapper, results: ResultManager) -> None:
"""Initialize the MDReportBase with an open markdown file object to write to and a ResultManager instance.
Expand Down Expand Up @@ -113,7 +103,7 @@ def generate_heading_name(self) -> str:
-------
str: Formatted header name.
Example:
Example
-------
- `ANTAReport` will become ANTA Report.
- `TestResultsSummary` will become Test Results Summary.
Expand Down Expand Up @@ -151,7 +141,7 @@ def write_heading(self, heading_level: int) -> None:
----------
heading_level: The level of the heading (1-6).
Example:
Example
-------
## Test Results Summary
"""
Expand Down Expand Up @@ -190,10 +180,6 @@ def generate_section(self) -> None:
"""Generate the `# ANTA Report` section of the markdown report."""
self.write_heading(heading_level=1)
toc = MD_REPORT_TOC

if not self.ONLY_FAILED_TESTS:
toc += "\n - [All Test Results](#all-test-results)"

self.mdfile.write(toc + "\n\n")


Expand All @@ -217,10 +203,10 @@ def generate_rows(self) -> Generator[str, None, None]:
"""Generate the rows of the summary totals table."""
yield (
f"| {self.results.get_total_results()} "
f"| {self.results.get_total_results('success')} "
f"| {self.results.get_total_results('skipped')} "
f"| {self.results.get_total_results('failure')} "
f"| {self.results.get_total_results('error')} |\n"
f"| {self.results.get_total_results({'success'})} "
f"| {self.results.get_total_results({'skipped'})} "
f"| {self.results.get_total_results({'failure'})} "
f"| {self.results.get_total_results({'error'})} |\n"
)

def generate_section(self) -> None:
Expand Down Expand Up @@ -277,35 +263,8 @@ def generate_section(self) -> None:
self.write_table(table_heading=self.TABLE_HEADING)


class FailedTestResultsSummary(MDReportBase):
"""Generate the `## Failed Test Results Summary` section of the markdown report."""

TABLE_HEADING: ClassVar[list[str]] = [
"| Device Under Test | Categories | Test | Description | Custom Field | Result | Messages |",
"| ----------------- | ---------- | ---- | ----------- | ------------ | ------ | -------- |",
]

def generate_rows(self) -> Generator[str, None, None]:
"""Generate the rows of the failed test results table."""
for result in self.results.get_results(status={"failure", "error"}, sort_by=["name", "test"]):
messages = self.safe_markdown(", ".join(result.messages))
categories = ", ".join(result.categories)
yield (
f"| {result.name or '-'} | {categories or '-'} | {result.test or '-'} "
f"| {result.description or '-'} | {self.safe_markdown(result.custom_field) or '-'} | {result.result or '-'} | {messages or '-'} |\n"
)

def generate_section(self) -> None:
"""Generate the `## Failed Test Results Summary` section of the markdown report."""
self.write_heading(heading_level=2)
self.write_table(table_heading=self.TABLE_HEADING, last_table=self.ONLY_FAILED_TESTS)


class AllTestResults(MDReportBase):
"""Generates the `## All Test Results` section of the markdown report.
This section is generated only if the report includes all results.
"""
class TestResults(MDReportBase):
"""Generates the `## Test Results` section of the markdown report."""

TABLE_HEADING: ClassVar[list[str]] = [
"| Device Under Test | Categories | Test | Description | Custom Field | Result | Messages |",
Expand All @@ -323,10 +282,6 @@ def generate_rows(self) -> Generator[str, None, None]:
)

def generate_section(self) -> None:
"""Generate the `## All Test Results` section of the markdown report.
This section is generated only if the report includes all results.
"""
if not self.ONLY_FAILED_TESTS:
self.write_heading(heading_level=2)
self.write_table(table_heading=self.TABLE_HEADING, last_table=True)
"""Generate the `## Test Results` section of the markdown report."""
self.write_heading(heading_level=2)
self.write_table(table_heading=self.TABLE_HEADING, last_table=True)
27 changes: 8 additions & 19 deletions anta/result_manager/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,29 +209,22 @@ def add(self, result: TestResult) -> None:
# Every time a new result is added, we need to clear the cached property
self.__dict__.pop("results_by_status", None)

def get_results(self, status: set[TestStatus] | TestStatus | None = None, sort_by: list[str] | None = None) -> list[TestResult]:
def get_results(self, status: set[TestStatus] | None = None, sort_by: list[str] | None = None) -> list[TestResult]:
"""Get the results, optionally filtered by status and sorted by TestResult fields.
If no status is provided, all results are returned.
Parameters
----------
status: Optional TestStatus or set of TestStatus literals to filter the results.
status: Optional set of TestStatus literals to filter the results.
sort_by: Optional list of TestResult fields to sort the results.
Returns
-------
List of TestResult.
"""
if status is None:
# Return all results
results = self._result_entries
elif isinstance(status, set):
# Return results for multiple statuses
results = list(chain.from_iterable(self.results_by_status.get(status, []) for status in status))
else:
# Return results for a single status
results = self.results_by_status.get(status, [])
# Return all results if no status is provided, otherwise return results for multiple statuses
results = self._result_entries if status is None else list(chain.from_iterable(self.results_by_status.get(status, []) for status in status))

if sort_by:
accepted_fields = TestResult.model_fields.keys()
Expand All @@ -242,14 +235,14 @@ def get_results(self, status: set[TestStatus] | TestStatus | None = None, sort_b

return results

def get_total_results(self, status: set[TestStatus] | TestStatus | None = None) -> int:
def get_total_results(self, status: set[TestStatus] | None = None) -> int:
"""Get the total number of results, optionally filtered by status.
If no status is provided, the total number of results is returned.
Parameters
----------
status: TestStatus or set of TestStatus literals to filter the results.
status: Optional set of TestStatus literals to filter the results.
Returns
-------
Expand All @@ -259,12 +252,8 @@ def get_total_results(self, status: set[TestStatus] | TestStatus | None = None)
# Return the total number of results
return sum(len(results) for results in self.results_by_status.values())

if isinstance(status, set):
# Return the total number of results for multiple statuses
return sum(len(self.results_by_status.get(status, [])) for status in status)

# Return the total number of results for a single status
return len(self.results_by_status.get(status, []))
# Return the total number of results for multiple statuses
return sum(len(self.results_by_status.get(status, [])) for status in status)

def get_status(self, *, ignore_error: bool = False) -> str:
"""Return the current status including error_status if ignore_error is False."""
Expand Down
14 changes: 5 additions & 9 deletions docs/cli/nrfu.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ Options `--device` and `--test` can be used to target one or multiple devices an

### Hide results

Option `--hide` can be used to hide test results in the output based on their status. The option can be repeated. Example: `anta nrfu --hide error --hide skipped`.
Option `--hide` can be used to hide test results in the output or report file based on their status. The option can be repeated. Example: `anta nrfu --hide error --hide skipped`.

## Performing NRFU with text rendering

Expand Down Expand Up @@ -169,9 +169,7 @@ Options:

## Performing NRFU and saving results in a Markdown file

The `md-report` command in NRFU testing generates a comprehensive Markdown report containing various sections, including detailed statistics for devices and test categories. By default, this command saves all test results from the current run in the Markdown file. However, you can choose to include only failed tests by using the `--only-failed-tests` option in the command line interface.

This feature is particularly useful for comparing reports from multiple runs, allowing you to quickly identify and track issues across your network over time. By focusing on failed tests, you can efficiently pinpoint areas that require attention or have shown improvement between different test executions.
The `md-report` command in NRFU testing generates a comprehensive Markdown report containing various sections, including detailed statistics for devices and test categories.

### Command overview

Expand All @@ -183,11 +181,9 @@ Usage: anta nrfu md-report [OPTIONS]
ANTA command to check network state with Markdown report.

Options:
--md-output FILE Path to save the report as a Markdown file [env var:
ANTA_NRFU_MD_REPORT_MD_OUTPUT; required]
--only-failed-tests Only include failed tests in the report. [env var:
ANTA_NRFU_MD_REPORT_ONLY_FAILED_TESTS]
--help Show this message and exit.
--md-output FILE Path to save the report as a Markdown file [env var:
ANTA_NRFU_MD_REPORT_MD_OUTPUT; required]
--help Show this message and exit.
```

### Example
Expand Down
Loading

0 comments on commit 8918cd0

Please sign in to comment.