diff options
Diffstat (limited to 'tests/units/reporter')
-rw-r--r-- | tests/units/reporter/conftest.py | 8 | ||||
-rw-r--r-- | tests/units/reporter/test__init__.py | 25 | ||||
-rw-r--r-- | tests/units/reporter/test_csv.py | 94 | ||||
-rw-r--r-- | tests/units/reporter/test_md_reporter.py | 54 |
4 files changed, 165 insertions, 16 deletions
diff --git a/tests/units/reporter/conftest.py b/tests/units/reporter/conftest.py new file mode 100644 index 0000000..ae7d3df --- /dev/null +++ b/tests/units/reporter/conftest.py @@ -0,0 +1,8 @@ +# Copyright (c) 2023-2024 Arista Networks, Inc. +# Use of this source code is governed by the Apache License 2.0 +# that can be found in the LICENSE file. +"""See https://docs.pytest.org/en/stable/reference/fixtures.html#conftest-py-sharing-fixtures-across-multiple-files.""" + +from tests.units.result_manager.conftest import list_result_factory, result_manager, result_manager_factory, test_result_factory + +__all__ = ["result_manager", "result_manager_factory", "list_result_factory", "test_result_factory"] diff --git a/tests/units/reporter/test__init__.py b/tests/units/reporter/test__init__.py index 2fc62ce..af26b54 100644 --- a/tests/units/reporter/test__init__.py +++ b/tests/units/reporter/test__init__.py @@ -13,9 +13,9 @@ from rich.table import Table from anta import RICH_COLOR_PALETTE from anta.reporter import ReportJinja, ReportTable +from anta.result_manager.models import AntaTestStatus if TYPE_CHECKING: - from anta.custom_types import TestStatus from anta.result_manager import ResultManager @@ -47,7 +47,6 @@ class TestReportTable: ) def test__split_list_to_txt_list(self, usr_list: list[str], delimiter: str | None, expected_output: str) -> None: """Test _split_list_to_txt_list.""" - # pylint: disable=protected-access report = ReportTable() assert report._split_list_to_txt_list(usr_list, delimiter) == expected_output @@ -61,7 +60,6 @@ class TestReportTable: ) def test__build_headers(self, headers: list[str]) -> None: """Test _build_headers.""" - # pylint: disable=protected-access report = ReportTable() table = Table() table_column_before = len(table.columns) @@ -73,17 +71,15 @@ class TestReportTable: @pytest.mark.parametrize( ("status", "expected_status"), [ - pytest.param("unknown", "unknown", id="unknown status"), - pytest.param("unset", "[grey74]unset", id="unset status"), - pytest.param("skipped", "[bold orange4]skipped", id="skipped status"), - pytest.param("failure", "[bold red]failure", id="failure status"), - pytest.param("error", "[indian_red]error", id="error status"), - pytest.param("success", "[green4]success", id="success status"), + pytest.param(AntaTestStatus.UNSET, "[grey74]unset", id="unset status"), + pytest.param(AntaTestStatus.SKIPPED, "[bold orange4]skipped", id="skipped status"), + pytest.param(AntaTestStatus.FAILURE, "[bold red]failure", id="failure status"), + pytest.param(AntaTestStatus.ERROR, "[indian_red]error", id="error status"), + pytest.param(AntaTestStatus.SUCCESS, "[green4]success", id="success status"), ], ) - def test__color_result(self, status: TestStatus, expected_status: str) -> None: + def test__color_result(self, status: AntaTestStatus, expected_status: str) -> None: """Test _build_headers.""" - # pylint: disable=protected-access report = ReportTable() assert report._color_result(status) == expected_status @@ -104,7 +100,6 @@ class TestReportTable: expected_length: int, ) -> None: """Test report_all.""" - # pylint: disable=too-many-arguments manager = result_manager_factory(number_of_tests) report = ReportTable() @@ -133,14 +128,13 @@ class TestReportTable: expected_length: int, ) -> None: """Test report_summary_tests.""" - # pylint: disable=too-many-arguments # TODO: refactor this later... this is injecting double test results by modyfing the device name # should be a fixture manager = result_manager_factory(number_of_tests) new_results = [result.model_copy() for result in manager.results] for result in new_results: result.name = "test_device" - result.result = "failure" + result.result = AntaTestStatus.FAILURE report = ReportTable() kwargs = {"tests": [test] if test is not None else None, "title": title} @@ -168,14 +162,13 @@ class TestReportTable: expected_length: int, ) -> None: """Test report_summary_devices.""" - # pylint: disable=too-many-arguments # TODO: refactor this later... this is injecting double test results by modyfing the device name # should be a fixture manager = result_manager_factory(number_of_tests) new_results = [result.model_copy() for result in manager.results] for result in new_results: result.name = dev or "test_device" - result.result = "failure" + result.result = AntaTestStatus.FAILURE manager.results = new_results report = ReportTable() diff --git a/tests/units/reporter/test_csv.py b/tests/units/reporter/test_csv.py new file mode 100644 index 0000000..1d59dae --- /dev/null +++ b/tests/units/reporter/test_csv.py @@ -0,0 +1,94 @@ +# Copyright (c) 2023-2024 Arista Networks, Inc. +# Use of this source code is governed by the Apache License 2.0 +# that can be found in the LICENSE file. +"""Test anta.report.csv_reporter.py.""" + +# pylint: disable=too-few-public-methods + +import csv +import pathlib +from typing import Any, Callable + +import pytest + +from anta.reporter.csv_reporter import ReportCsv +from anta.result_manager import ResultManager +from anta.tools import convert_categories + + +class TestReportCsv: + """Tester for ReportCsv class.""" + + def compare_csv_and_result(self, rows: list[Any], index: int, result_manager: ResultManager) -> None: + """Compare CSV and TestResult.""" + assert rows[index + 1][0] == result_manager.results[index].name + assert rows[index + 1][1] == result_manager.results[index].test + assert rows[index + 1][2] == result_manager.results[index].result + assert rows[index + 1][3] == ReportCsv().split_list_to_txt_list(result_manager.results[index].messages) + assert rows[index + 1][4] == result_manager.results[index].description + assert rows[index + 1][5] == ReportCsv().split_list_to_txt_list(convert_categories(result_manager.results[index].categories)) + + def test_report_csv_generate( + self, + result_manager_factory: Callable[[int], ResultManager], + tmp_path: pathlib.Path, + ) -> None: + """Test CSV reporter.""" + max_test_entries = 10 + + # Create a temporary CSV file path + csv_filename = tmp_path / "test.csv" + + # Create a ResultManager instance with dummy test results + result_manager = result_manager_factory(max_test_entries) + # Test usecase with list of messages + result_manager.results[0].messages = ["Message 1", "Message 2"] + # Test usecase with list of categories + result_manager.results[1].messages = ["Cat 1", "Cat 2"] + + # Generate the CSV report + ReportCsv.generate(result_manager, csv_filename) + + # Read the generated CSV file + with pathlib.Path.open(csv_filename, encoding="utf-8") as csvfile: + reader = csv.reader(csvfile, delimiter=",") + rows = list(reader) + + # Assert the headers + assert rows[0] == [ + ReportCsv.Headers.device, + ReportCsv.Headers.test_name, + ReportCsv.Headers.test_status, + ReportCsv.Headers.messages, + ReportCsv.Headers.description, + ReportCsv.Headers.categories, + ] + + # Assert the test result rows + for index in [0, max_test_entries - 1]: + self.compare_csv_and_result(rows, index, result_manager) + + # Assert number of lines: Number of TestResults + CSV Headers + assert len(rows) == len(result_manager.results) + 1 + + def test_report_csv_generate_os_error( + self, + result_manager_factory: Callable[[int], ResultManager], + tmp_path: pathlib.Path, + caplog: pytest.LogCaptureFixture, + ) -> None: + """Test CSV reporter OSError.""" + # Create a ResultManager instance with dummy test results + max_test_entries = 10 + result_manager = result_manager_factory(max_test_entries) + + # Create a temporary CSV file path and make tmp_path read_only + tmp_path.chmod(0o400) + csv_filename = tmp_path / "read_only.csv" + + with pytest.raises(OSError, match="Permission denied"): + # Generate the CSV report + ReportCsv.generate(result_manager, csv_filename) + + assert len(caplog.record_tuples) == 1 + assert "OSError caught while writing the CSV file" in caplog.text diff --git a/tests/units/reporter/test_md_reporter.py b/tests/units/reporter/test_md_reporter.py new file mode 100644 index 0000000..a607733 --- /dev/null +++ b/tests/units/reporter/test_md_reporter.py @@ -0,0 +1,54 @@ +# Copyright (c) 2023-2024 Arista Networks, Inc. +# Use of this source code is governed by the Apache License 2.0 +# that can be found in the LICENSE file. +"""Test anta.reporter.md_reporter.py.""" + +from __future__ import annotations + +from io import StringIO +from pathlib import Path + +import pytest + +from anta.reporter.md_reporter import MDReportBase, MDReportGenerator +from anta.result_manager import ResultManager + +DATA_DIR: Path = Path(__file__).parent.parent.parent.resolve() / "data" + + +def test_md_report_generate(tmp_path: Path, result_manager: ResultManager) -> None: + """Test the MDReportGenerator class.""" + md_filename = tmp_path / "test.md" + expected_report = "test_md_report.md" + + # Generate the Markdown report + MDReportGenerator.generate(result_manager, md_filename) + assert md_filename.exists() + + # Load the existing Markdown report to compare with the generated one + with (DATA_DIR / expected_report).open("r", encoding="utf-8") as f: + expected_content = f.read() + + # Check the content of the Markdown file + content = md_filename.read_text(encoding="utf-8") + + assert content == expected_content + + +def test_md_report_base() -> None: + """Test the MDReportBase class.""" + + class FakeMDReportBase(MDReportBase): + """Fake MDReportBase class.""" + + def generate_section(self) -> None: + pass + + results = ResultManager() + + with StringIO() as mock_file: + report = FakeMDReportBase(mock_file, results) + assert report.generate_heading_name() == "Fake MD Report Base" + + with pytest.raises(NotImplementedError, match="Subclasses should implement this method"): + report.generate_rows() |