blob: c34712c70583405038ddc03cf9c56c661bea205c [file]
############################################################################
# SPDX-License-Identifier: Apache-2.0
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership. The
# ASF licenses this file to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance with the
# License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
############################################################################
"""Tests for NTFC report generation module."""
import os
import tempfile
from xml.etree.ElementTree import Element, ElementTree, SubElement
from ntfc.log.report import Reporter
def create_test_xml(
filename: str,
tests: int = 10,
passes: int = 8,
failures: int = 2,
skipped: int = 0,
errors: int = 0,
time: float = 1.5,
) -> str:
"""Create a test JUnit XML file."""
testsuites = Element("testsuites")
testsuite = SubElement(testsuites, "testsuite")
testsuite.set("tests", str(tests))
testsuite.set("failures", str(failures))
testsuite.set("skipped", str(skipped))
testsuite.set("errors", str(errors))
testsuite.set("time", str(time))
testsuite.set("name", os.path.basename(filename).replace(".xml", ""))
tree = ElementTree(testsuites)
tree.write(filename)
return filename
def test_generate_result_summary_with_single_xml_file():
"""Test generate_result_summary with a single XML file."""
with tempfile.TemporaryDirectory() as tmpdir:
report_dir = os.path.join(tmpdir, "report")
os.makedirs(report_dir)
# Create test XML file directly in report_dir
xml_file = os.path.join(report_dir, "001_test.xml")
create_test_xml(xml_file, tests=10, passes=8, failures=2)
# Call generate_result_summary - should not raise
reporter = Reporter()
reporter.generate_result_summary(tmpdir)
# Verify summary files were created in report_dir
assert os.path.exists(os.path.join(report_dir, "result_summary.txt"))
assert os.path.exists(os.path.join(report_dir, "result_summary.html"))
def test_generate_result_summary_with_multiple_files():
"""Test generate_result_summary aggregates multiple XML files."""
with tempfile.TemporaryDirectory() as tmpdir:
report_dir = os.path.join(tmpdir, "report")
os.makedirs(report_dir)
# Create multiple test XML files in report_dir
xml_file1 = os.path.join(report_dir, "001_module1.xml")
xml_file2 = os.path.join(report_dir, "002_module2.xml")
create_test_xml(xml_file1, tests=10, passes=8, failures=2)
create_test_xml(xml_file2, tests=5, passes=5, failures=0)
reporter = Reporter()
reporter.generate_result_summary(tmpdir)
# Verify both summary files created and contain results
summary_file = os.path.join(report_dir, "result_summary.txt")
assert os.path.exists(summary_file)
with open(summary_file) as f:
content = f.read()
# Should have summary with passes and failures
assert "passes:" in content or "Pass" in content
def test_generate_result_summary_with_skipped_tests():
"""Test generate_result_summary with skipped tests."""
with tempfile.TemporaryDirectory() as tmpdir:
report_dir = os.path.join(tmpdir, "report")
os.makedirs(report_dir)
xml_file = os.path.join(report_dir, "001_test.xml")
create_test_xml(
xml_file, tests=10, passes=5, failures=0, skipped=5, errors=0
)
reporter = Reporter()
reporter.generate_result_summary(tmpdir)
summary_file = os.path.join(report_dir, "result_summary.txt")
with open(summary_file) as f:
content = f.read()
assert "skipped" in content
def test_generate_result_summary_with_errors():
"""Test generate_result_summary with test errors."""
with tempfile.TemporaryDirectory() as tmpdir:
report_dir = os.path.join(tmpdir, "report")
os.makedirs(report_dir)
xml_file = os.path.join(report_dir, "001_test.xml")
create_test_xml(xml_file, tests=10, passes=7, failures=2, errors=1)
reporter = Reporter()
reporter.generate_result_summary(tmpdir)
summary_file = os.path.join(report_dir, "result_summary.txt")
with open(summary_file) as f:
content = f.read()
assert "errors" in content
def test_generate_result_summary_skips_skip_list():
"""Test generate_result_summary ignores skip_list.xml."""
with tempfile.TemporaryDirectory() as tmpdir:
report_dir = os.path.join(tmpdir, "report")
logs_dir = os.path.join(tmpdir, "logs")
os.makedirs(report_dir)
os.makedirs(logs_dir)
# Create skip_list.xml which should be ignored
skip_list_file = os.path.join(logs_dir, "skip_list.xml")
create_test_xml(skip_list_file, tests=5, passes=5)
# Create actual test file in report_dir
xml_file = os.path.join(report_dir, "001_test.xml")
create_test_xml(xml_file, tests=10, passes=8, failures=2)
reporter = Reporter()
reporter.generate_result_summary(tmpdir)
summary_file = os.path.join(report_dir, "result_summary.txt")
with open(summary_file) as f:
content = f.read()
# Verify summary was created (skip_list should be ignored)
assert os.path.exists(summary_file)
assert "RESULT_SUMMARY" in content or "Summary" in content
def test_generate_result_summary_with_invalid_xml():
"""Test generate_result_summary handles invalid XML gracefully."""
with tempfile.TemporaryDirectory() as tmpdir:
report_dir = os.path.join(tmpdir, "report")
os.makedirs(report_dir)
# Create invalid XML file in report_dir
invalid_xml = os.path.join(report_dir, "001_invalid.xml")
with open(invalid_xml, "w") as f:
f.write("not valid xml content")
# Should not raise exception
reporter = Reporter()
reporter.generate_result_summary(tmpdir)
def test_generate_result_summary_missing_testsuite():
"""Test generate_result_summary with XML missing testsuite element."""
with tempfile.TemporaryDirectory() as tmpdir:
report_dir = os.path.join(tmpdir, "report")
os.makedirs(report_dir)
# Create XML without testsuite element in report_dir
xml_file = os.path.join(report_dir, "001_test.xml")
testsuites = Element("testsuites")
tree = ElementTree(testsuites)
tree.write(xml_file)
# Should handle gracefully
reporter = Reporter()
reporter.generate_result_summary(tmpdir)
def test_generate_result_summary_html_output():
"""Test generate_result_summary generates HTML with hyperlinks."""
with tempfile.TemporaryDirectory() as tmpdir:
report_dir = os.path.join(tmpdir, "report")
os.makedirs(report_dir)
xml_file = os.path.join(report_dir, "001_test.xml")
create_test_xml(xml_file, tests=10, passes=8, failures=2)
reporter = Reporter()
reporter.generate_result_summary(tmpdir)
# Check HTML file exists in report_dir and contains hyperlinks
html_file = os.path.join(report_dir, "result_summary.html")
assert os.path.exists(html_file)
with open(html_file) as f:
html_content = f.read()
assert "<a href=" in html_content
def test_generate_result_summary_with_nested_directories():
"""Test generate_result_summary with XML files in nested directories."""
with tempfile.TemporaryDirectory() as tmpdir:
# report_dir is created by generate_result_summary itself
report_dir = os.path.join(tmpdir, "report")
os.makedirs(report_dir)
xml_file = os.path.join(report_dir, "001_test.xml")
create_test_xml(xml_file, tests=10, passes=8, failures=2)
reporter = Reporter()
reporter.generate_result_summary(tmpdir)
# Summary should be in report_dir
summary_file = os.path.join(report_dir, "result_summary.txt")
assert os.path.exists(summary_file)
def test_generate_result_summary_exception_handling():
"""Test generate_result_summary handles exceptions gracefully."""
with tempfile.TemporaryDirectory() as tmpdir:
# Call with valid but empty directory (no XMLs anywhere)
# Should not raise even with no XML files
reporter = Reporter()
reporter.generate_result_summary(tmpdir)
def test_generate_result_summary_with_zero_time():
"""Test generate_result_summary with zero test execution time."""
with tempfile.TemporaryDirectory() as tmpdir:
report_dir = os.path.join(tmpdir, "report")
os.makedirs(report_dir)
xml_file = os.path.join(report_dir, "001_test.xml")
create_test_xml(xml_file, tests=5, passes=5, time=0.0)
reporter = Reporter()
reporter.generate_result_summary(tmpdir)
summary_file = os.path.join(report_dir, "result_summary.txt")
with open(summary_file) as f:
content = f.read()
# Should handle zero time properly
assert "time:" in content
def test_generate_result_summary_with_large_time():
"""Test generate_result_summary with large test execution time."""
with tempfile.TemporaryDirectory() as tmpdir:
report_dir = os.path.join(tmpdir, "report")
os.makedirs(report_dir)
xml_file = os.path.join(report_dir, "001_test.xml")
create_test_xml(xml_file, tests=5, passes=5, time=3600.5)
reporter = Reporter()
reporter.generate_result_summary(tmpdir)
summary_file = os.path.join(report_dir, "result_summary.txt")
assert os.path.exists(summary_file)
def test_generate_result_summary_complex_scenario():
"""Test generate_result_summary with complex scenario."""
with tempfile.TemporaryDirectory() as tmpdir:
report_dir = os.path.join(tmpdir, "report")
os.makedirs(report_dir)
# Create multiple files with varying results in report_dir
create_test_xml(
os.path.join(report_dir, "001_module1.xml"),
tests=20,
passes=18,
failures=2,
skipped=0,
errors=0,
)
create_test_xml(
os.path.join(report_dir, "002_module2.xml"),
tests=15,
passes=12,
failures=2,
skipped=1,
errors=0,
)
create_test_xml(
os.path.join(report_dir, "003_module3.xml"),
tests=10,
passes=8,
failures=1,
skipped=0,
errors=1,
)
reporter = Reporter()
reporter.generate_result_summary(tmpdir)
# Verify all files were processed and summary created
summary_file = os.path.join(report_dir, "result_summary.txt")
assert os.path.exists(summary_file)
with open(summary_file) as f:
content = f.read()
# Should contain summary information
assert "RESULT_SUMMARY" in content or "Summary" in content
def test_split_xml_by_module():
"""Test splitting a single XML report into per-module files."""
with tempfile.TemporaryDirectory() as tmpdir:
# Create a single XML file with tests from multiple modules
xml_file = os.path.join(tmpdir, "report.xml")
testsuites = Element("testsuites")
testsuite = SubElement(testsuites, "testsuite")
testsuite.set("tests", "6")
testsuite.set("failures", "1")
testsuite.set("skipped", "0")
testsuite.set("errors", "0")
testsuite.set("time", "2.5")
# Add testcases from different modules
tc1 = SubElement(testsuite, "testcase")
tc1.set("name", "test_one")
tc1.set("classname", "test_module1.py::test_one")
tc1.set("time", "1.0")
tc2 = SubElement(testsuite, "testcase")
tc2.set("name", "test_two")
tc2.set("classname", "test_module1.py::test_two")
tc2.set("time", "0.5")
tc3 = SubElement(testsuite, "testcase")
tc3.set("name", "test_three")
tc3.set("classname", "test_module2.py::test_three")
tc3.set("time", "1.0")
failure = SubElement(tc3, "failure")
failure.set("message", "Test failed")
tree = ElementTree(testsuites)
tree.write(xml_file)
# Split the XML
reporter = Reporter()
module_files = reporter._split_xml_by_module(xml_file, tmpdir)
# Should have 2 module files
assert len(module_files) == 2
assert "test_module1" in module_files
assert "test_module2" in module_files
# Verify files exist
for module_file in module_files.values():
assert os.path.exists(module_file)
def test_split_xml_by_module_nonexistent_file():
"""Test _split_xml_by_module with nonexistent file."""
with tempfile.TemporaryDirectory() as tmpdir:
reporter = Reporter()
result = reporter._split_xml_by_module(
os.path.join(tmpdir, "nonexistent.xml"), tmpdir
)
assert result == {}
def test_split_xml_by_module_invalid_xml():
"""Test _split_xml_by_module with invalid XML."""
with tempfile.TemporaryDirectory() as tmpdir:
invalid_xml = os.path.join(tmpdir, "invalid.xml")
with open(invalid_xml, "w") as f:
f.write("not valid xml")
reporter = Reporter()
result = reporter._split_xml_by_module(invalid_xml, tmpdir)
assert result == {}
def test_generate_html_for_module():
"""Test HTML generation for a module report."""
with tempfile.TemporaryDirectory() as tmpdir:
xml_file = os.path.join(tmpdir, "test_module.xml")
create_test_xml(xml_file, tests=5, passes=4, failures=1, errors=0)
html_file = os.path.join(tmpdir, "test_module.html")
reporter = Reporter()
reporter._generate_html_for_module(xml_file, html_file)
# Verify HTML file was created
assert os.path.exists(html_file)
# Verify HTML contains expected content
with open(html_file) as f:
html_content = f.read()
assert "<html>" in html_content.lower()
assert "test_module" in html_content
assert "4" in html_content # passed count
assert "1" in html_content # failed count
def test_generate_result_summary_splits_single_report():
"""Test splitting single report.xml into per-module files in report_dir."""
with tempfile.TemporaryDirectory() as tmpdir:
# Create a single report.xml file (as pytest would) in session_dir
single_xml = os.path.join(tmpdir, "report.xml")
testsuites = Element("testsuites")
testsuite = SubElement(testsuites, "testsuite")
testsuite.set("tests", "4")
testsuite.set("failures", "1")
testsuite.set("errors", "0")
testsuite.set("skipped", "0")
testsuite.set("time", "2.0")
testsuite.set("name", "tests")
# Add tests from different modules
tc1 = SubElement(testsuite, "testcase")
tc1.set("name", "test_func1")
tc1.set("classname", "test_module1.py::test_func1")
tc1.set("time", "1.0")
tc2 = SubElement(testsuite, "testcase")
tc2.set("name", "test_func2")
tc2.set("classname", "test_module1.py::test_func2")
tc2.set("time", "0.5")
tc3 = SubElement(testsuite, "testcase")
tc3.set("name", "test_func3")
tc3.set("classname", "test_module2.py::test_func3")
tc3.set("time", "0.5")
failure = SubElement(tc3, "failure")
failure.set("message", "Assertion failed")
tc4 = SubElement(testsuite, "testcase")
tc4.set("name", "test_func4")
tc4.set("classname", "test_module2.py::test_func4")
tc4.set("time", "0.0")
tree = ElementTree(testsuites)
tree.write(single_xml)
# Also create report.html (as pytest would)
single_html = os.path.join(tmpdir, "report.html")
with open(single_html, "w") as f:
f.write("<html><body>test</body></html>")
# Call generate_result_summary
reporter = Reporter()
reporter.generate_result_summary(tmpdir)
# Verify single files were removed from session_dir
assert not os.path.exists(single_xml)
assert not os.path.exists(single_html)
# Verify per-module files were created in report_dir
report_dir = os.path.join(tmpdir, "report")
module1_xml = os.path.join(report_dir, "001_test_module1.xml")
module1_html = os.path.join(report_dir, "001_test_module1.html")
module2_xml = os.path.join(report_dir, "002_test_module2.xml")
module2_html = os.path.join(report_dir, "002_test_module2.html")
assert os.path.exists(module1_xml)
assert os.path.exists(module1_html)
assert os.path.exists(module2_xml)
assert os.path.exists(module2_html)
# Verify summary files were created in report_dir
assert os.path.exists(os.path.join(report_dir, "result_summary.txt"))
assert os.path.exists(os.path.join(report_dir, "result_summary.html"))