Skip to content

Commit 99efc06

Browse files
cav71gaborbernat
andauthored
added printer_factory and pprint fixtures (#155)
* added printer_factory and pprint fixtures, and tests * tox fixes * hide _create_printer and rename printer_factory -> pprinter_factory * restore create_printer * consolidate into RecordFormatter more record formatting * remove unsupported __slots__ in dataclasses for py3.8/py3.9 * PR feedback Signed-off-by: Bernát Gábor <bgabor8@bloomberg.net> --------- Signed-off-by: Bernát Gábor <bgabor8@bloomberg.net> Co-authored-by: Bernát Gábor <bgabor8@bloomberg.net>
1 parent 4000034 commit 99efc06

10 files changed

+628
-109
lines changed

README.md

Lines changed: 168 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -8,52 +8,194 @@
88
[![check](https://github.com/pytest-dev/pytest-print/actions/workflows/check.yaml/badge.svg)](https://github.com/pytest-dev/pytest-print/actions/workflows/check.yaml)
99

1010
Allows to print extra content onto the PyTest reporting. This can be used for example to report sub-steps for long
11-
running tests, or to print debug information in your tests when you cannot debug the code.
11+
running tests, or to print debug information in your tests when you cannot debug the code (so that the end user does not
12+
need to wonder if the test froze/dead locked or not).
1213

13-
## install
14+
<!--ts-->
15+
16+
- [Install](#install)
17+
- [CLI flags](#cli-flags)
18+
- [API](#api)
19+
- [Example: printer_session](#example-printer_session)
20+
- [Example: pretty_printer](#example-pretty_printer)
21+
- [Example: create_pretty_printer](#example-create_pretty_printer)
22+
23+
<!--te-->
24+
25+
## Install
1426

1527
```sh
1628
pip install pytest-print
1729
```
1830

19-
The plugin provides ability to print information during the tests runs.
31+
## CLI flags
2032

21-
## flags
33+
The following flags are registered for the pytest command:
2234

2335
- `--print` by default the module activates print when pytest verbosity is greater than zero, this allows to bypass this
2436
and force print irrespective of the verbosity
2537
- `--print-relative-time` will print the relative time since the start of the test (display how long it takes to reach
2638
prints)
2739

28-
## use cases
40+
## API
41+
42+
This library provides the following fixtures that help you print messages within a pytest run (bypasses the pytest
43+
output capture, so it will show up in the standard output, even if the test passes):
44+
45+
- `printer: Printter` - function level fixture, when called prints a message line (with very simple formatting),
46+
- [`printer_session: Printter`](#example-printer_session) - session scoped fixture same as above but using (this exists
47+
as a backwards compatibility layer, as we didn't want to switch the originally function scope variant to session one),
48+
- [`pretty_printer: PrettyPrintter`](#example-pretty_printer) - session scoped fixture, when called prints a message
49+
line (with fancy formatting of space for indentation, `` icon for every message, and elapsed time format in form of
50+
`[{elapsed:.20f}]`) and also allows creating a printer that will be indented one level deeper (and optionally use a
51+
different icon).
52+
- [`create_pretty_printer: PrettyPrinterFactory`](#example-create_pretty_printer) - allows the caller to customize the
53+
fancy formatter as they wish. Takes one `formatter` argument, whose arguments should be interpreted as:
54+
55+
```shell
56+
┌──────┐ ┌──────────┐┌─────────┐┌────────┐
57+
│ pre │ ==│ head ││ icon ││ space │
58+
└──────┘ └──────────┘└─────────┘└────────┘
59+
60+
┌─────────────┐┌───────┐┌──────┐┌────────────┐
61+
│ indentation ││ timer ││ pre ││ msg │
62+
└─────────────┘└───────┘└──────┘└────────────┘
63+
┌───────┐┌────────────────────┐┌──────┐┌────────────┐
64+
│ timer ││ spacer ││ pre ││ msg │
65+
└───────┘└────────────────────┘└──────┘└────────────┘
66+
┌───────┐┌────────────────────┐┌────────────────────┐┌──────┐┌────────────┐
67+
│ timer ││ spacer ││ spacer ││ pre ││ msg │
68+
└───────┘└────────────────────┘└────────────────────┘└──────┘└────────────┘
69+
```
70+
71+
### Example: `printer_session`
72+
73+
```python
74+
from __future__ import annotations
75+
76+
from typing import TYPE_CHECKING, Iterator
77+
78+
import pytest
79+
80+
if TYPE_CHECKING:
81+
from pytest_print import Printer
82+
83+
84+
@pytest.fixture(scope="session")
85+
def _expensive_setup(printer_session: Printer) -> Iterator[None]:
86+
printer_session("setup")
87+
yield
88+
printer_session("teardown")
89+
90+
91+
@pytest.mark.usefixtures("_expensive_setup")
92+
def test_run(printer_session: Printer) -> None:
93+
printer_session("running")
94+
```
95+
96+
```shell
97+
pytest magic.py -vvvv
98+
...
99+
100+
magic.py::test_run
101+
setup expensive operation
102+
running test
103+
104+
magic.py::test_run PASSED
105+
teardown expensive operation
106+
```
107+
108+
### Example: `pretty_printer`
109+
110+
```python
111+
from __future__ import annotations
112+
113+
from typing import TYPE_CHECKING
114+
115+
import pytest
29116

30-
### sub-step reporting
117+
from pytest_print import Formatter
31118

32-
For tests that are long running this can provide feedback to the end-user that what is just happening in the background.
119+
if TYPE_CHECKING:
120+
from pytest_print import PrettyPrinter, PrettyPrinterFactory
121+
122+
123+
@pytest.fixture(scope="session")
124+
def pretty(create_pretty_printer: PrettyPrinterFactory) -> PrettyPrinter:
125+
formatter = Formatter(indentation=" ", head=" ", space=" ", icon="", timer_fmt="[{elapsed:.20f}]")
126+
return create_pretty_printer(formatter=formatter)
127+
128+
129+
def test_long_running(pretty: PrettyPrinter) -> None:
130+
pretty("Starting test")
131+
132+
pretty_printer_1 = pretty.indent(icon="🚀")
133+
pretty_printer_1("Drill down to 1st level details")
134+
135+
pretty_printer_2 = pretty_printer_1.indent(icon="🚀")
136+
pretty_printer_2("Drill down to 2nd level details")
137+
138+
pretty("Finished test")
139+
```
140+
141+
```shell
142+
magic.py::test_long_running
143+
⏩ Starting test
144+
🚀 Drill down to 1st level details
145+
🚀 Drill down to 2nd level details
146+
⏩ Finished test
147+
148+
magic.py::test_long_running PASSED
149+
```
150+
151+
### Example: `create_pretty_printer`
152+
153+
If you need nested messages you can use the `printer_factory` fixture or the `pprinter`.
33154

34155
```python
35-
def test_server_parallel_requests(printer, tmpdir):
36-
printer("create virtual environment into {}".format(tmpdir))
37-
create_virtual_environment(tmpdir)
156+
from __future__ import annotations
157+
158+
from typing import TYPE_CHECKING
159+
160+
import pytest
161+
162+
from pytest_print import Formatter
163+
164+
if TYPE_CHECKING:
165+
from pytest_print import PrettyPrinter, PrettyPrinterFactory
166+
167+
168+
@pytest.fixture(scope="session")
169+
def pretty(create_pretty_printer: PrettyPrinterFactory) -> PrettyPrinter:
170+
formatter = Formatter(
171+
indentation=" I ",
172+
head=" H ",
173+
space=" S ",
174+
icon="🧹",
175+
timer_fmt="[{elapsed:.5f}]",
176+
)
177+
return create_pretty_printer(formatter=formatter)
178+
179+
180+
def test_long_running(pretty: PrettyPrinter) -> None:
181+
pretty("Starting test")
182+
183+
pretty_printer_1 = pretty.indent(icon="🚀")
184+
pretty_printer_1("Drill down to 1st level details")
38185

39-
printer("start server from virtual env")
40-
start_server(tmpdir)
186+
pretty_printer_2 = pretty_printer_1.indent(icon="🚀")
187+
pretty_printer_2("Drill down to 2nd level details")
41188

42-
printer("do the parallel request test")
43-
parallel_requests()
189+
pretty("Finished test")
44190
```
45191

46192
```bash
47-
$ py.test --vv
48-
============================= test session starts ==============================
49-
platform linux -- Python 3.6.4, pytest-3.5.0, py-1.5.3, pluggy-0.6.0
50-
collecting ... collected 1 item
51-
52-
test_printer_progress.py::test_server_parallel_requests
53-
create virtual environment
54-
start server from virtual env
55-
do the parallel request test
56-
PASSED [100%]
57-
58-
=========================== 1 passed in 0.02 seconds ===========================
193+
pytest magic.py --print --print-relative-time
194+
...
195+
196+
magic.py
197+
I [0.00022] H 🧹 S Starting test
198+
[0.00029] H 🚀 S Drill down to 1st level details
199+
[0.00034] H 🚀 S Drill down to 2nd level details
200+
I [0.00038] H 🧹 S Finished test
59201
```

pyproject.toml

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@ urls.Tracker = "https://github.com/pytest-dev/pytest-print/issues"
5151
entry-points.pytest11.print = "pytest_print"
5252

5353
[tool.hatch]
54-
build.hooks.vcs.version-file = "src/pytest_print/_version.py"
5554
version.source = "vcs"
5655

5756
[tool.ruff]
@@ -64,7 +63,6 @@ lint.select = [
6463
"ALL",
6564
]
6665
lint.ignore = [
67-
"ANN101", # no type annotation for self
6866
"ANN401", # allow Any as type annotation
6967
"COM812", # Conflict with formatter
7068
"CPY", # No copyright statements
@@ -106,9 +104,9 @@ run.dynamic_context = "test_function"
106104
run.branch = true
107105
run.parallel = true
108106
report.omit = [
109-
"tests/example.py",
107+
"tests/example_*.py",
110108
]
111-
report.fail_under = 78
109+
report.fail_under = 100
112110
report.show_missing = true
113111
html.show_contexts = true
114112
html.skip_covered = false

0 commit comments

Comments
 (0)