pytest-pulse-report 1.0.0__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_pulse_report-1.0.0/LICENSE +21 -0
- pytest_pulse_report-1.0.0/PKG-INFO +267 -0
- pytest_pulse_report-1.0.0/README.md +241 -0
- pytest_pulse_report-1.0.0/pyproject.toml +66 -0
- pytest_pulse_report-1.0.0/setup.cfg +4 -0
- pytest_pulse_report-1.0.0/src/pytest_pulse/__init__.py +15 -0
- pytest_pulse_report-1.0.0/src/pytest_pulse/attachment_utils.py +142 -0
- pytest_pulse_report-1.0.0/src/pytest_pulse/cli.py +241 -0
- pytest_pulse_report-1.0.0/src/pytest_pulse/decorators.py +49 -0
- pytest_pulse_report-1.0.0/src/pytest_pulse/dynamic_generator.py +4442 -0
- pytest_pulse_report-1.0.0/src/pytest_pulse/email_generator.py +741 -0
- pytest_pulse_report-1.0.0/src/pytest_pulse/email_sender.py +132 -0
- pytest_pulse_report-1.0.0/src/pytest_pulse/env_utils.py +43 -0
- pytest_pulse_report-1.0.0/src/pytest_pulse/highcharts.min.js +29 -0
- pytest_pulse_report-1.0.0/src/pytest_pulse/merge_reports.py +292 -0
- pytest_pulse_report-1.0.0/src/pytest_pulse/plugin.py +1196 -0
- pytest_pulse_report-1.0.0/src/pytest_pulse/report_writer.py +155 -0
- pytest_pulse_report-1.0.0/src/pytest_pulse/static_generator.py +5063 -0
- pytest_pulse_report-1.0.0/src/pytest_pulse/types.py +159 -0
- pytest_pulse_report-1.0.0/src/pytest_pulse_report.egg-info/PKG-INFO +267 -0
- pytest_pulse_report-1.0.0/src/pytest_pulse_report.egg-info/SOURCES.txt +23 -0
- pytest_pulse_report-1.0.0/src/pytest_pulse_report.egg-info/dependency_links.txt +1 -0
- pytest_pulse_report-1.0.0/src/pytest_pulse_report.egg-info/entry_points.txt +10 -0
- pytest_pulse_report-1.0.0/src/pytest_pulse_report.egg-info/requires.txt +11 -0
- pytest_pulse_report-1.0.0/src/pytest_pulse_report.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Arghajit Singha
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pytest-pulse-report
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: A pytest reporter and dashboard for visualizing Playwright (pytest-playwright) test results — Python port of playwright-pulse
|
|
5
|
+
Author: Arghajit Singha
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://arghajit47.github.io/playwright-pulse/
|
|
8
|
+
Project-URL: Repository, https://github.com/Arghajit47/playwright-pulse
|
|
9
|
+
Keywords: pytest,playwright,pytest-playwright,reporter,dashboard,test,reporting,pulse,pulse-report,test-report,html-report
|
|
10
|
+
Classifier: Framework :: Pytest
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Operating System :: OS Independent
|
|
13
|
+
Classifier: Topic :: Software Development :: Testing
|
|
14
|
+
Requires-Python: >=3.8
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
License-File: LICENSE
|
|
17
|
+
Requires-Dist: pytest>=7.0.0
|
|
18
|
+
Requires-Dist: psutil>=5.0.0
|
|
19
|
+
Provides-Extra: email
|
|
20
|
+
Requires-Dist: secure-smtplib; extra == "email"
|
|
21
|
+
Provides-Extra: compression
|
|
22
|
+
Requires-Dist: Pillow>=9.0.0; extra == "compression"
|
|
23
|
+
Provides-Extra: all
|
|
24
|
+
Requires-Dist: Pillow>=9.0.0; extra == "all"
|
|
25
|
+
Dynamic: license-file
|
|
26
|
+
|
|
27
|
+
# pytest-pulse-report
|
|
28
|
+
|
|
29
|
+
> **Python port of [playwright-pulse](https://github.com/Arghajit47/playwright-pulse)** — the same rich interactive dashboard, now for **pytest-playwright** (and plain pytest).
|
|
30
|
+
|
|
31
|
+
[](https://pypi.org/project/pytest-pulse-report/)
|
|
32
|
+
[](https://opensource.org/licenses/MIT)
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## Features
|
|
37
|
+
|
|
38
|
+
| Feature | Description |
|
|
39
|
+
| :--- | :--- |
|
|
40
|
+
| **Same JSON format** | 100 % compatible with the JS reporter's output format |
|
|
41
|
+
| **Interactive HTML report** | Dark-themed dashboard with Highcharts charts |
|
|
42
|
+
| **Self-contained static report** | All assets embedded — share a single `.html` file |
|
|
43
|
+
| **Email summary** | Lightweight HTML email + optional full-report attachment |
|
|
44
|
+
| **Step recording** | `@step` decorator and `pulse_step` context manager |
|
|
45
|
+
| **Severity & tags** | `@pytest.mark.pulse_severity` / `@pytest.mark.pulse_tag` |
|
|
46
|
+
| **Artifact collection** | Auto-discovers screenshots / videos / traces from pytest-playwright |
|
|
47
|
+
| **pytest-xdist** | Each worker writes a shard; master merges them |
|
|
48
|
+
| **Sequential runs** | Accumulate reports across runs with `--pulse-no-reset` |
|
|
49
|
+
| **AI Failure Analyzer** | Client-side Claude / OpenAI analysis in the report |
|
|
50
|
+
| **Trend history** | Archive runs for historical charts |
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Installation
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
pip install pytest-pulse-report
|
|
58
|
+
# Optional: image compression
|
|
59
|
+
pip install pytest-pulse-report[compression]
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
The plugin is auto-registered via the `pytest11` entry point — no `conftest.py` changes needed.
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## Quick start
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
# Run your tests
|
|
70
|
+
pytest tests/ --pulse-output-dir=pulse-report
|
|
71
|
+
|
|
72
|
+
# Generate the interactive HTML report
|
|
73
|
+
generate-pulse-report
|
|
74
|
+
|
|
75
|
+
# Open pulse-report/playwright-pulse-static-report.html
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## Configuration
|
|
81
|
+
|
|
82
|
+
### Command-line options
|
|
83
|
+
|
|
84
|
+
| Option | Default | Description |
|
|
85
|
+
| :--- | :--- | :--- |
|
|
86
|
+
| `--pulse-output-dir` | `pulse-report` | Output directory |
|
|
87
|
+
| `--pulse-output-file` | `playwright-pulse-report.json` | JSON filename |
|
|
88
|
+
| `--pulse-no-reset` | — | Accumulate reports across runs |
|
|
89
|
+
| `--pulse-individual-subdir` | `pulse-results` | Sub-dir for individual run JSONs |
|
|
90
|
+
| `--pulse-description` | — | Custom text in report header |
|
|
91
|
+
| `--pulse-logo` | — | Path to a custom logo image |
|
|
92
|
+
|
|
93
|
+
### pytest.ini / pyproject.toml
|
|
94
|
+
|
|
95
|
+
```ini
|
|
96
|
+
[pytest]
|
|
97
|
+
addopts = --pulse-output-dir=pulse-report --pulse-description="My CI Suite"
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## Step Recording
|
|
103
|
+
|
|
104
|
+
### ⚡ Super Easy Mode: The `@step` Decorator
|
|
105
|
+
|
|
106
|
+
The most efficient way to record steps, especially within Page Object Models (POM). No fixtures needed.
|
|
107
|
+
|
|
108
|
+
```python
|
|
109
|
+
from pytest_pulse import step
|
|
110
|
+
|
|
111
|
+
class LoginPage:
|
|
112
|
+
def __init__(self, page):
|
|
113
|
+
self.page = page
|
|
114
|
+
|
|
115
|
+
@step("Login to Application")
|
|
116
|
+
def login(self, username, password):
|
|
117
|
+
self.enter_credentials(username, password)
|
|
118
|
+
self.submit_form()
|
|
119
|
+
|
|
120
|
+
@step("Enter Credentials")
|
|
121
|
+
def enter_credentials(self, username, password):
|
|
122
|
+
self.page.fill("#user", username)
|
|
123
|
+
self.page.fill("#pass", password)
|
|
124
|
+
|
|
125
|
+
@step("Submit Login Form")
|
|
126
|
+
def submit_form(self):
|
|
127
|
+
self.page.click("#login-button")
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### The `pulse_step` Context Manager
|
|
131
|
+
|
|
132
|
+
Ideal for wrapping specific blocks of code directly inside your test functions.
|
|
133
|
+
|
|
134
|
+
```python
|
|
135
|
+
from pytest_pulse import pulse_step
|
|
136
|
+
|
|
137
|
+
def test_example(page):
|
|
138
|
+
with pulse_step("Navigate to Home Page"):
|
|
139
|
+
page.goto("https://example.com")
|
|
140
|
+
|
|
141
|
+
with pulse_step("Perform Search"):
|
|
142
|
+
page.fill("#search", "Playwright Pulse")
|
|
143
|
+
page.press("#search", "Enter")
|
|
144
|
+
|
|
145
|
+
with pulse_step("Verify Results"):
|
|
146
|
+
assert page.is_visible(".results-count")
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Attaching Files with `pulse_attach`
|
|
150
|
+
|
|
151
|
+
You can manually attach any file (logs, CSVs, custom screenshots) to the test result using the `pulse_attach` fixture.
|
|
152
|
+
|
|
153
|
+
```python
|
|
154
|
+
def test_export(page, pulse_attach):
|
|
155
|
+
page.click("#export-csv")
|
|
156
|
+
pulse_attach("/tmp/export.csv")
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
## Markers
|
|
162
|
+
|
|
163
|
+
```python
|
|
164
|
+
import pytest
|
|
165
|
+
|
|
166
|
+
@pytest.mark.pulse_severity("Critical") # Minor / Low / Medium / High / Critical
|
|
167
|
+
@pytest.mark.pulse_tag("smoke")
|
|
168
|
+
@pytest.mark.pulse_tag("regression")
|
|
169
|
+
@pytest.mark.pulse_annotation("jira", "PROJ-123")
|
|
170
|
+
def test_checkout(page, pulse_step):
|
|
171
|
+
with pulse_step("Go to checkout"):
|
|
172
|
+
page.goto("/checkout")
|
|
173
|
+
with pulse_step("Fill in payment"):
|
|
174
|
+
page.fill("#card", "4242424242424242")
|
|
175
|
+
with pulse_step("Submit order"):
|
|
176
|
+
page.click("#pay")
|
|
177
|
+
page.wait_for_url("**/confirmation")
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
## CLI commands
|
|
183
|
+
|
|
184
|
+
| Command | Description |
|
|
185
|
+
| :--- | :--- |
|
|
186
|
+
| `generate-pulse-report` | Self-contained static HTML (all assets embedded) |
|
|
187
|
+
| `generate-report` | Dynamic HTML (references `attachments/` dir) |
|
|
188
|
+
| `merge-pulse-report` | Merge sharded or sequential reports |
|
|
189
|
+
| `send-email` | Send report via SMTP |
|
|
190
|
+
| `generate-email-report` | Lightweight email summary HTML |
|
|
191
|
+
| `generate-trend` | Archive current run for trend history |
|
|
192
|
+
|
|
193
|
+
All commands accept `--outputDir / -o` flag.
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
## Email sending
|
|
198
|
+
|
|
199
|
+
Set environment variables (supports `.env` files via `python-dotenv`):
|
|
200
|
+
|
|
201
|
+
```bash
|
|
202
|
+
PULSE_MAIL_HOST=gmail # gmail | outlook | smtp
|
|
203
|
+
PULSE_MAIL_USERNAME=you@gmail.com
|
|
204
|
+
PULSE_MAIL_PASSWORD=app_password
|
|
205
|
+
RECIPIENT_EMAIL_1=team@example.com
|
|
206
|
+
RECIPIENT_EMAIL_2=boss@example.com
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
```bash
|
|
210
|
+
send-email --attach-html
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
---
|
|
214
|
+
|
|
215
|
+
## pytest-playwright integration
|
|
216
|
+
|
|
217
|
+
When **pytest-playwright** is installed, the plugin automatically:
|
|
218
|
+
|
|
219
|
+
1. Detects the browser name from the `browser_name` fixture / callspec params
|
|
220
|
+
2. Scans pytest-playwright's `--output` directory (default: `test-results`) for screenshots, videos and traces after each test
|
|
221
|
+
3. Copies and optionally compresses those artefacts into `pulse-report/attachments/`
|
|
222
|
+
|
|
223
|
+
```bash
|
|
224
|
+
pytest tests/ --browser chromium --video on --screenshot on \
|
|
225
|
+
--pulse-output-dir=pulse-report
|
|
226
|
+
generate-pulse-report
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
---
|
|
230
|
+
|
|
231
|
+
## pytest-xdist (parallel runs)
|
|
232
|
+
|
|
233
|
+
```bash
|
|
234
|
+
pytest tests/ -n 4 --pulse-output-dir=pulse-report
|
|
235
|
+
generate-pulse-report
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
Each worker writes a temporary shard file. The master process merges all shards at session end.
|
|
239
|
+
|
|
240
|
+
---
|
|
241
|
+
|
|
242
|
+
## Sequential runs (`--pulse-no-reset`)
|
|
243
|
+
|
|
244
|
+
```bash
|
|
245
|
+
pytest tests/smoke/ --pulse-no-reset
|
|
246
|
+
pytest tests/regression/ --pulse-no-reset
|
|
247
|
+
merge-pulse-report # combines both into one report
|
|
248
|
+
generate-pulse-report
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
---
|
|
252
|
+
|
|
253
|
+
## JSON report format
|
|
254
|
+
|
|
255
|
+
The output JSON is **identical** to the JS playwright-pulse format, so existing tooling (CI dashboards, the JS `generate-pulse-report` script, etc.) works without changes.
|
|
256
|
+
|
|
257
|
+
---
|
|
258
|
+
|
|
259
|
+
## Github repository
|
|
260
|
+
|
|
261
|
+
Learning from the documentation or, the readme file sometimes is a big ask. So I have created this repository to serve as a quick reference for the users. Here is the link to the Github repository:
|
|
262
|
+
|
|
263
|
+
[pytest-playwright](https://github.com/Arghajit47/pytest-playwright)
|
|
264
|
+
|
|
265
|
+
## Author
|
|
266
|
+
|
|
267
|
+
**Arghajit Singha** — [playwright-pulse](https://github.com/Arghajit47/playwright-pulse)
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
# pytest-pulse-report
|
|
2
|
+
|
|
3
|
+
> **Python port of [playwright-pulse](https://github.com/Arghajit47/playwright-pulse)** — the same rich interactive dashboard, now for **pytest-playwright** (and plain pytest).
|
|
4
|
+
|
|
5
|
+
[](https://pypi.org/project/pytest-pulse-report/)
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Features
|
|
11
|
+
|
|
12
|
+
| Feature | Description |
|
|
13
|
+
| :--- | :--- |
|
|
14
|
+
| **Same JSON format** | 100 % compatible with the JS reporter's output format |
|
|
15
|
+
| **Interactive HTML report** | Dark-themed dashboard with Highcharts charts |
|
|
16
|
+
| **Self-contained static report** | All assets embedded — share a single `.html` file |
|
|
17
|
+
| **Email summary** | Lightweight HTML email + optional full-report attachment |
|
|
18
|
+
| **Step recording** | `@step` decorator and `pulse_step` context manager |
|
|
19
|
+
| **Severity & tags** | `@pytest.mark.pulse_severity` / `@pytest.mark.pulse_tag` |
|
|
20
|
+
| **Artifact collection** | Auto-discovers screenshots / videos / traces from pytest-playwright |
|
|
21
|
+
| **pytest-xdist** | Each worker writes a shard; master merges them |
|
|
22
|
+
| **Sequential runs** | Accumulate reports across runs with `--pulse-no-reset` |
|
|
23
|
+
| **AI Failure Analyzer** | Client-side Claude / OpenAI analysis in the report |
|
|
24
|
+
| **Trend history** | Archive runs for historical charts |
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## Installation
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
pip install pytest-pulse-report
|
|
32
|
+
# Optional: image compression
|
|
33
|
+
pip install pytest-pulse-report[compression]
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
The plugin is auto-registered via the `pytest11` entry point — no `conftest.py` changes needed.
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Quick start
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
# Run your tests
|
|
44
|
+
pytest tests/ --pulse-output-dir=pulse-report
|
|
45
|
+
|
|
46
|
+
# Generate the interactive HTML report
|
|
47
|
+
generate-pulse-report
|
|
48
|
+
|
|
49
|
+
# Open pulse-report/playwright-pulse-static-report.html
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Configuration
|
|
55
|
+
|
|
56
|
+
### Command-line options
|
|
57
|
+
|
|
58
|
+
| Option | Default | Description |
|
|
59
|
+
| :--- | :--- | :--- |
|
|
60
|
+
| `--pulse-output-dir` | `pulse-report` | Output directory |
|
|
61
|
+
| `--pulse-output-file` | `playwright-pulse-report.json` | JSON filename |
|
|
62
|
+
| `--pulse-no-reset` | — | Accumulate reports across runs |
|
|
63
|
+
| `--pulse-individual-subdir` | `pulse-results` | Sub-dir for individual run JSONs |
|
|
64
|
+
| `--pulse-description` | — | Custom text in report header |
|
|
65
|
+
| `--pulse-logo` | — | Path to a custom logo image |
|
|
66
|
+
|
|
67
|
+
### pytest.ini / pyproject.toml
|
|
68
|
+
|
|
69
|
+
```ini
|
|
70
|
+
[pytest]
|
|
71
|
+
addopts = --pulse-output-dir=pulse-report --pulse-description="My CI Suite"
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## Step Recording
|
|
77
|
+
|
|
78
|
+
### ⚡ Super Easy Mode: The `@step` Decorator
|
|
79
|
+
|
|
80
|
+
The most efficient way to record steps, especially within Page Object Models (POM). No fixtures needed.
|
|
81
|
+
|
|
82
|
+
```python
|
|
83
|
+
from pytest_pulse import step
|
|
84
|
+
|
|
85
|
+
class LoginPage:
|
|
86
|
+
def __init__(self, page):
|
|
87
|
+
self.page = page
|
|
88
|
+
|
|
89
|
+
@step("Login to Application")
|
|
90
|
+
def login(self, username, password):
|
|
91
|
+
self.enter_credentials(username, password)
|
|
92
|
+
self.submit_form()
|
|
93
|
+
|
|
94
|
+
@step("Enter Credentials")
|
|
95
|
+
def enter_credentials(self, username, password):
|
|
96
|
+
self.page.fill("#user", username)
|
|
97
|
+
self.page.fill("#pass", password)
|
|
98
|
+
|
|
99
|
+
@step("Submit Login Form")
|
|
100
|
+
def submit_form(self):
|
|
101
|
+
self.page.click("#login-button")
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### The `pulse_step` Context Manager
|
|
105
|
+
|
|
106
|
+
Ideal for wrapping specific blocks of code directly inside your test functions.
|
|
107
|
+
|
|
108
|
+
```python
|
|
109
|
+
from pytest_pulse import pulse_step
|
|
110
|
+
|
|
111
|
+
def test_example(page):
|
|
112
|
+
with pulse_step("Navigate to Home Page"):
|
|
113
|
+
page.goto("https://example.com")
|
|
114
|
+
|
|
115
|
+
with pulse_step("Perform Search"):
|
|
116
|
+
page.fill("#search", "Playwright Pulse")
|
|
117
|
+
page.press("#search", "Enter")
|
|
118
|
+
|
|
119
|
+
with pulse_step("Verify Results"):
|
|
120
|
+
assert page.is_visible(".results-count")
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Attaching Files with `pulse_attach`
|
|
124
|
+
|
|
125
|
+
You can manually attach any file (logs, CSVs, custom screenshots) to the test result using the `pulse_attach` fixture.
|
|
126
|
+
|
|
127
|
+
```python
|
|
128
|
+
def test_export(page, pulse_attach):
|
|
129
|
+
page.click("#export-csv")
|
|
130
|
+
pulse_attach("/tmp/export.csv")
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## Markers
|
|
136
|
+
|
|
137
|
+
```python
|
|
138
|
+
import pytest
|
|
139
|
+
|
|
140
|
+
@pytest.mark.pulse_severity("Critical") # Minor / Low / Medium / High / Critical
|
|
141
|
+
@pytest.mark.pulse_tag("smoke")
|
|
142
|
+
@pytest.mark.pulse_tag("regression")
|
|
143
|
+
@pytest.mark.pulse_annotation("jira", "PROJ-123")
|
|
144
|
+
def test_checkout(page, pulse_step):
|
|
145
|
+
with pulse_step("Go to checkout"):
|
|
146
|
+
page.goto("/checkout")
|
|
147
|
+
with pulse_step("Fill in payment"):
|
|
148
|
+
page.fill("#card", "4242424242424242")
|
|
149
|
+
with pulse_step("Submit order"):
|
|
150
|
+
page.click("#pay")
|
|
151
|
+
page.wait_for_url("**/confirmation")
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
## CLI commands
|
|
157
|
+
|
|
158
|
+
| Command | Description |
|
|
159
|
+
| :--- | :--- |
|
|
160
|
+
| `generate-pulse-report` | Self-contained static HTML (all assets embedded) |
|
|
161
|
+
| `generate-report` | Dynamic HTML (references `attachments/` dir) |
|
|
162
|
+
| `merge-pulse-report` | Merge sharded or sequential reports |
|
|
163
|
+
| `send-email` | Send report via SMTP |
|
|
164
|
+
| `generate-email-report` | Lightweight email summary HTML |
|
|
165
|
+
| `generate-trend` | Archive current run for trend history |
|
|
166
|
+
|
|
167
|
+
All commands accept `--outputDir / -o` flag.
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
## Email sending
|
|
172
|
+
|
|
173
|
+
Set environment variables (supports `.env` files via `python-dotenv`):
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
PULSE_MAIL_HOST=gmail # gmail | outlook | smtp
|
|
177
|
+
PULSE_MAIL_USERNAME=you@gmail.com
|
|
178
|
+
PULSE_MAIL_PASSWORD=app_password
|
|
179
|
+
RECIPIENT_EMAIL_1=team@example.com
|
|
180
|
+
RECIPIENT_EMAIL_2=boss@example.com
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
```bash
|
|
184
|
+
send-email --attach-html
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## pytest-playwright integration
|
|
190
|
+
|
|
191
|
+
When **pytest-playwright** is installed, the plugin automatically:
|
|
192
|
+
|
|
193
|
+
1. Detects the browser name from the `browser_name` fixture / callspec params
|
|
194
|
+
2. Scans pytest-playwright's `--output` directory (default: `test-results`) for screenshots, videos and traces after each test
|
|
195
|
+
3. Copies and optionally compresses those artefacts into `pulse-report/attachments/`
|
|
196
|
+
|
|
197
|
+
```bash
|
|
198
|
+
pytest tests/ --browser chromium --video on --screenshot on \
|
|
199
|
+
--pulse-output-dir=pulse-report
|
|
200
|
+
generate-pulse-report
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
---
|
|
204
|
+
|
|
205
|
+
## pytest-xdist (parallel runs)
|
|
206
|
+
|
|
207
|
+
```bash
|
|
208
|
+
pytest tests/ -n 4 --pulse-output-dir=pulse-report
|
|
209
|
+
generate-pulse-report
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
Each worker writes a temporary shard file. The master process merges all shards at session end.
|
|
213
|
+
|
|
214
|
+
---
|
|
215
|
+
|
|
216
|
+
## Sequential runs (`--pulse-no-reset`)
|
|
217
|
+
|
|
218
|
+
```bash
|
|
219
|
+
pytest tests/smoke/ --pulse-no-reset
|
|
220
|
+
pytest tests/regression/ --pulse-no-reset
|
|
221
|
+
merge-pulse-report # combines both into one report
|
|
222
|
+
generate-pulse-report
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
---
|
|
226
|
+
|
|
227
|
+
## JSON report format
|
|
228
|
+
|
|
229
|
+
The output JSON is **identical** to the JS playwright-pulse format, so existing tooling (CI dashboards, the JS `generate-pulse-report` script, etc.) works without changes.
|
|
230
|
+
|
|
231
|
+
---
|
|
232
|
+
|
|
233
|
+
## Github repository
|
|
234
|
+
|
|
235
|
+
Learning from the documentation or, the readme file sometimes is a big ask. So I have created this repository to serve as a quick reference for the users. Here is the link to the Github repository:
|
|
236
|
+
|
|
237
|
+
[pytest-playwright](https://github.com/Arghajit47/pytest-playwright)
|
|
238
|
+
|
|
239
|
+
## Author
|
|
240
|
+
|
|
241
|
+
**Arghajit Singha** — [playwright-pulse](https://github.com/Arghajit47/playwright-pulse)
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "pytest-pulse-report"
|
|
7
|
+
version = "1.0.0"
|
|
8
|
+
description = "A pytest reporter and dashboard for visualizing Playwright (pytest-playwright) test results — Python port of playwright-pulse"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.8"
|
|
11
|
+
license = "MIT"
|
|
12
|
+
authors = [{ name = "Arghajit Singha" }]
|
|
13
|
+
keywords = [
|
|
14
|
+
"pytest",
|
|
15
|
+
"playwright",
|
|
16
|
+
"pytest-playwright",
|
|
17
|
+
"reporter",
|
|
18
|
+
"dashboard",
|
|
19
|
+
"test",
|
|
20
|
+
"reporting",
|
|
21
|
+
"pulse",
|
|
22
|
+
"pulse-report",
|
|
23
|
+
"test-report",
|
|
24
|
+
"html-report",
|
|
25
|
+
]
|
|
26
|
+
classifiers = [
|
|
27
|
+
"Framework :: Pytest",
|
|
28
|
+
"Programming Language :: Python :: 3",
|
|
29
|
+
"Operating System :: OS Independent",
|
|
30
|
+
"Topic :: Software Development :: Testing",
|
|
31
|
+
]
|
|
32
|
+
dependencies = [
|
|
33
|
+
"pytest>=7.0.0",
|
|
34
|
+
"psutil>=5.0.0",
|
|
35
|
+
]
|
|
36
|
+
|
|
37
|
+
[project.optional-dependencies]
|
|
38
|
+
email = ["secure-smtplib"]
|
|
39
|
+
compression = ["Pillow>=9.0.0"]
|
|
40
|
+
all = ["Pillow>=9.0.0"]
|
|
41
|
+
|
|
42
|
+
[project.urls]
|
|
43
|
+
Homepage = "https://arghajit47.github.io/playwright-pulse/"
|
|
44
|
+
Repository = "https://github.com/Arghajit47/playwright-pulse"
|
|
45
|
+
|
|
46
|
+
[project.entry-points."pytest11"]
|
|
47
|
+
pulse-report = "pytest_pulse.plugin"
|
|
48
|
+
|
|
49
|
+
[project.scripts]
|
|
50
|
+
generate-pulse-report = "pytest_pulse.cli:generate_static_report"
|
|
51
|
+
generate-report = "pytest_pulse.cli:generate_report"
|
|
52
|
+
merge-pulse-report = "pytest_pulse.cli:merge_reports_cli"
|
|
53
|
+
send-email = "pytest_pulse.cli:send_email_cli"
|
|
54
|
+
generate-email-report = "pytest_pulse.cli:generate_email_report_cli"
|
|
55
|
+
generate-trend = "pytest_pulse.cli:generate_trend_cli"
|
|
56
|
+
|
|
57
|
+
[tool.setuptools.packages.find]
|
|
58
|
+
where = ["src"]
|
|
59
|
+
include = ["pytest_pulse*"]
|
|
60
|
+
|
|
61
|
+
[tool.setuptools]
|
|
62
|
+
include-package-data = true
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
[tool.setuptools.package-data]
|
|
66
|
+
pytest_pulse = ["*.js"]
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"""pytest-pulse-report — Python pytest plugin for Playwright test reporting.
|
|
2
|
+
|
|
3
|
+
The plugin is auto-discovered by pytest via the ``pytest11`` entry point.
|
|
4
|
+
You can also import the public API directly:
|
|
5
|
+
|
|
6
|
+
from pytest_pulse.static_generator import generate_static_html
|
|
7
|
+
from pytest_pulse.merge_reports import merge_shard_directories
|
|
8
|
+
from pytest_pulse.email_sender import send_report
|
|
9
|
+
from pytest_pulse.decorators import step
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from .decorators import step, pulse_step
|
|
13
|
+
|
|
14
|
+
__version__ = "1.0.0"
|
|
15
|
+
__author__ = "Arghajit Singha"
|