|
8 | 8 | [](https://github.com/pytest-dev/pytest-print/actions/workflows/check.yaml)
|
9 | 9 |
|
10 | 10 | 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). |
12 | 13 |
|
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 |
14 | 26 |
|
15 | 27 | ```sh
|
16 | 28 | pip install pytest-print
|
17 | 29 | ```
|
18 | 30 |
|
19 |
| -The plugin provides ability to print information during the tests runs. |
| 31 | +## CLI flags |
20 | 32 |
|
21 |
| -## flags |
| 33 | +The following flags are registered for the pytest command: |
22 | 34 |
|
23 | 35 | - `--print` by default the module activates print when pytest verbosity is greater than zero, this allows to bypass this
|
24 | 36 | and force print irrespective of the verbosity
|
25 | 37 | - `--print-relative-time` will print the relative time since the start of the test (display how long it takes to reach
|
26 | 38 | prints)
|
27 | 39 |
|
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 |
29 | 116 |
|
30 |
| -### sub-step reporting |
| 117 | +from pytest_print import Formatter |
31 | 118 |
|
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`. |
33 | 154 |
|
34 | 155 | ```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") |
38 | 185 |
|
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") |
41 | 188 |
|
42 |
| - printer("do the parallel request test") |
43 |
| - parallel_requests() |
| 189 | + pretty("Finished test") |
44 | 190 | ```
|
45 | 191 |
|
46 | 192 | ```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 |
59 | 201 | ```
|
0 commit comments