pytest-html-plus 0.5.2__tar.gz → 1.0.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pytest_html_plus-0.5.2 → pytest_html_plus-1.0.1}/PKG-INFO +69 -31
- {pytest_html_plus-0.5.2 → pytest_html_plus-1.0.1}/README.md +62 -28
- {pytest_html_plus-0.5.2 → pytest_html_plus-1.0.1}/pyproject.toml +14 -3
- {pytest_html_plus-0.5.2 → pytest_html_plus-1.0.1}/pytest_html_plus/generate_html_report.py +0 -1
- {pytest_html_plus-0.5.2 → pytest_html_plus-1.0.1}/pytest_html_plus/plugin.py +157 -6
- {pytest_html_plus-0.5.2 → pytest_html_plus-1.0.1}/LICENSE +0 -0
- {pytest_html_plus-0.5.2 → pytest_html_plus-1.0.1}/pytest_html_plus/__init__.py +0 -0
- {pytest_html_plus-0.5.2 → pytest_html_plus-1.0.1}/pytest_html_plus/compute_filter_counts.py +0 -0
- {pytest_html_plus-0.5.2 → pytest_html_plus-1.0.1}/pytest_html_plus/compute_report_metadata.py +0 -0
- {pytest_html_plus-0.5.2 → pytest_html_plus-1.0.1}/pytest_html_plus/extract_link.py +0 -0
- {pytest_html_plus-0.5.2 → pytest_html_plus-1.0.1}/pytest_html_plus/json_merge.py +0 -0
- {pytest_html_plus-0.5.2 → pytest_html_plus-1.0.1}/pytest_html_plus/json_to_xml_converter.py +0 -0
- {pytest_html_plus-0.5.2 → pytest_html_plus-1.0.1}/pytest_html_plus/resolver_driver.py +0 -0
- {pytest_html_plus-0.5.2 → pytest_html_plus-1.0.1}/pytest_html_plus/send_email_report.py +0 -0
- {pytest_html_plus-0.5.2 → pytest_html_plus-1.0.1}/pytest_html_plus/utils.py +0 -0
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: pytest-html-plus
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 1.0.1
|
|
4
4
|
Summary: Generate Actionable, automatic screenshots, unified Mobile friendly Pytest HTML report in less than 3 seconds — no hooks, merge plugins, no config, xdist-ready.
|
|
5
5
|
License: MIT
|
|
6
|
+
License-File: LICENSE
|
|
6
7
|
Keywords: pytest,pytest-plugin,html-report,test-report,screenshot,mobile-report,xdist,allure-alternative,playwright,selenium
|
|
7
8
|
Author: reporterplus
|
|
8
9
|
Maintainer: reporterplus
|
|
9
10
|
Requires-Python: >=3.10,<4.0
|
|
10
|
-
Classifier: Development Status ::
|
|
11
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
11
12
|
Classifier: Framework :: Pytest
|
|
12
13
|
Classifier: Intended Audience :: Developers
|
|
13
14
|
Classifier: License :: OSI Approved :: MIT License
|
|
@@ -17,10 +18,13 @@ Classifier: Programming Language :: Python :: 3.10
|
|
|
17
18
|
Classifier: Programming Language :: Python :: 3.11
|
|
18
19
|
Classifier: Programming Language :: Python :: 3.12
|
|
19
20
|
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
20
22
|
Classifier: Topic :: Software Development :: Quality Assurance
|
|
21
23
|
Classifier: Topic :: Software Development :: Testing
|
|
22
24
|
Requires-Dist: keyring (>=25.6.0,<26.0.0)
|
|
25
|
+
Requires-Dist: tomli (>=2.0.1,<3.0.0) ; python_version < "3.11"
|
|
23
26
|
Requires-Dist: yagmail (>=0.15.293,<0.16.0)
|
|
27
|
+
Project-URL: Changelog, https://github.com/reporterplus/pytest-html-plus/blob/main/CHANGELOG.md
|
|
24
28
|
Project-URL: Documentation, https://pytest-html-plus.readthedocs.io
|
|
25
29
|
Project-URL: Homepage, https://github.com/reporterplus/pytest-html-plus
|
|
26
30
|
Project-URL: Source, https://github.com/reporterplus/pytest-html-plus
|
|
@@ -34,9 +38,41 @@ Description-Content-Type: text/markdown
|
|
|
34
38
|
|
|
35
39
|
➡️ [View Demo Report](https://reporterplus.github.io/pytest-html-plus/)
|
|
36
40
|
|
|
37
|
-
[](https://pytest-html-plus.readthedocs.io/en/main/) [](https://pepy.tech/projects/pytest-html-plus)    [](https://pytest-html-plus.readthedocs.io/en/main/) [](https://pepy.tech/projects/pytest-html-plus)    [](https://github.com/reporterplus/pytest-html-plus/actions/workflows/unit-test.yml) [](https://codecov.io/gh/reporterplus/pytest-html-plus)
|
|
38
42
|
|
|
39
|
-
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## Already using pytest-html or Allure?
|
|
46
|
+
|
|
47
|
+
No uninstall needed — `pytest-html-plus` works alongside `pytest-html`. Install it, run your suite, and see what you've been missing. Most teams uninstall `pytest-html` within the same day.
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
pip install pytest-html-plus
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Your existing `pytest --html=report.html` commands keep working unchanged.
|
|
54
|
+
|
|
55
|
+
| Feature | pytest-html | Allure | pytest-html-plus |
|
|
56
|
+
|---|:---:|:---:|:---:|
|
|
57
|
+
| Self-contained single HTML file | ✅ | ❌ | ✅ |
|
|
58
|
+
| No server or CLI tool needed | ✅ | ❌ | ✅ |
|
|
59
|
+
| Zero config — works out of the box | ✅ | ❌ | ✅ |
|
|
60
|
+
| xdist parallel run support | ⚠️ extra plugin | ✅ | ✅ built-in |
|
|
61
|
+
| Screenshots (no hooks or decorators) | ❌ | ❌ requires decorators | ✅ |
|
|
62
|
+
| Automatic log & print() capture | ❌ | ✅ | ✅ |
|
|
63
|
+
| Flaky test detection + retry history | ❌ | ✅ | ✅ |
|
|
64
|
+
| Slow test highlighting | ❌ | ❌ | ✅ |
|
|
65
|
+
| Traceability links (Jira, Testmo, etc.) | ❌ | ✅ | ✅ |
|
|
66
|
+
| JUnit XML export (merged, one flag) | ❌ extra steps | ✅ | ✅ |
|
|
67
|
+
| Run metadata (branch, commit, env) | ❌ | ✅ | ✅ |
|
|
68
|
+
| Reusable config profiles | ❌ | ❌ | ✅ |
|
|
69
|
+
| Unlinked test detection | ❌ | ❌ | ✅ |
|
|
70
|
+
| Copy logs & traces to clipboard | ❌ | ❌ | ✅ |
|
|
71
|
+
| Email reports | ❌ | ❌ | ✅ |
|
|
72
|
+
| Mobile-friendly layout | ❌ | ✅ | ✅ |
|
|
73
|
+
| Report size | 🟢 single file | 🔴 many files | 🟢 single file |
|
|
74
|
+
|
|
75
|
+
---
|
|
40
76
|
|
|
41
77
|
## 🚀 Installation
|
|
42
78
|
|
|
@@ -48,7 +84,7 @@ poetry add pytest-html-plus
|
|
|
48
84
|
|
|
49
85
|
## Pytest HTML Plus Action
|
|
50
86
|
|
|
51
|
-
If you don
|
|
87
|
+
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.
|
|
52
88
|
|
|
53
89
|
[](https://github.com/marketplace/actions/pytest-html-plus-action)
|
|
54
90
|
[](https://pytest-html-plus.readthedocs.io/en/main/marketplace/usage.html)
|
|
@@ -70,7 +106,7 @@ Export a fully merged JUnit XML report effortlessly — no external tools or plu
|
|
|
70
106
|
|
|
71
107
|

|
|
72
108
|
|
|
73
|
-
#### 🔄 Stop Guessing — See What
|
|
109
|
+
#### 🔄 Stop Guessing — See What's Breaking Your Flaky Tests
|
|
74
110
|
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.
|
|
75
111
|
|
|
76
112
|

|
|
@@ -111,7 +147,7 @@ Just start typing, and the dashboard will instantly filter tests by:
|
|
|
111
147
|
|
|
112
148
|
#### 📧 Email Test Reports: Send your reports via email effortlessly using SendGrid integration.
|
|
113
149
|
|
|
114
|
-

|
|
115
151
|
|
|
116
152
|
#### 🐢 Spot Slow Tests: Highlights the slowest tests so you know where to optimize your suite.
|
|
117
153
|
|
|
@@ -121,7 +157,28 @@ Just start typing, and the dashboard will instantly filter tests by:
|
|
|
121
157
|
|
|
122
158
|

|
|
123
159
|
|
|
124
|
-
###
|
|
160
|
+
### Complete Feature List
|
|
161
|
+
|
|
162
|
+
| Feature | Details |
|
|
163
|
+
|---|---|
|
|
164
|
+
| 📊 **Single-file HTML report** | Fully self-contained — no external CSS, JS, or image folders to archive |
|
|
165
|
+
| 🔄 **Flaky test detection** | Detects tests that fail then pass on retry; shows full retry history |
|
|
166
|
+
| 📸 **Automatic screenshots** | Selenium & Playwright screenshots captured and embedded with no conftest hooks |
|
|
167
|
+
| 🧩 **JUnit XML export** | Merged XML output compatible with TestRail, Xray, and Zephyr (`--generate-xml`) |
|
|
168
|
+
| 🔗 **Traceability links** | Attach Jira, Testmo, Notion, or any URL to a test; rendered and searchable in the report |
|
|
169
|
+
| 🏷️ **Dynamic markers** | Tag tests at runtime with `pytest.mark.*` — no marker pre-registration needed |
|
|
170
|
+
| 🔍 **Universal search** | Filter tests by name, issue ID, or any URL keyword in real time |
|
|
171
|
+
| 🐢 **Slow test highlighting** | Slowest tests in the run automatically flagged |
|
|
172
|
+
| 📋 **Copy-to-clipboard** | Copy test path, logs, trace, and errors in one click |
|
|
173
|
+
| 📦 **Run metadata** | Branch, commit SHA, environment, and custom metadata embedded in the report header |
|
|
174
|
+
| 📝 **Comprehensive log capture** | `print()`, logger output, and stdout/stderr automatically captured per test |
|
|
175
|
+
| ⚡ **xdist support** | Parallel runs with `pytest-xdist` produce a single merged report, no extra steps |
|
|
176
|
+
| 🌐 **Auto-open report** | `--should-open-report` opens the report in your browser after a run (always / failed / never) |
|
|
177
|
+
| 📄 **JSON report** | Raw JSON output (`--json-report`) for custom dashboards or post-processing |
|
|
178
|
+
| 🔎 **Unlinked test detection** | Instantly filter tests that have no associated issue or documentation link |
|
|
179
|
+
| ⚙️ **Reusable config profiles** | Define named profiles in `pyproject.toml` (`--profile=ci`) — no more repeated CLI flags |
|
|
180
|
+
| 📱 **Mobile-friendly layout** | Report renders cleanly on any screen size |
|
|
181
|
+
| 📧 **Email reports** | Send reports via SendGrid integration (`--send-email`) |
|
|
125
182
|
|
|
126
183
|
## Target Audience
|
|
127
184
|
|
|
@@ -133,36 +190,17 @@ This plugin is aimed at those who are:
|
|
|
133
190
|
|
|
134
191
|
- Are frustrated with archiving folders full of assets, CSS, JS, and dashboards just to share test results.
|
|
135
192
|
|
|
136
|
-
- Don
|
|
193
|
+
- Don't want to refactor existing test suites or tag everything with new decorators just to integrate with a reporting tool.
|
|
137
194
|
|
|
138
195
|
- Prefer simplicity — a zero-config, zero code, lightweight report that still looks clean, useful, and polished.
|
|
139
196
|
|
|
140
|
-
- Want
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
## Comparison with Alternatives
|
|
144
|
-
Most existing pytest reporter tools:
|
|
145
|
-
|
|
146
|
-
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.
|
|
147
|
-
|
|
148
|
-
Heavy duty with bloated charts and other test management features(when they arent your only test management system either) increasing your archive size.
|
|
149
|
-
|
|
150
|
-
This plugin aims to fill those gaps by acting as a companion layer on top of the JSON report, focusing on:
|
|
151
|
-
|
|
152
|
-
🔄 Merge + flakiness intelligence
|
|
153
|
-
|
|
154
|
-
🔗 Traceability via metadata
|
|
155
|
-
|
|
156
|
-
🧼 HTML that’s both readable and minimal
|
|
157
|
-
|
|
158
|
-
🧼 Quickly copy test paths and run in your local
|
|
197
|
+
- 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.
|
|
159
198
|
|
|
160
199
|
## Contributing
|
|
161
200
|
|
|
162
201
|
We welcome pull requests, issues, and feature suggestions from the community.
|
|
163
202
|
|
|
164
|
-
See the [contribution guide](
|
|
165
|
-
|
|
203
|
+
See the [contribution guide](CONTRIBUTING.md) for setup instructions.
|
|
166
204
|
|
|
167
205
|
## 📜 License
|
|
168
206
|
|
|
@@ -5,9 +5,41 @@
|
|
|
5
5
|
|
|
6
6
|
➡️ [View Demo Report](https://reporterplus.github.io/pytest-html-plus/)
|
|
7
7
|
|
|
8
|
-
[](https://pytest-html-plus.readthedocs.io/en/main/) [](https://pepy.tech/projects/pytest-html-plus)    [](https://pytest-html-plus.readthedocs.io/en/main/) [](https://pepy.tech/projects/pytest-html-plus)    [](https://github.com/reporterplus/pytest-html-plus/actions/workflows/unit-test.yml) [](https://codecov.io/gh/reporterplus/pytest-html-plus)
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Already using pytest-html or Allure?
|
|
13
|
+
|
|
14
|
+
No uninstall needed — `pytest-html-plus` works alongside `pytest-html`. Install it, run your suite, and see what you've been missing. Most teams uninstall `pytest-html` within the same day.
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
pip install pytest-html-plus
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Your existing `pytest --html=report.html` commands keep working unchanged.
|
|
21
|
+
|
|
22
|
+
| Feature | pytest-html | Allure | pytest-html-plus |
|
|
23
|
+
|---|:---:|:---:|:---:|
|
|
24
|
+
| Self-contained single HTML file | ✅ | ❌ | ✅ |
|
|
25
|
+
| No server or CLI tool needed | ✅ | ❌ | ✅ |
|
|
26
|
+
| Zero config — works out of the box | ✅ | ❌ | ✅ |
|
|
27
|
+
| xdist parallel run support | ⚠️ extra plugin | ✅ | ✅ built-in |
|
|
28
|
+
| Screenshots (no hooks or decorators) | ❌ | ❌ requires decorators | ✅ |
|
|
29
|
+
| Automatic log & print() capture | ❌ | ✅ | ✅ |
|
|
30
|
+
| Flaky test detection + retry history | ❌ | ✅ | ✅ |
|
|
31
|
+
| Slow test highlighting | ❌ | ❌ | ✅ |
|
|
32
|
+
| Traceability links (Jira, Testmo, etc.) | ❌ | ✅ | ✅ |
|
|
33
|
+
| JUnit XML export (merged, one flag) | ❌ extra steps | ✅ | ✅ |
|
|
34
|
+
| Run metadata (branch, commit, env) | ❌ | ✅ | ✅ |
|
|
35
|
+
| Reusable config profiles | ❌ | ❌ | ✅ |
|
|
36
|
+
| Unlinked test detection | ❌ | ❌ | ✅ |
|
|
37
|
+
| Copy logs & traces to clipboard | ❌ | ❌ | ✅ |
|
|
38
|
+
| Email reports | ❌ | ❌ | ✅ |
|
|
39
|
+
| Mobile-friendly layout | ❌ | ✅ | ✅ |
|
|
40
|
+
| Report size | 🟢 single file | 🔴 many files | 🟢 single file |
|
|
41
|
+
|
|
42
|
+
---
|
|
11
43
|
|
|
12
44
|
## 🚀 Installation
|
|
13
45
|
|
|
@@ -19,7 +51,7 @@ poetry add pytest-html-plus
|
|
|
19
51
|
|
|
20
52
|
## Pytest HTML Plus Action
|
|
21
53
|
|
|
22
|
-
If you don
|
|
54
|
+
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.
|
|
23
55
|
|
|
24
56
|
[](https://github.com/marketplace/actions/pytest-html-plus-action)
|
|
25
57
|
[](https://pytest-html-plus.readthedocs.io/en/main/marketplace/usage.html)
|
|
@@ -41,7 +73,7 @@ Export a fully merged JUnit XML report effortlessly — no external tools or plu
|
|
|
41
73
|
|
|
42
74
|

|
|
43
75
|
|
|
44
|
-
#### 🔄 Stop Guessing — See What
|
|
76
|
+
#### 🔄 Stop Guessing — See What's Breaking Your Flaky Tests
|
|
45
77
|
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.
|
|
46
78
|
|
|
47
79
|

|
|
@@ -82,7 +114,7 @@ Just start typing, and the dashboard will instantly filter tests by:
|
|
|
82
114
|
|
|
83
115
|
#### 📧 Email Test Reports: Send your reports via email effortlessly using SendGrid integration.
|
|
84
116
|
|
|
85
|
-

|
|
86
118
|
|
|
87
119
|
#### 🐢 Spot Slow Tests: Highlights the slowest tests so you know where to optimize your suite.
|
|
88
120
|
|
|
@@ -92,7 +124,28 @@ Just start typing, and the dashboard will instantly filter tests by:
|
|
|
92
124
|
|
|
93
125
|

|
|
94
126
|
|
|
95
|
-
###
|
|
127
|
+
### Complete Feature List
|
|
128
|
+
|
|
129
|
+
| Feature | Details |
|
|
130
|
+
|---|---|
|
|
131
|
+
| 📊 **Single-file HTML report** | Fully self-contained — no external CSS, JS, or image folders to archive |
|
|
132
|
+
| 🔄 **Flaky test detection** | Detects tests that fail then pass on retry; shows full retry history |
|
|
133
|
+
| 📸 **Automatic screenshots** | Selenium & Playwright screenshots captured and embedded with no conftest hooks |
|
|
134
|
+
| 🧩 **JUnit XML export** | Merged XML output compatible with TestRail, Xray, and Zephyr (`--generate-xml`) |
|
|
135
|
+
| 🔗 **Traceability links** | Attach Jira, Testmo, Notion, or any URL to a test; rendered and searchable in the report |
|
|
136
|
+
| 🏷️ **Dynamic markers** | Tag tests at runtime with `pytest.mark.*` — no marker pre-registration needed |
|
|
137
|
+
| 🔍 **Universal search** | Filter tests by name, issue ID, or any URL keyword in real time |
|
|
138
|
+
| 🐢 **Slow test highlighting** | Slowest tests in the run automatically flagged |
|
|
139
|
+
| 📋 **Copy-to-clipboard** | Copy test path, logs, trace, and errors in one click |
|
|
140
|
+
| 📦 **Run metadata** | Branch, commit SHA, environment, and custom metadata embedded in the report header |
|
|
141
|
+
| 📝 **Comprehensive log capture** | `print()`, logger output, and stdout/stderr automatically captured per test |
|
|
142
|
+
| ⚡ **xdist support** | Parallel runs with `pytest-xdist` produce a single merged report, no extra steps |
|
|
143
|
+
| 🌐 **Auto-open report** | `--should-open-report` opens the report in your browser after a run (always / failed / never) |
|
|
144
|
+
| 📄 **JSON report** | Raw JSON output (`--json-report`) for custom dashboards or post-processing |
|
|
145
|
+
| 🔎 **Unlinked test detection** | Instantly filter tests that have no associated issue or documentation link |
|
|
146
|
+
| ⚙️ **Reusable config profiles** | Define named profiles in `pyproject.toml` (`--profile=ci`) — no more repeated CLI flags |
|
|
147
|
+
| 📱 **Mobile-friendly layout** | Report renders cleanly on any screen size |
|
|
148
|
+
| 📧 **Email reports** | Send reports via SendGrid integration (`--send-email`) |
|
|
96
149
|
|
|
97
150
|
## Target Audience
|
|
98
151
|
|
|
@@ -104,36 +157,17 @@ This plugin is aimed at those who are:
|
|
|
104
157
|
|
|
105
158
|
- Are frustrated with archiving folders full of assets, CSS, JS, and dashboards just to share test results.
|
|
106
159
|
|
|
107
|
-
- Don
|
|
160
|
+
- Don't want to refactor existing test suites or tag everything with new decorators just to integrate with a reporting tool.
|
|
108
161
|
|
|
109
162
|
- Prefer simplicity — a zero-config, zero code, lightweight report that still looks clean, useful, and polished.
|
|
110
163
|
|
|
111
|
-
- Want
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
## Comparison with Alternatives
|
|
115
|
-
Most existing pytest reporter tools:
|
|
116
|
-
|
|
117
|
-
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.
|
|
118
|
-
|
|
119
|
-
Heavy duty with bloated charts and other test management features(when they arent your only test management system either) increasing your archive size.
|
|
120
|
-
|
|
121
|
-
This plugin aims to fill those gaps by acting as a companion layer on top of the JSON report, focusing on:
|
|
122
|
-
|
|
123
|
-
🔄 Merge + flakiness intelligence
|
|
124
|
-
|
|
125
|
-
🔗 Traceability via metadata
|
|
126
|
-
|
|
127
|
-
🧼 HTML that’s both readable and minimal
|
|
128
|
-
|
|
129
|
-
🧼 Quickly copy test paths and run in your local
|
|
164
|
+
- 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.
|
|
130
165
|
|
|
131
166
|
## Contributing
|
|
132
167
|
|
|
133
168
|
We welcome pull requests, issues, and feature suggestions from the community.
|
|
134
169
|
|
|
135
|
-
See the [contribution guide](
|
|
136
|
-
|
|
170
|
+
See the [contribution guide](CONTRIBUTING.md) for setup instructions.
|
|
137
171
|
|
|
138
172
|
## 📜 License
|
|
139
173
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "pytest-html-plus"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "1.0.1"
|
|
4
4
|
description = "Generate Actionable, automatic screenshots, unified Mobile friendly Pytest HTML report in less than 3 seconds — no hooks, merge plugins, no config, xdist-ready."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
authors = ["reporterplus"]
|
|
@@ -18,7 +18,7 @@ classifiers = [
|
|
|
18
18
|
"Topic :: Software Development :: Testing",
|
|
19
19
|
"Topic :: Software Development :: Quality Assurance",
|
|
20
20
|
"Intended Audience :: Developers",
|
|
21
|
-
"Development Status ::
|
|
21
|
+
"Development Status :: 5 - Production/Stable",
|
|
22
22
|
]
|
|
23
23
|
keywords = [
|
|
24
24
|
"pytest",
|
|
@@ -37,11 +37,13 @@ urls.Homepage = "https://github.com/reporterplus/pytest-html-plus"
|
|
|
37
37
|
urls.Source = "https://github.com/reporterplus/pytest-html-plus"
|
|
38
38
|
urls.Tracker = "https://github.com/reporterplus/pytest-html-plus/issues"
|
|
39
39
|
urls.Documentation = "https://pytest-html-plus.readthedocs.io"
|
|
40
|
+
urls.Changelog = "https://github.com/reporterplus/pytest-html-plus/blob/main/CHANGELOG.md"
|
|
40
41
|
|
|
41
42
|
[tool.poetry.dependencies]
|
|
42
43
|
python = ">=3.10,<4.0"
|
|
43
44
|
yagmail = ">=0.15.293,<0.16.0"
|
|
44
45
|
keyring = ">=25.6.0,<26.0.0"
|
|
46
|
+
tomli = { version = ">=2.0.1,<3.0.0", python = "<3.11" }
|
|
45
47
|
|
|
46
48
|
[tool.poetry.group.dev.dependencies]
|
|
47
49
|
pytest-rerunfailures = "^15.1"
|
|
@@ -64,6 +66,15 @@ build-backend = "poetry.core.masonry.api"
|
|
|
64
66
|
[tool.poetry.plugins."pytest11"]
|
|
65
67
|
pytest_html_plus = "pytest_html_plus.plugin"
|
|
66
68
|
|
|
69
|
+
[tool.pytest-html-plus.profiles.ci]
|
|
70
|
+
generate-xml = true
|
|
71
|
+
xml-report = "final_xml_ci.xml"
|
|
72
|
+
|
|
73
|
+
[tool.pytest-html-plus.profiles.ci-warnings]
|
|
74
|
+
generate-xml = true
|
|
75
|
+
xml-report = "final_xml_ci_warnings.xml"
|
|
76
|
+
html-output = "report_output_warnings"
|
|
77
|
+
|
|
67
78
|
[tool.ruff]
|
|
68
79
|
line-length = 88
|
|
69
80
|
target-version = "py39"
|
|
@@ -84,4 +95,4 @@ select = [
|
|
|
84
95
|
"I", # isort
|
|
85
96
|
"UP", # pyupgrade
|
|
86
97
|
]
|
|
87
|
-
ignore = []
|
|
98
|
+
ignore = []
|
|
@@ -9,6 +9,11 @@ from pathlib import Path
|
|
|
9
9
|
|
|
10
10
|
import pytest
|
|
11
11
|
|
|
12
|
+
try:
|
|
13
|
+
import tomllib
|
|
14
|
+
except ModuleNotFoundError: # pragma: no cover - Python < 3.11
|
|
15
|
+
import tomli as tomllib
|
|
16
|
+
|
|
12
17
|
from pytest_html_plus.compute_report_metadata import write_plus_metadata_if_main_worker
|
|
13
18
|
from pytest_html_plus.extract_link import extract_links_from_item
|
|
14
19
|
from pytest_html_plus.generate_html_report import JSONReporter
|
|
@@ -24,6 +29,21 @@ from pytest_html_plus.utils import (
|
|
|
24
29
|
|
|
25
30
|
python_executable = shutil.which("python3") or shutil.which("python")
|
|
26
31
|
test_screenshot_paths = {}
|
|
32
|
+
PROFILE_OPTION = "--plus-profile"
|
|
33
|
+
PROFILE_SECTION = ("tool", "pytest-html-plus", "profiles")
|
|
34
|
+
PROFILE_OPTION_MAP = {
|
|
35
|
+
"json-report": {"flag": "--json-report", "kind": "value"},
|
|
36
|
+
"capture-screenshots": {"flag": "--capture-screenshots", "kind": "value"},
|
|
37
|
+
"html-output": {"flag": "--html-output", "kind": "value"},
|
|
38
|
+
"screenshots": {"flag": "--screenshots", "kind": "value"},
|
|
39
|
+
"plus-email": {"flag": "--plus-email", "kind": "bool"},
|
|
40
|
+
"should-open-report": {"flag": "--should-open-report", "kind": "value"},
|
|
41
|
+
"generate-xml": {"flag": "--generate-xml", "kind": "bool"},
|
|
42
|
+
"xml-report": {"flag": "--xml-report", "kind": "value"},
|
|
43
|
+
"git-branch": {"flag": "--git-branch", "kind": "value"},
|
|
44
|
+
"git-commit": {"flag": "--git-commit", "kind": "value"},
|
|
45
|
+
"rp-env": {"flag": "--rp-env", "kind": "value"},
|
|
46
|
+
}
|
|
27
47
|
|
|
28
48
|
|
|
29
49
|
logger = logging.getLogger()
|
|
@@ -36,6 +56,136 @@ if not logger.handlers:
|
|
|
36
56
|
logger.addHandler(handler)
|
|
37
57
|
|
|
38
58
|
|
|
59
|
+
def _normalize_profile_key(key):
|
|
60
|
+
return key.replace("_", "-")
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def _find_pyproject_toml(start_path=None):
|
|
64
|
+
current = Path(start_path or Path.cwd()).resolve()
|
|
65
|
+
for candidate in (current, *current.parents):
|
|
66
|
+
pyproject_file = candidate / "pyproject.toml"
|
|
67
|
+
if pyproject_file.exists():
|
|
68
|
+
return pyproject_file
|
|
69
|
+
return None
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def _read_profiles_from_pyproject(start_path=None):
|
|
73
|
+
pyproject_file = _find_pyproject_toml(start_path=start_path)
|
|
74
|
+
if pyproject_file is None:
|
|
75
|
+
raise pytest.UsageError(
|
|
76
|
+
f"{PROFILE_OPTION} requires a pyproject.toml file in the current "
|
|
77
|
+
"directory or a parent directory"
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
try:
|
|
81
|
+
with pyproject_file.open("rb") as fh:
|
|
82
|
+
pyproject_data = tomllib.load(fh)
|
|
83
|
+
except tomllib.TOMLDecodeError as exc:
|
|
84
|
+
raise pytest.UsageError(f"Invalid TOML in {pyproject_file}: {exc}") from exc
|
|
85
|
+
|
|
86
|
+
profiles = pyproject_data
|
|
87
|
+
for section in PROFILE_SECTION:
|
|
88
|
+
profiles = profiles.get(section, {})
|
|
89
|
+
|
|
90
|
+
if not isinstance(profiles, dict):
|
|
91
|
+
raise pytest.UsageError(
|
|
92
|
+
f"Expected [{'.'.join(PROFILE_SECTION)}] to be a TOML table"
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
return profiles
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def _build_profile_args(profile_name, start_path=None):
|
|
99
|
+
profiles = _read_profiles_from_pyproject(start_path=start_path)
|
|
100
|
+
profile = profiles.get(profile_name)
|
|
101
|
+
|
|
102
|
+
if profile is None:
|
|
103
|
+
available_profiles = ", ".join(sorted(profiles)) or "none"
|
|
104
|
+
raise pytest.UsageError(
|
|
105
|
+
f"Unknown profile '{profile_name}' for {PROFILE_OPTION}. "
|
|
106
|
+
f"Available profiles: {available_profiles}"
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
if not isinstance(profile, dict):
|
|
110
|
+
raise pytest.UsageError(
|
|
111
|
+
f"Profile '{profile_name}' must be defined as a TOML table"
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
profile_args = []
|
|
115
|
+
invalid_keys = []
|
|
116
|
+
|
|
117
|
+
for raw_key, value in profile.items():
|
|
118
|
+
key = _normalize_profile_key(raw_key)
|
|
119
|
+
option = PROFILE_OPTION_MAP.get(key)
|
|
120
|
+
|
|
121
|
+
if option is None:
|
|
122
|
+
invalid_keys.append(raw_key)
|
|
123
|
+
continue
|
|
124
|
+
|
|
125
|
+
if option["kind"] == "bool":
|
|
126
|
+
if not isinstance(value, bool):
|
|
127
|
+
raise pytest.UsageError(
|
|
128
|
+
f"Profile '{profile_name}' option '{raw_key}' must be true or false"
|
|
129
|
+
)
|
|
130
|
+
if value:
|
|
131
|
+
profile_args.append(option["flag"])
|
|
132
|
+
continue
|
|
133
|
+
|
|
134
|
+
if not isinstance(value, (str, int, float)):
|
|
135
|
+
raise pytest.UsageError(
|
|
136
|
+
f"Profile '{profile_name}' option '{raw_key}' "
|
|
137
|
+
"must be a string-like value"
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
profile_args.append(f"{option['flag']}={value}")
|
|
141
|
+
|
|
142
|
+
if invalid_keys:
|
|
143
|
+
valid_keys = ", ".join(sorted(PROFILE_OPTION_MAP))
|
|
144
|
+
invalid = ", ".join(sorted(invalid_keys))
|
|
145
|
+
raise pytest.UsageError(
|
|
146
|
+
f"Invalid key(s) in profile '{profile_name}': {invalid}. "
|
|
147
|
+
f"Valid keys: {valid_keys}"
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
return profile_args
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
def apply_plus_profile_args(args, start_path=None):
|
|
154
|
+
profile_name = None
|
|
155
|
+
remaining_args = []
|
|
156
|
+
skip_next = False
|
|
157
|
+
|
|
158
|
+
for index, arg in enumerate(args):
|
|
159
|
+
if skip_next:
|
|
160
|
+
skip_next = False
|
|
161
|
+
continue
|
|
162
|
+
|
|
163
|
+
if arg == PROFILE_OPTION:
|
|
164
|
+
if profile_name is not None:
|
|
165
|
+
raise pytest.UsageError(f"{PROFILE_OPTION} can only be specified once")
|
|
166
|
+
if index + 1 >= len(args):
|
|
167
|
+
raise pytest.UsageError(f"{PROFILE_OPTION} requires a profile name")
|
|
168
|
+
profile_name = args[index + 1]
|
|
169
|
+
skip_next = True
|
|
170
|
+
continue
|
|
171
|
+
|
|
172
|
+
if arg.startswith(f"{PROFILE_OPTION}="):
|
|
173
|
+
if profile_name is not None:
|
|
174
|
+
raise pytest.UsageError(f"{PROFILE_OPTION} can only be specified once")
|
|
175
|
+
profile_name = arg.split("=", 1)[1]
|
|
176
|
+
if not profile_name:
|
|
177
|
+
raise pytest.UsageError(f"{PROFILE_OPTION} requires a profile name")
|
|
178
|
+
continue
|
|
179
|
+
|
|
180
|
+
remaining_args.append(arg)
|
|
181
|
+
|
|
182
|
+
if not profile_name:
|
|
183
|
+
return list(args)
|
|
184
|
+
|
|
185
|
+
profile_args = _build_profile_args(profile_name, start_path=start_path)
|
|
186
|
+
return profile_args + remaining_args
|
|
187
|
+
|
|
188
|
+
|
|
39
189
|
@pytest.hookimpl(tryfirst=True)
|
|
40
190
|
def pytest_runtest_setup(item):
|
|
41
191
|
if "caplog" not in item.fixturenames:
|
|
@@ -263,6 +413,7 @@ def pytest_sessionstart(session):
|
|
|
263
413
|
|
|
264
414
|
|
|
265
415
|
def pytest_load_initial_conftests(args):
|
|
416
|
+
args[:] = apply_plus_profile_args(args, start_path=Path.cwd())
|
|
266
417
|
if not any(arg.startswith("--capture") for arg in args):
|
|
267
418
|
args.append("--capture=tee-sys")
|
|
268
419
|
|
|
@@ -270,6 +421,12 @@ def pytest_load_initial_conftests(args):
|
|
|
270
421
|
def pytest_addoption(parser):
|
|
271
422
|
group = parser.getgroup("pytest-html-plus", "pytest-html-plus reporting options")
|
|
272
423
|
|
|
424
|
+
group.addoption(
|
|
425
|
+
PROFILE_OPTION,
|
|
426
|
+
action="store",
|
|
427
|
+
default=None,
|
|
428
|
+
help="Load pytest-html-plus options from a named profile in pyproject.toml",
|
|
429
|
+
)
|
|
273
430
|
group.addoption(
|
|
274
431
|
"--json-report",
|
|
275
432
|
action="store",
|
|
@@ -291,12 +448,6 @@ def pytest_addoption(parser):
|
|
|
291
448
|
default=False,
|
|
292
449
|
help="Send HTML test report via email after test run",
|
|
293
450
|
)
|
|
294
|
-
group.addoption(
|
|
295
|
-
"--detect-flake",
|
|
296
|
-
action="store",
|
|
297
|
-
default=False,
|
|
298
|
-
help="Helps capture flaky tests in the last n number of builds",
|
|
299
|
-
)
|
|
300
451
|
group.addoption(
|
|
301
452
|
"--should-open-report",
|
|
302
453
|
action="store",
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pytest_html_plus-0.5.2 → pytest_html_plus-1.0.1}/pytest_html_plus/compute_report_metadata.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|