Skip to content

Commit f33a0de

Browse files
authored
Updated tests (#243)
* Updated tests * fix tests * fix tests * fix tests on windows * update coverage threshold
1 parent e1283a8 commit f33a0de

8 files changed

Lines changed: 712 additions & 103 deletions

File tree

.github/workflows/unit-test-windows.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ jobs:
7171
$env:PYTHONWARNINGS = "error"
7272
poetry run pytest `
7373
--cov=pytest_html_plus `
74-
--cov-fail-under=39 `
74+
--cov-fail-under=75 `
7575
--cov-report=term `
7676
--reruns 1 `
7777
--ignore=tests/browser `

.github/workflows/unit-test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ jobs:
5757
export REPORT_COMMIT="$(git rev-parse HEAD)"
5858
poetry run pytest \
5959
--cov=pytest_html_plus \
60-
--cov-fail-under=39 \
60+
--cov-fail-under=75 \
6161
--cov-report=term \
6262
--cov-report=xml:coverage.xml \
6363
--reruns 1 \

README.md

Lines changed: 54 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,42 @@
99

1010
[![Discord](https://img.shields.io/discord/1377581416337903646?labelColor=black&logo=discord&logoColor=c20a71&style=for-the-badge&color=c20a71)](https://discord.gg/nUNZ9crf)
1111

12+
---
13+
14+
## Already using pytest-html?
15+
16+
No uninstall needed — `pytest-html-plus` works alongside it. Install it, run your suite, and see what you've been missing. Most teams uninstall `pytest-html` within the same day.
17+
18+
```bash
19+
pip install pytest-html-plus
20+
```
21+
22+
Your existing `pytest --html=report.html` commands keep working unchanged.
23+
24+
| Feature | pytest-html | pytest-html-plus |
25+
|---|:---:|:---:|
26+
| Single-file self-contained HTML report |||
27+
| Zero config — works out of the box |||
28+
| xdist parallel run support | ⚠️ requires extra plugin | ✅ built-in |
29+
| Screenshots (no conftest hooks) |||
30+
| Automatic log & print() capture |||
31+
| Flaky test detection + retry history |||
32+
| Slow test highlighting |||
33+
| Traceability links (Jira, Testmo, etc.) |||
34+
| Dynamic markers / tags |||
35+
| Universal search across tests |||
36+
| Unlinked test detection |||
37+
| Copy logs & traces to clipboard |||
38+
| JUnit XML export (merged, one flag) | ❌ requires extra steps ||
39+
| Run metadata (branch, commit, env) |||
40+
| Reusable config profiles |||
41+
| Email reports |||
42+
| Mobile-friendly layout |||
43+
| GitHub Actions marketplace action |||
44+
| VSCode extension |||
45+
46+
---
47+
1248
## 🚀 Installation
1349

1450
```bash
@@ -19,7 +55,7 @@ poetry add pytest-html-plus
1955

2056
## Pytest HTML Plus Action
2157

22-
If you dont want the burden of installing pytest-html-plus manually and your project already manages dependencies with `requirements.txt` or Poetry, use this GitHub Action to generate rich pytest reports automatically.
58+
If you don't want the burden of installing pytest-html-plus manually and your project already manages dependencies with `requirements.txt` or Poetry, use this GitHub Action to generate rich pytest reports automatically.
2359

2460
[![🚀 Checkout on GitHub Marketplace](https://img.shields.io/badge/Marketplace-Pytest%20HTML%20Plus-blue?logo=github)](https://github.com/marketplace/actions/pytest-html-plus-action)
2561
[![Documentation](https://img.shields.io/badge/docs-readthedocs.io-brightgreen)](https://pytest-html-plus.readthedocs.io/en/main/marketplace/usage.html)
@@ -41,7 +77,7 @@ Export a fully merged JUnit XML report effortlessly — no external tools or plu
4177

4278
![ScreenRecording2025-07-06at11 38 21PM-ezgif com-video-to-gif-converter](https://github.com/user-attachments/assets/02da5cc9-7ef5-4a3a-a475-88907964a9c6)
4379

44-
#### 🔄 Stop Guessing — See Whats Breaking Your Flaky Tests
80+
#### 🔄 Stop Guessing — See What's Breaking Your Flaky Tests
4581
Instantly see how your tests behave across retries — from failure to recovery. Spot patterns like cache issues, race conditions, and random crashes without the guesswork.
4682

4783
![ezgif com-video-to-gif-converter](https://github.com/user-attachments/assets/1f7e0cd8-d2f9-47fd-8909-6f12adf8a800)
@@ -82,7 +118,7 @@ Just start typing, and the dashboard will instantly filter tests by:
82118

83119
#### 📧 Email Test Reports: Send your reports via email effortlessly using SendGrid integration.
84120

85-
![Screenshot 2025-05-28 at 4 38 49PM](https://github.com/user-attachments/assets/3f40e206-5dfd-45e9-a511-4dd206cf3318)
121+
![Screenshot 2025-05-28 at 4 38 49 PM](https://github.com/user-attachments/assets/3f40e206-5dfd-45e9-a511-4dd206cf3318)
86122

87123
#### 🐢 Spot Slow Tests: Highlights the slowest tests so you know where to optimize your suite.
88124

@@ -125,36 +161,32 @@ This plugin is aimed at those who are:
125161

126162
- Are frustrated with archiving folders full of assets, CSS, JS, and dashboards just to share test results.
127163

128-
- Dont want to refactor existing test suites or tag everything with new decorators just to integrate with a reporting tool.
164+
- Don't want to refactor existing test suites or tag everything with new decorators just to integrate with a reporting tool.
129165

130166
- Prefer simplicity — a zero-config, zero code, lightweight report that still looks clean, useful, and polished.
131167

132-
- Want just enough — not bare-bones plain text, not a full dashboard with database setup — just a portable HTML report that STILL supports features like links, screenshots, and markers.
168+
- Want "just enough" — not bare-bones plain text, not a full dashboard with database setup — just a portable HTML report that STILL supports features like links, screenshots, and markers.
133169

170+
## vs Allure
134171

135-
## Comparison with Alternatives
136-
Most existing pytest reporter tools:
172+
Allure is powerful but comes with significant overhead — a separate report server, external assets, and a complex setup. `pytest-html-plus` is for teams that want rich reporting without the infrastructure cost.
137173

138-
Only generate HTML reports from a single run (by making you write code for creating xmls like pytest-html) OR they generate all the JS and png files that are not the scope of test results and force you to archive it.
139-
140-
Heavy duty with bloated charts and other test management features(when they arent your only test management system either) increasing your archive size.
141-
142-
This plugin aims to fill those gaps by acting as a companion layer on top of the JSON report, focusing on:
143-
144-
🔄 Merge + flakiness intelligence
145-
146-
🔗 Traceability via metadata
147-
148-
🧼 HTML that’s both readable and minimal
149-
150-
🧼 Quickly copy test paths and run in your local
174+
| | Allure | pytest-html-plus |
175+
|---|:---:|:---:|
176+
| Self-contained single HTML file |||
177+
| No extra server or CLI tool needed |||
178+
| Zero-config screenshots | ❌ requires decorators ||
179+
| Works in any CI without setup steps |||
180+
| Flaky test detection |||
181+
| Traceability links |||
182+
| JUnit XML export |||
183+
| Report file size (typical run) | 🔴 large (many files) | 🟢 single file |
151184

152185
## Contributing
153186

154187
We welcome pull requests, issues, and feature suggestions from the community.
155188

156-
See the [contribution guide](https://pytest-html-plus.readthedocs.io/en/latest/contributing.html) for setup instructions.
157-
189+
See the [contribution guide](CONTRIBUTING.md) for setup instructions.
158190

159191
## 📜 License
160192

tests/unit/conftest.py

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
"""
2+
Shared fixtures for the pytest-html-plus unit test suite.
3+
"""
4+
5+
import json
6+
7+
import pytest
8+
9+
from pytest_html_plus.compute_filter_counts import compute_filter_count
10+
from pytest_html_plus.generate_html_report import JSONReporter
11+
12+
# All fields that generate_html_report() hard-accesses (no .get() fallback).
13+
# Any test result dict passed to the HTML renderer must include these.
14+
_RESULT_DEFAULTS = {
15+
"worker": "main",
16+
"stdout": "",
17+
"stderr": "",
18+
"error": None,
19+
"trace": None,
20+
"attempts": [],
21+
"links": [],
22+
"markers": [],
23+
"duration": 0.1,
24+
"flaky": False,
25+
"attempt_count": 1,
26+
}
27+
28+
29+
def make_test_result(**kwargs):
30+
"""
31+
Build a valid test result dict with all required fields.
32+
Pass keyword arguments to override any default.
33+
34+
Example:
35+
make_test_result(nodeid="test_x.py::test_a", status="failed", flaky=True)
36+
"""
37+
result = dict(_RESULT_DEFAULTS)
38+
result.update(kwargs)
39+
return result
40+
41+
42+
@pytest.fixture
43+
def reporter_factory(tmp_path):
44+
"""
45+
Returns a factory function that creates a fully initialised JSONReporter
46+
pointed at isolated tmp_path subdirectories, ready to call
47+
generate_html_report() on.
48+
49+
Usage:
50+
def test_something(reporter_factory):
51+
reporter = reporter_factory()
52+
reporter = reporter_factory(results=[make_test_result(...)])
53+
"""
54+
55+
def _make(results=None, report_filename="report.json"):
56+
screenshots_dir = tmp_path / "screenshots"
57+
output_dir = tmp_path / "output"
58+
screenshots_dir.mkdir(exist_ok=True)
59+
output_dir.mkdir(exist_ok=True)
60+
61+
results = results or []
62+
report_file = tmp_path / report_filename
63+
report_file.write_text(json.dumps({"results": results, "filters": {}}))
64+
65+
reporter = JSONReporter(
66+
report_path=str(report_file),
67+
screenshots_dir=str(screenshots_dir),
68+
output_dir=str(output_dir),
69+
)
70+
reporter.results = results
71+
reporter.filters = compute_filter_count(results)
72+
reporter.metadata = {}
73+
return reporter
74+
75+
return _make
76+
77+
78+
@pytest.fixture
79+
def screenshots_dir(tmp_path):
80+
"""
81+
A tmp directory pre-populated with fake PNG screenshots.
82+
File names follow the pattern: test_<name>_failure.png
83+
"""
84+
d = tmp_path / "screenshots"
85+
d.mkdir()
86+
for name in ("login", "checkout", "profile"):
87+
(d / f"test_{name}_failure.png").write_bytes(b"\x89PNG\r\nfake")
88+
return d
89+
90+
91+
@pytest.fixture
92+
def output_dir(tmp_path):
93+
"""A clean tmp output directory."""
94+
d = tmp_path / "output"
95+
d.mkdir()
96+
return d
97+
98+
99+
@pytest.fixture
100+
def passing_test_result():
101+
"""A minimal valid passing test result dict."""
102+
return make_test_result(
103+
nodeid="test_sample.py::test_passes",
104+
test="test_passes",
105+
status="passed",
106+
)
107+
108+
109+
@pytest.fixture
110+
def failing_test_result():
111+
"""A minimal valid failing test result dict."""
112+
return make_test_result(
113+
nodeid="test_sample.py::test_fails",
114+
test="test_fails",
115+
status="failed",
116+
error="E AssertionError: something went wrong",
117+
trace="test_sample.py line 5\n assert False",
118+
)
119+
120+
121+
@pytest.fixture
122+
def flaky_test_result():
123+
"""A test result marked as flaky with 3 attempts."""
124+
return make_test_result(
125+
nodeid="test_sample.py::test_flaky",
126+
test="test_flaky",
127+
status="passed",
128+
flaky=True,
129+
attempt_count=3,
130+
flaky_attempts=["failed", "failed", "passed"],
131+
duration=0.5,
132+
)

0 commit comments

Comments
 (0)