qapytest 0.3.2__tar.gz → 0.3.3__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.
- {qapytest-0.3.2 → qapytest-0.3.3}/CHANGELOG.md +9 -0
- {qapytest-0.3.2 → qapytest-0.3.3}/PKG-INFO +3 -3
- {qapytest-0.3.2 → qapytest-0.3.3}/README.md +2 -2
- {qapytest-0.3.2 → qapytest-0.3.3}/docs/CLI.md +2 -2
- {qapytest-0.3.2 → qapytest-0.3.3}/pyproject.toml +1 -1
- {qapytest-0.3.2 → qapytest-0.3.3}/qapytest/_assets/report.html.jinja2 +1 -1
- {qapytest-0.3.2 → qapytest-0.3.3}/qapytest/_internal.py +19 -7
- {qapytest-0.3.2 → qapytest-0.3.3}/qapytest/_plugin.py +97 -55
- {qapytest-0.3.2 → qapytest-0.3.3}/qapytest/_report.py +2 -2
- {qapytest-0.3.2 → qapytest-0.3.3}/tests/test_internal_functions.py +11 -11
- {qapytest-0.3.2 → qapytest-0.3.3}/uv.lock +1 -1
- {qapytest-0.3.2 → qapytest-0.3.3}/.gitignore +0 -0
- {qapytest-0.3.2 → qapytest-0.3.3}/.pre-commit-config.yaml +0 -0
- {qapytest-0.3.2 → qapytest-0.3.3}/LICENSE +0 -0
- {qapytest-0.3.2 → qapytest-0.3.3}/NOTICE +0 -0
- {qapytest-0.3.2 → qapytest-0.3.3}/THIRD_PARTY_NOTICES.txt +0 -0
- {qapytest-0.3.2 → qapytest-0.3.3}/demo.py +0 -0
- {qapytest-0.3.2 → qapytest-0.3.3}/docs/API.md +0 -0
- {qapytest-0.3.2 → qapytest-0.3.3}/licenses/faker.LICENSE +0 -0
- {qapytest-0.3.2 → qapytest-0.3.3}/licenses/httpx.LICENSE +0 -0
- {qapytest-0.3.2 → qapytest-0.3.3}/licenses/jinja2.LICENSE +0 -0
- {qapytest-0.3.2 → qapytest-0.3.3}/licenses/jsonschema.LICENSE +0 -0
- {qapytest-0.3.2 → qapytest-0.3.3}/licenses/playwright-python.LICENSE +0 -0
- {qapytest-0.3.2 → qapytest-0.3.3}/licenses/pytest-playwright.LICENSE +0 -0
- {qapytest-0.3.2 → qapytest-0.3.3}/licenses/pytest.LICENSE +0 -0
- {qapytest-0.3.2 → qapytest-0.3.3}/licenses/python_dotenv.LICENSE +0 -0
- {qapytest-0.3.2 → qapytest-0.3.3}/licenses/redis-py.LICENSE +0 -0
- {qapytest-0.3.2 → qapytest-0.3.3}/licenses/sqlalchemy.LICENSE +0 -0
- {qapytest-0.3.2 → qapytest-0.3.3}/qapytest/__init__.py +0 -0
- {qapytest-0.3.2 → qapytest-0.3.3}/qapytest/_assets/_log_tree.html.jinja2 +0 -0
- {qapytest-0.3.2 → qapytest-0.3.3}/qapytest/_assets/scripts.js +0 -0
- {qapytest-0.3.2 → qapytest-0.3.3}/qapytest/_assets/styles.css +0 -0
- {qapytest-0.3.2 → qapytest-0.3.3}/qapytest/_attach.py +0 -0
- {qapytest-0.3.2 → qapytest-0.3.3}/qapytest/_client_http.py +0 -0
- {qapytest-0.3.2 → qapytest-0.3.3}/qapytest/_config.py +0 -0
- {qapytest-0.3.2 → qapytest-0.3.3}/qapytest/_config_http.py +0 -0
- {qapytest-0.3.2 → qapytest-0.3.3}/qapytest/_json_validation.py +0 -0
- {qapytest-0.3.2 → qapytest-0.3.3}/qapytest/_redis.py +0 -0
- {qapytest-0.3.2 → qapytest-0.3.3}/qapytest/_soft_assert.py +0 -0
- {qapytest-0.3.2 → qapytest-0.3.3}/qapytest/_sql.py +0 -0
- {qapytest-0.3.2 → qapytest-0.3.3}/qapytest/_step.py +0 -0
- {qapytest-0.3.2 → qapytest-0.3.3}/qapytest/py.typed +0 -0
- {qapytest-0.3.2 → qapytest-0.3.3}/tests/encoding.py +0 -0
- {qapytest-0.3.2 → qapytest-0.3.3}/tests/test_attach.py +0 -0
- {qapytest-0.3.2 → qapytest-0.3.3}/tests/test_graphql_client.py +0 -0
- {qapytest-0.3.2 → qapytest-0.3.3}/tests/test_http_client.py +0 -0
- {qapytest-0.3.2 → qapytest-0.3.3}/tests/test_integration.py +0 -0
- {qapytest-0.3.2 → qapytest-0.3.3}/tests/test_markers.py +0 -0
- {qapytest-0.3.2 → qapytest-0.3.3}/tests/test_redis_client.py +0 -0
- {qapytest-0.3.2 → qapytest-0.3.3}/tests/test_soft_assert.py +0 -0
- {qapytest-0.3.2 → qapytest-0.3.3}/tests/test_sql_client.py +0 -0
- {qapytest-0.3.2 → qapytest-0.3.3}/tests/test_step.py +0 -0
|
@@ -5,6 +5,14 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.3.3] - 2025-10-31
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- ⚙️ **CLI option renamed** - `--disable-unicode-terminal` renamed to `--disable-unicode`
|
|
13
|
+
- 🖥️ **Unicode display in IDE** - fixed Unicode rendering issues in integrated development environments
|
|
14
|
+
- 🔧 **Minor bug fixes** - resolved small issues to improve overall stability
|
|
15
|
+
|
|
8
16
|
## [0.3.2] - 2025-10-29
|
|
9
17
|
|
|
10
18
|
### Added
|
|
@@ -149,6 +157,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
149
157
|
- Configurable attachment size limits
|
|
150
158
|
- Professional report styling with responsive design
|
|
151
159
|
|
|
160
|
+
[0.3.3]: https://github.com/o73k51i/qapytest/releases/tag/v0.3.3
|
|
152
161
|
[0.3.2]: https://github.com/o73k51i/qapytest/releases/tag/v0.3.2
|
|
153
162
|
[0.3.1]: https://github.com/o73k51i/qapytest/releases/tag/v0.3.1
|
|
154
163
|
[0.3.0]: https://github.com/o73k51i/qapytest/releases/tag/v0.3.0
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: qapytest
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.3
|
|
4
4
|
Summary: A powerful testing framework based on pytest, specifically designed for QA engineers
|
|
5
5
|
Project-URL: Homepage, https://github.com/o73k51i/qapytest
|
|
6
6
|
Project-URL: Repository, https://github.com/o73k51i/qapytest
|
|
@@ -281,8 +281,8 @@ def test_user_login():
|
|
|
281
281
|
- **`--report-title NAME`** : set the HTML report title.
|
|
282
282
|
- **`--report-theme {light,dark,auto}`** : choose the report theme: `light`,
|
|
283
283
|
`dark` or `auto` (default).
|
|
284
|
-
- **`--disable-unicode
|
|
285
|
-
terminal for compatibility with older systems.
|
|
284
|
+
- **`--disable-unicode`** : disable Unicode character display in
|
|
285
|
+
terminal output for compatibility with older terminals or CI systems.
|
|
286
286
|
|
|
287
287
|
More about CLI options on the [documentation page](https://github.com/o73k51i/qapytest/blob/main/docs/CLI.md).
|
|
288
288
|
|
|
@@ -225,8 +225,8 @@ def test_user_login():
|
|
|
225
225
|
- **`--report-title NAME`** : set the HTML report title.
|
|
226
226
|
- **`--report-theme {light,dark,auto}`** : choose the report theme: `light`,
|
|
227
227
|
`dark` or `auto` (default).
|
|
228
|
-
- **`--disable-unicode
|
|
229
|
-
terminal for compatibility with older systems.
|
|
228
|
+
- **`--disable-unicode`** : disable Unicode character display in
|
|
229
|
+
terminal output for compatibility with older terminals or CI systems.
|
|
230
230
|
|
|
231
231
|
More about CLI options on the [documentation page](https://github.com/o73k51i/qapytest/blob/main/docs/CLI.md).
|
|
232
232
|
|
|
@@ -23,7 +23,7 @@ Below are the available options, their purpose, and usage examples.
|
|
|
23
23
|
`dark`, or `auto` (default).
|
|
24
24
|
- **`--max-attachment-bytes N`** : maximum attachment size (in bytes) to embed
|
|
25
25
|
in the HTML; larger files will be truncated (default is unlimited).
|
|
26
|
-
- **`--disable-unicode
|
|
26
|
+
- **`--disable-unicode`** : disable Unicode character display in
|
|
27
27
|
terminal output for compatibility with older terminals or CI systems.
|
|
28
28
|
|
|
29
29
|
### Behavior with `.env`
|
|
@@ -57,7 +57,7 @@ you can disable this feature:
|
|
|
57
57
|
|
|
58
58
|
```bash
|
|
59
59
|
# Disable Unicode character display in terminal
|
|
60
|
-
pytest --disable-unicode
|
|
60
|
+
pytest --disable-unicode --report-html
|
|
61
61
|
|
|
62
62
|
# Normal run with Unicode support (default)
|
|
63
63
|
pytest --report-html
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
<td class="small">{{ loop.index }}</td>
|
|
54
54
|
<td>
|
|
55
55
|
<div class="mono">{{ decode_unicode_escapes(result.title)|e }}</div>
|
|
56
|
-
{% if params_str %}<div class="small">Parametrize: {{ params_str|e }}</div>{% endif %}
|
|
56
|
+
{% if params_str %}<div class="small">Parametrize: {{ decode_unicode_escapes(params_str)|e }}</div>{% endif %}
|
|
57
57
|
</td>
|
|
58
58
|
<td><span class="status {{ result.outcome }}">{{ result.outcome }}</span></td>
|
|
59
59
|
<td class="small">{{ (result.components or [])|join(', ')|e }}</td>
|
|
@@ -272,21 +272,33 @@ def parse_params_from_nodeid(nodeid: str) -> str:
|
|
|
272
272
|
end = nodeid.rfind("]")
|
|
273
273
|
if start != -1 and end != -1 and end > start:
|
|
274
274
|
param_str = nodeid[start + 1 : end]
|
|
275
|
-
try:
|
|
276
|
-
import codecs
|
|
277
275
|
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
276
|
+
if all(ord(c) <= 255 for c in param_str):
|
|
277
|
+
try:
|
|
278
|
+
return param_str.encode("latin-1").decode("utf-8")
|
|
279
|
+
except (UnicodeEncodeError, UnicodeDecodeError):
|
|
280
|
+
pass
|
|
281
|
+
|
|
282
|
+
if "\\" in param_str:
|
|
283
|
+
try:
|
|
284
|
+
import codecs
|
|
285
|
+
|
|
286
|
+
decoded = codecs.decode(param_str, "unicode_escape")
|
|
287
|
+
if decoded != param_str:
|
|
288
|
+
return decoded
|
|
289
|
+
except Exception: # noqa: S110
|
|
290
|
+
pass
|
|
291
|
+
|
|
292
|
+
return param_str
|
|
281
293
|
except Exception: # noqa: S110
|
|
282
294
|
pass
|
|
283
295
|
return ""
|
|
284
296
|
|
|
285
297
|
|
|
286
298
|
def decode_unicode_escapes(text: str) -> str:
|
|
287
|
-
"""Decode Unicode escape sequences in text to readable characters."""
|
|
299
|
+
"""Decode Unicode and other escape sequences in text to readable characters."""
|
|
288
300
|
try:
|
|
289
|
-
if "\\
|
|
301
|
+
if "\\" in text:
|
|
290
302
|
import codecs
|
|
291
303
|
|
|
292
304
|
return codecs.decode(text, "unicode_escape")
|
|
@@ -9,6 +9,7 @@ of Pytest.
|
|
|
9
9
|
|
|
10
10
|
from __future__ import annotations
|
|
11
11
|
|
|
12
|
+
import shutil
|
|
12
13
|
from collections.abc import Generator
|
|
13
14
|
from pathlib import Path
|
|
14
15
|
|
|
@@ -19,56 +20,6 @@ from qapytest import _internal as utils
|
|
|
19
20
|
from qapytest import _report as report
|
|
20
21
|
|
|
21
22
|
|
|
22
|
-
class UnicodeTerminalPlugin:
|
|
23
|
-
"""Plugin to display Unicode characters properly in terminal output."""
|
|
24
|
-
|
|
25
|
-
def __init__(self) -> None:
|
|
26
|
-
self._original_write = None
|
|
27
|
-
self._patched = False
|
|
28
|
-
|
|
29
|
-
@pytest.hookimpl(tryfirst=True)
|
|
30
|
-
def pytest_sessionstart(self, session: pytest.Session) -> None:
|
|
31
|
-
"""Patch terminal reporter at session start."""
|
|
32
|
-
if self._patched:
|
|
33
|
-
return
|
|
34
|
-
|
|
35
|
-
config = session.config
|
|
36
|
-
terminal_reporter = config.pluginmanager.get_plugin("terminalreporter")
|
|
37
|
-
|
|
38
|
-
if terminal_reporter and hasattr(terminal_reporter, "_tw") and hasattr(terminal_reporter._tw, "write"): # noqa: SLF001
|
|
39
|
-
try:
|
|
40
|
-
self._original_write = terminal_reporter._tw.write # noqa: SLF001
|
|
41
|
-
|
|
42
|
-
def unicode_write(s: str, **kwargs: cfg.AnyType) -> None:
|
|
43
|
-
"""Write method that decodes Unicode escapes."""
|
|
44
|
-
if "\\u" in s and ("::" in s or "PASSED" in s or "FAILED" in s):
|
|
45
|
-
decoded_s = utils.decode_unicode_escapes(s)
|
|
46
|
-
self._original_write(decoded_s, **kwargs) # type: ignore[misc]
|
|
47
|
-
else:
|
|
48
|
-
self._original_write(s, **kwargs) # type: ignore[misc]
|
|
49
|
-
|
|
50
|
-
terminal_reporter._tw.write = unicode_write # noqa: SLF001
|
|
51
|
-
self._patched = True
|
|
52
|
-
except Exception: # noqa: S110
|
|
53
|
-
pass
|
|
54
|
-
|
|
55
|
-
@pytest.hookimpl
|
|
56
|
-
def pytest_sessionfinish(self, session: pytest.Session, exitstatus: int) -> None: # noqa: ARG002
|
|
57
|
-
"""Restore original write method at session finish."""
|
|
58
|
-
if not self._patched:
|
|
59
|
-
return
|
|
60
|
-
|
|
61
|
-
config = session.config
|
|
62
|
-
terminal_reporter = config.pluginmanager.get_plugin("terminalreporter")
|
|
63
|
-
|
|
64
|
-
if terminal_reporter and self._original_write:
|
|
65
|
-
try:
|
|
66
|
-
terminal_reporter._tw.write = self._original_write # noqa: SLF001
|
|
67
|
-
self._patched = False
|
|
68
|
-
except Exception: # noqa: S110
|
|
69
|
-
pass
|
|
70
|
-
|
|
71
|
-
|
|
72
23
|
def pytest_addoption(parser: pytest.Parser) -> None:
|
|
73
24
|
group = parser.getgroup("QAPyTest", "QAPyTest custom options")
|
|
74
25
|
group.addoption(
|
|
@@ -118,7 +69,7 @@ def pytest_addoption(parser: pytest.Parser) -> None:
|
|
|
118
69
|
help="Max bytes to embed for any single attachment (text or binary). Larger data will be truncated.",
|
|
119
70
|
)
|
|
120
71
|
group.addoption(
|
|
121
|
-
"--disable-unicode
|
|
72
|
+
"--disable-unicode",
|
|
122
73
|
action="store_true",
|
|
123
74
|
default=False,
|
|
124
75
|
help="Disable Unicode character display in terminal (for compatibility).",
|
|
@@ -135,9 +86,36 @@ def pytest_configure(config: pytest.Config) -> None:
|
|
|
135
86
|
|
|
136
87
|
cfg.ATTACH_LIMIT_BYTES = config.getoption("max_attachment_bytes")
|
|
137
88
|
|
|
138
|
-
if not config.getoption("
|
|
139
|
-
|
|
140
|
-
|
|
89
|
+
if not config.getoption("--disable-unicode"):
|
|
90
|
+
for i, arg in enumerate(config.args):
|
|
91
|
+
if "::" in arg:
|
|
92
|
+
path_part, test_part = arg.split("::", 1)
|
|
93
|
+
path = Path(path_part)
|
|
94
|
+
if not path.is_absolute():
|
|
95
|
+
path = Path.cwd() / path
|
|
96
|
+
abs_path = str(path)
|
|
97
|
+
try:
|
|
98
|
+
encoded_test = test_part.encode("ascii", "backslashreplace").decode("ascii")
|
|
99
|
+
except Exception:
|
|
100
|
+
encoded_test = test_part
|
|
101
|
+
config.args[i] = abs_path + "::" + encoded_test
|
|
102
|
+
|
|
103
|
+
try:
|
|
104
|
+
import _pytest.main as main
|
|
105
|
+
|
|
106
|
+
spec_class = main.Spec # type: ignore
|
|
107
|
+
original_matches = spec_class.matches
|
|
108
|
+
|
|
109
|
+
def new_matches(self, item): # noqa: ANN001, ANN202
|
|
110
|
+
if hasattr(item, "nodeid") and not item.config.getoption("--disable-unicode"):
|
|
111
|
+
encoded_item_nodeid = item.nodeid.encode("ascii", "backslashreplace").decode("ascii")
|
|
112
|
+
if encoded_item_nodeid == self.nodeid:
|
|
113
|
+
return True
|
|
114
|
+
return original_matches(self, item)
|
|
115
|
+
|
|
116
|
+
spec_class.matches = new_matches
|
|
117
|
+
except Exception: # noqa: S110
|
|
118
|
+
pass
|
|
141
119
|
|
|
142
120
|
report_path = config.getoption("report_html")
|
|
143
121
|
if not report_path:
|
|
@@ -172,10 +150,21 @@ def pytest_runtest_teardown(item: pytest.Item, nextitem: pytest.Item | None) ->
|
|
|
172
150
|
|
|
173
151
|
|
|
174
152
|
@pytest.hookimpl(hookwrapper=True)
|
|
175
|
-
def pytest_runtest_makereport(item: pytest.Item, call: cfg.AnyType) -> Generator[cfg.AnyType, None, None]:
|
|
153
|
+
def pytest_runtest_makereport(item: pytest.Item, call: cfg.AnyType) -> Generator[cfg.AnyType, None, None]:
|
|
176
154
|
outcome = yield
|
|
177
155
|
report: pytest.TestReport = outcome.get_result() # type: ignore
|
|
178
156
|
|
|
157
|
+
if not item.config.getoption("disable_unicode"):
|
|
158
|
+
if hasattr(report, "nodeid") and report.nodeid and "\\" in report.nodeid:
|
|
159
|
+
report.nodeid = utils.decode_unicode_escapes(report.nodeid)
|
|
160
|
+
if hasattr(report, "location") and getattr(report, "location", None):
|
|
161
|
+
try:
|
|
162
|
+
path, lineno, domain = report.location # type: ignore[misc]
|
|
163
|
+
if isinstance(domain, str) and "\\" in domain:
|
|
164
|
+
report.location = (path, lineno, utils.decode_unicode_escapes(domain))
|
|
165
|
+
except Exception: # noqa: S110
|
|
166
|
+
pass
|
|
167
|
+
|
|
179
168
|
try:
|
|
180
169
|
if call and getattr(call, "excinfo", None) is not None and call.excinfo.type is not None:
|
|
181
170
|
report._exc_class_name = getattr( # noqa: SLF001 # type: ignore
|
|
@@ -206,6 +195,14 @@ def pytest_runtest_makereport(item: pytest.Item, call: cfg.AnyType) -> Generator
|
|
|
206
195
|
full_summary = [header, *error_summary_lines]
|
|
207
196
|
report.longrepr = "\n".join(full_summary)
|
|
208
197
|
|
|
198
|
+
if (
|
|
199
|
+
not item.config.getoption("disable_unicode")
|
|
200
|
+
and hasattr(report, "longrepr")
|
|
201
|
+
and report.longrepr
|
|
202
|
+
and "\\u" in str(report.longrepr)
|
|
203
|
+
):
|
|
204
|
+
report.longrepr = utils.decode_unicode_escapes(str(report.longrepr))
|
|
205
|
+
|
|
209
206
|
|
|
210
207
|
def pytest_collection_modifyitems(config: pytest.Config, items: list[pytest.Item]) -> None: # noqa: ARG001
|
|
211
208
|
for item in items:
|
|
@@ -221,3 +218,48 @@ def pytest_collection_modifyitems(config: pytest.Config, items: list[pytest.Item
|
|
|
221
218
|
components.append(arg)
|
|
222
219
|
if components:
|
|
223
220
|
item.user_properties.append(("components", tuple(components)))
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
def pytest_itemcollected(item: pytest.Item) -> None:
|
|
224
|
+
if not item.config.getoption("disable_unicode"):
|
|
225
|
+
if "\\" in item.nodeid:
|
|
226
|
+
item._nodeid = utils.decode_unicode_escapes(item.nodeid) # noqa: SLF001
|
|
227
|
+
try:
|
|
228
|
+
if isinstance(getattr(item, "name", None), str) and "\\u" in item.name:
|
|
229
|
+
decoded_name = utils.decode_unicode_escapes(item.name)
|
|
230
|
+
object.__setattr__(item, "name", decoded_name)
|
|
231
|
+
except Exception: # noqa: S110
|
|
232
|
+
pass
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
def pytest_sessionstart(session): # noqa: ANN001, ANN202
|
|
236
|
+
"""Patch terminal reporter at session start."""
|
|
237
|
+
if session.config.getoption("disable_unicode"):
|
|
238
|
+
return
|
|
239
|
+
|
|
240
|
+
try:
|
|
241
|
+
terminal_reporter = session.config.pluginmanager.get_plugin("terminalreporter")
|
|
242
|
+
if terminal_reporter and hasattr(terminal_reporter, "_tw"):
|
|
243
|
+
tw = terminal_reporter._tw # noqa: SLF001
|
|
244
|
+
if hasattr(tw, "write"):
|
|
245
|
+
original_write = tw.write
|
|
246
|
+
|
|
247
|
+
def unicode_write(s, **kwargs): # noqa: ANN001, ANN202
|
|
248
|
+
if isinstance(s, str) and "\\" in s:
|
|
249
|
+
decoded_s = utils.decode_unicode_escapes(s)
|
|
250
|
+
if decoded_s.startswith("_") and decoded_s.endswith("_") and " " in decoded_s:
|
|
251
|
+
stripped = decoded_s.strip("_")
|
|
252
|
+
if stripped.startswith(" ") and stripped.endswith(" "):
|
|
253
|
+
nodeid = stripped.strip()
|
|
254
|
+
total_width = shutil.get_terminal_size().columns - 2
|
|
255
|
+
nodeid_len = len(nodeid)
|
|
256
|
+
if nodeid_len + 4 <= total_width:
|
|
257
|
+
left_underscores = (total_width - nodeid_len - 2) // 2
|
|
258
|
+
right_underscores = total_width - left_underscores - len(nodeid) - 2
|
|
259
|
+
decoded_s = "_" * left_underscores + " " + nodeid + " " + "_" * right_underscores
|
|
260
|
+
s = decoded_s
|
|
261
|
+
return original_write(s, **kwargs)
|
|
262
|
+
|
|
263
|
+
tw.write = unicode_write
|
|
264
|
+
except Exception: # noqa: S110
|
|
265
|
+
pass
|
|
@@ -37,7 +37,7 @@ class HtmlReportPlugin:
|
|
|
37
37
|
return "", 0, getattr(report, "nodeid", "")
|
|
38
38
|
|
|
39
39
|
def pytest_runtest_logreport(self, report: pytest.TestReport) -> None:
|
|
40
|
-
nodeid = report.nodeid
|
|
40
|
+
nodeid = utils.decode_unicode_escapes(report.nodeid)
|
|
41
41
|
if nodeid not in self.results:
|
|
42
42
|
self.test_order.append(nodeid)
|
|
43
43
|
path, lineno, _ = self._safe_location(report)
|
|
@@ -97,7 +97,7 @@ class HtmlReportPlugin:
|
|
|
97
97
|
|
|
98
98
|
self.collection_errors.append(
|
|
99
99
|
{
|
|
100
|
-
"nodeid": getattr(report, "nodeid", "<collection>"),
|
|
100
|
+
"nodeid": utils.decode_unicode_escapes(getattr(report, "nodeid", "<collection>")),
|
|
101
101
|
"path": path,
|
|
102
102
|
"outcome": "error",
|
|
103
103
|
"duration": getattr(report, "duration", 0.0),
|
|
@@ -268,21 +268,22 @@ class TestTextUtilities:
|
|
|
268
268
|
|
|
269
269
|
def test_parse_params_from_nodeid_with_unicode_escapes(self):
|
|
270
270
|
"""Test parsing parameters with Unicode escape sequences from pytest nodeid."""
|
|
271
|
-
|
|
271
|
+
# Test with already decoded Unicode characters (as they appear in pytest nodeids)
|
|
272
|
+
nodeid_cyrillic = "test_file.py::test_function[Перший]"
|
|
272
273
|
params = utils.parse_params_from_nodeid(nodeid_cyrillic)
|
|
273
274
|
assert params == "Перший"
|
|
274
275
|
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
"u0448\\u0438\\u0439-\\u0414\\u0440\\u0443\\u0433\\u0438\\u0439]"
|
|
278
|
-
)
|
|
276
|
+
# Test with multiple parameters
|
|
277
|
+
nodeid_multiple = "test_file.py::test_function[Перший-Другий]"
|
|
279
278
|
params = utils.parse_params_from_nodeid(nodeid_multiple)
|
|
280
279
|
assert params == "Перший-Другий"
|
|
281
280
|
|
|
282
|
-
|
|
281
|
+
# Test with mixed content
|
|
282
|
+
nodeid_mixed = "test_file.py::test_function[test-Третій-param]"
|
|
283
283
|
params = utils.parse_params_from_nodeid(nodeid_mixed)
|
|
284
284
|
assert params == "test-Третій-param"
|
|
285
285
|
|
|
286
|
+
# Test with malformed escape (should return original)
|
|
286
287
|
nodeid_malformed = "test_file.py::test_function[\\u041Z-invalid]"
|
|
287
288
|
params = utils.parse_params_from_nodeid(nodeid_malformed)
|
|
288
289
|
assert params == "\\u041Z-invalid" # Should return original string on decode error
|
|
@@ -323,7 +324,8 @@ class TestTextUtilities:
|
|
|
323
324
|
|
|
324
325
|
def test_unicode_functions_integration(self):
|
|
325
326
|
"""Test integration of Unicode functions with realistic pytest nodeid examples."""
|
|
326
|
-
|
|
327
|
+
# Test with already decoded Unicode characters
|
|
328
|
+
realistic_nodeid = "temp.py::test_parametrized[Перший]"
|
|
327
329
|
|
|
328
330
|
params = utils.parse_params_from_nodeid(realistic_nodeid)
|
|
329
331
|
assert params == "Перший"
|
|
@@ -339,10 +341,8 @@ class TestTextUtilities:
|
|
|
339
341
|
decoded_title = utils.decode_unicode_escapes(title_with_escapes)
|
|
340
342
|
assert decoded_title == "Перевірка відображення параметризації"
|
|
341
343
|
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
"\\u0414\\u0440\\u0443\\u0433\\u0438\\u0439-\\u0422\\u0440\\u0435\\u0442\\u0456\\u0439]"
|
|
345
|
-
)
|
|
344
|
+
# Test with multiple parameters
|
|
345
|
+
multi_param_nodeid = "test.py::test_func[Перший-Другий-Третій]"
|
|
346
346
|
multi_params = utils.parse_params_from_nodeid(multi_param_nodeid)
|
|
347
347
|
assert multi_params == "Перший-Другий-Третій"
|
|
348
348
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|