|
8 | 8 | pytest --cov=src/rattlesnake --cov-report=html --cov-report=xml --cov-report=term-misssing |
9 | 9 | """ |
10 | 10 |
|
11 | | -import types |
12 | 11 | from pathlib import Path |
| 12 | +import types |
13 | 13 | from typing import Final |
14 | 14 |
|
15 | 15 | import pytest |
|
18 | 18 | CoverageMetric, |
19 | 19 | get_coverage_metric, |
20 | 20 | get_report_html, |
| 21 | + main, |
21 | 22 | run_pytest_report, |
22 | 23 | ) |
23 | 24 |
|
@@ -71,11 +72,47 @@ def test_get_coverage_metrics_bad_attributes(): |
71 | 72 | assert result.coverage == 0.0 |
72 | 73 |
|
73 | 74 |
|
| 75 | +def test_get_coverage_metric_file_not_found(): |
| 76 | + """Tests that get_coverage_metric handles a non-existent file.""" |
| 77 | + fin = Path("non_existent_file.xml") |
| 78 | + result = get_coverage_metric(fin) |
| 79 | + expected = CoverageMetric(lines_valid=0, lines_covered=0) |
| 80 | + assert result.lines_valid == expected.lines_valid |
| 81 | + assert result.lines_covered == expected.lines_covered |
| 82 | + assert result.coverage == expected.coverage |
| 83 | + |
| 84 | + |
| 85 | +def test_get_report_html(): |
| 86 | + """Test get_report_html with minimal valid inputs. |
| 87 | +
|
| 88 | + Ensures generated HTML includes expected static and dynamic content |
| 89 | + like report title, coverage, and summary. |
| 90 | + """ |
| 91 | + coverage_metric = CoverageMetric(lines_valid=200, lines_covered=150) |
| 92 | + report = get_report_html( |
| 93 | + coverage_metric=coverage_metric, |
| 94 | + timestamp="20250815_211112_UTC", |
| 95 | + run_id="123", |
| 96 | + ref_name="main", |
| 97 | + github_sha="abc123def456", |
| 98 | + github_repo="testuser/testrepo", |
| 99 | + ) |
| 100 | + |
| 101 | + assert "<!DOCTYPE html>" in report |
| 102 | + assert "Pytest Report" in report |
| 103 | + assert "Coverage: 75.00%" in report |
| 104 | + assert "<strong>Lines Covered:</strong> 150" in report |
| 105 | + assert "<strong>Total Lines:</strong> 200" in report |
| 106 | + assert 'href="https://github.com/testuser/testrepo/actions/runs/123"' in report |
| 107 | + assert 'href="https://github.com/testuser/testrepo/tree/main"' in report |
| 108 | + assert 'href="https://github.com/testuser/testrepo/commit/abc123def456"' in report |
| 109 | + |
| 110 | + |
74 | 111 | def test_run_pytest_report(): |
75 | 112 | """Tests the main report creation.""" |
76 | 113 |
|
77 | 114 | function_debug: Final[bool] = ( |
78 | | - True # set to True to avoid deleting the temporary output file |
| 115 | + False # set to True to avoid deleting the temporary output file |
79 | 116 | ) |
80 | 117 |
|
81 | 118 | fin = Path(__file__).parent / "files" / "coverage_output_20250807_241800_UTC.xml" |
@@ -124,25 +161,102 @@ def test_run_pytest_report(): |
124 | 161 | print(f"Retained output file: {fout}") |
125 | 162 |
|
126 | 163 |
|
127 | | -# def test_main_success(monkeypatch, capsys): |
128 | | -# """Test the main function for a successful run.""" |
129 | | -# mock_args = types.SimpleNamespace( |
130 | | -# input_file="dummy_input.tx", |
131 | | -# output_file="dummy_output.html", |
132 | | -# timestamp="20250818_123456_UTC", |
133 | | -# run_id="123", |
134 | | -# ref_name="main", |
135 | | -# github_sha="abc", |
136 | | -# github_repo="user/repo", |
137 | | -# ) |
138 | | - |
139 | | -# monkeypatch.setattr("argparse.ArgumentParser.parse_args", lambda self: mock_args) |
140 | | -# monkeypatch.setattr( |
141 | | -# "rattlesnake.cicd.report_pytest.run_pytest_report", |
142 | | -# lambda *args, **kwargs: CoverageMetric(100, 80), |
143 | | -# ) |
144 | | - |
145 | | -# breakpoint() |
146 | | -# main() |
147 | | -# captured = capsys.readouterr() |
148 | | -# assert "Coverage report generated successfully" in captured.out |
| 164 | +def test_main_success(monkeypatch, capsys): |
| 165 | + """Test the main function for a successful run.""" |
| 166 | + mock_args = types.SimpleNamespace( |
| 167 | + input_file="dummy_input.xml", |
| 168 | + output_file="dummy_output.html", |
| 169 | + timestamp="20240101_120000_UTC", |
| 170 | + run_id="123", |
| 171 | + ref_name="main", |
| 172 | + github_sha="abc", |
| 173 | + github_repo="owner/repo", |
| 174 | + ) |
| 175 | + |
| 176 | + monkeypatch.setattr("argparse.ArgumentParser.parse_args", lambda self: mock_args) |
| 177 | + monkeypatch.setattr( |
| 178 | + "rattlesnake.cicd.report_pytest.run_pytest_report", |
| 179 | + lambda *args, **kwargs: CoverageMetric(lines_valid=100, lines_covered=85), |
| 180 | + ) |
| 181 | + |
| 182 | + main() |
| 183 | + captured = capsys.readouterr() |
| 184 | + assert "✅ Pytest HTML report generated: dummy_output.html" in captured.out |
| 185 | + assert "📊 - valid lines of code: 100" in captured.out |
| 186 | + assert "🔍 - lines covered: 85" in captured.out |
| 187 | + assert "🎉 - coverage: 85.0" in captured.out |
| 188 | + |
| 189 | + |
| 190 | +def test_main_file_not_found(monkeypatch, capsys): |
| 191 | + """Test the main function when the input file is not found.""" |
| 192 | + mock_args = types.SimpleNamespace( |
| 193 | + input_file="non_existent.xml", |
| 194 | + output_file="dummy_output.html", |
| 195 | + timestamp="20240101_120000_UTC", |
| 196 | + run_id="123", |
| 197 | + ref_name="main", |
| 198 | + github_sha="abc", |
| 199 | + github_repo="owner/repo", |
| 200 | + ) |
| 201 | + |
| 202 | + monkeypatch.setattr("argparse.ArgumentParser.parse_args", lambda self: mock_args) |
| 203 | + monkeypatch.setattr( |
| 204 | + "rattlesnake.cicd.report_pytest.run_pytest_report", |
| 205 | + lambda *args, **kwargs: exec('raise FileNotFoundError("File not found")'), |
| 206 | + ) |
| 207 | + |
| 208 | + exit_code = main() |
| 209 | + assert exit_code == 1 |
| 210 | + |
| 211 | + captured = capsys.readouterr() |
| 212 | + assert "❌ Error: The input file 'non_existent.xml' was not found." in captured.out |
| 213 | + |
| 214 | + |
| 215 | +def test_main_io_error(monkeypatch, capsys): |
| 216 | + """Test the main function when an IOError occurs.""" |
| 217 | + mock_args = types.SimpleNamespace( |
| 218 | + input_file="dummy_input.xml", |
| 219 | + output_file="dummy_output.html", |
| 220 | + timestamp="20240101_120000_UTC", |
| 221 | + run_id="123", |
| 222 | + ref_name="main", |
| 223 | + github_sha="abc", |
| 224 | + github_repo="owner/repo", |
| 225 | + ) |
| 226 | + |
| 227 | + monkeypatch.setattr("argparse.ArgumentParser.parse_args", lambda self: mock_args) |
| 228 | + monkeypatch.setattr( |
| 229 | + "rattlesnake.cicd.report_pytest.run_pytest_report", |
| 230 | + lambda *args, **kwargs: exec('raise IOError("Permission denied")'), |
| 231 | + ) |
| 232 | + |
| 233 | + exit_code = main() |
| 234 | + assert exit_code == 1 |
| 235 | + |
| 236 | + captured = capsys.readouterr() |
| 237 | + assert "❌ I/O error occurred: Permission denied" in captured.out |
| 238 | + |
| 239 | + |
| 240 | +def test_main_unexpected_error(monkeypatch, capsys): |
| 241 | + """Test the main function for an unexpected error.""" |
| 242 | + mock_args = types.SimpleNamespace( |
| 243 | + input_file="dummy_input.xml", |
| 244 | + output_file="dummy_output.html", |
| 245 | + timestamp="20240101_120000_UTC", |
| 246 | + run_id="123", |
| 247 | + ref_name="main", |
| 248 | + github_sha="abc", |
| 249 | + github_repo="owner/repo", |
| 250 | + ) |
| 251 | + |
| 252 | + monkeypatch.setattr("argparse.ArgumentParser.parse_args", lambda self: mock_args) |
| 253 | + monkeypatch.setattr( |
| 254 | + "rattlesnake.cicd.report_pytest.run_pytest_report", |
| 255 | + lambda *args, **kwargs: exec('raise Exception("Something went wrong")'), |
| 256 | + ) |
| 257 | + |
| 258 | + exit_code = main() |
| 259 | + assert exit_code == 1 |
| 260 | + |
| 261 | + captured = capsys.readouterr() |
| 262 | + assert "❌ An unexpected error occurred: Something went wrong" in captured.out |
0 commit comments