pytest-extended-data 0.1.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_extended_data-0.1.0/.gitignore +16 -0
- pytest_extended_data-0.1.0/CHANGELOG.md +8 -0
- pytest_extended_data-0.1.0/PKG-INFO +45 -0
- pytest_extended_data-0.1.0/README.md +18 -0
- pytest_extended_data-0.1.0/pyproject.toml +47 -0
- pytest_extended_data-0.1.0/src/pytest_extended_data/__init__.py +11 -0
- pytest_extended_data-0.1.0/src/pytest_extended_data/plugin.py +63 -0
- pytest_extended_data-0.1.0/src/pytest_extended_data/py.typed +1 -0
- pytest_extended_data-0.1.0/tests/test_plugin.py +64 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
.venv/
|
|
2
|
+
.pytest_cache/
|
|
3
|
+
.ruff_cache/
|
|
4
|
+
.mypy_cache/
|
|
5
|
+
.hypothesis/
|
|
6
|
+
dist/
|
|
7
|
+
build/
|
|
8
|
+
*.egg-info/
|
|
9
|
+
__pycache__/
|
|
10
|
+
*.py[cod]
|
|
11
|
+
*.log
|
|
12
|
+
coverage.xml
|
|
13
|
+
.coverage
|
|
14
|
+
.tox/
|
|
15
|
+
packages/extended-data/docs/apidocs/
|
|
16
|
+
packages/extended-data/docs/_build/
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pytest-extended-data
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Pytest fixtures and assertions for projects using extended-data
|
|
5
|
+
Project-URL: Documentation, https://extended-data.dev
|
|
6
|
+
Project-URL: Issues, https://github.com/jbcom/extended-data/issues
|
|
7
|
+
Project-URL: Source, https://github.com/jbcom/extended-data
|
|
8
|
+
Project-URL: Changelog, https://github.com/jbcom/extended-data/blob/main/packages/pytest-extended-data/CHANGELOG.md
|
|
9
|
+
Author-email: Jon Bogaty <jon@jonbogaty.com>
|
|
10
|
+
Maintainer-email: Jon Bogaty <jon@jonbogaty.com>
|
|
11
|
+
License: MIT
|
|
12
|
+
Keywords: extended-data,fixtures,pytest,testing
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Framework :: Pytest
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
22
|
+
Classifier: Typing :: Typed
|
|
23
|
+
Requires-Python: >=3.11
|
|
24
|
+
Requires-Dist: extended-data>=8.3.1
|
|
25
|
+
Requires-Dist: pytest>=9.0.3
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
|
|
28
|
+
# pytest-extended-data
|
|
29
|
+
|
|
30
|
+
`pytest-extended-data` publishes reusable pytest fixtures and assertions for
|
|
31
|
+
projects built on `extended-data`.
|
|
32
|
+
|
|
33
|
+
Install it in test environments:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
uv add --dev pytest-extended-data
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
The plugin is exposed through the standard `pytest11` entry point. It provides:
|
|
40
|
+
|
|
41
|
+
- `extended_data_factory`: the `ExtendedData` polymorphic constructor.
|
|
42
|
+
- `extended_data_payload`: a small nested mapping payload for examples and smoke tests.
|
|
43
|
+
- `extended_data_value`: the payload wrapped as an `ExtendedData` value.
|
|
44
|
+
- `assert_extended_shape(value, shape)`: assertion helper for shape checks.
|
|
45
|
+
- `assert_builtin_round_trip(value, expected)`: assertion helper for export-boundary checks.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# pytest-extended-data
|
|
2
|
+
|
|
3
|
+
`pytest-extended-data` publishes reusable pytest fixtures and assertions for
|
|
4
|
+
projects built on `extended-data`.
|
|
5
|
+
|
|
6
|
+
Install it in test environments:
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
uv add --dev pytest-extended-data
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
The plugin is exposed through the standard `pytest11` entry point. It provides:
|
|
13
|
+
|
|
14
|
+
- `extended_data_factory`: the `ExtendedData` polymorphic constructor.
|
|
15
|
+
- `extended_data_payload`: a small nested mapping payload for examples and smoke tests.
|
|
16
|
+
- `extended_data_value`: the payload wrapped as an `ExtendedData` value.
|
|
17
|
+
- `assert_extended_shape(value, shape)`: assertion helper for shape checks.
|
|
18
|
+
- `assert_builtin_round_trip(value, expected)`: assertion helper for export-boundary checks.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "pytest-extended-data"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Pytest fixtures and assertions for projects using extended-data"
|
|
9
|
+
requires-python = ">=3.11"
|
|
10
|
+
license = { text = "MIT" }
|
|
11
|
+
readme = "README.md"
|
|
12
|
+
keywords = [
|
|
13
|
+
"extended-data",
|
|
14
|
+
"pytest",
|
|
15
|
+
"fixtures",
|
|
16
|
+
"testing",
|
|
17
|
+
]
|
|
18
|
+
authors = [{ name = "Jon Bogaty", email = "jon@jonbogaty.com" }]
|
|
19
|
+
maintainers = [{ name = "Jon Bogaty", email = "jon@jonbogaty.com" }]
|
|
20
|
+
classifiers = [
|
|
21
|
+
"Development Status :: 4 - Beta",
|
|
22
|
+
"Framework :: Pytest",
|
|
23
|
+
"Intended Audience :: Developers",
|
|
24
|
+
"License :: OSI Approved :: MIT License",
|
|
25
|
+
"Programming Language :: Python :: 3",
|
|
26
|
+
"Programming Language :: Python :: 3.11",
|
|
27
|
+
"Programming Language :: Python :: 3.12",
|
|
28
|
+
"Programming Language :: Python :: 3.13",
|
|
29
|
+
"Programming Language :: Python :: 3.14",
|
|
30
|
+
"Typing :: Typed",
|
|
31
|
+
]
|
|
32
|
+
dependencies = [
|
|
33
|
+
"extended-data>=8.3.1",
|
|
34
|
+
"pytest>=9.0.3",
|
|
35
|
+
]
|
|
36
|
+
|
|
37
|
+
[project.urls]
|
|
38
|
+
Documentation = "https://extended-data.dev"
|
|
39
|
+
Issues = "https://github.com/jbcom/extended-data/issues"
|
|
40
|
+
Source = "https://github.com/jbcom/extended-data"
|
|
41
|
+
Changelog = "https://github.com/jbcom/extended-data/blob/main/packages/pytest-extended-data/CHANGELOG.md"
|
|
42
|
+
|
|
43
|
+
[project.entry-points.pytest11]
|
|
44
|
+
extended_data = "pytest_extended_data.plugin"
|
|
45
|
+
|
|
46
|
+
[tool.hatch.build.targets.wheel]
|
|
47
|
+
packages = ["src/pytest_extended_data"]
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"""Pytest helpers for projects using Extended Data."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from pytest_extended_data.plugin import assert_builtin_round_trip, assert_extended_shape
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
__all__ = [
|
|
9
|
+
"assert_builtin_round_trip",
|
|
10
|
+
"assert_extended_shape",
|
|
11
|
+
]
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"""Pytest fixtures and assertions for Extended Data consumers."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from collections.abc import Callable, Mapping
|
|
6
|
+
from typing import TYPE_CHECKING, Any
|
|
7
|
+
|
|
8
|
+
import pytest
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
if TYPE_CHECKING:
|
|
12
|
+
from extended_data import ExtendedData
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _extended_data_type() -> type[ExtendedData]:
|
|
16
|
+
from extended_data import ExtendedData
|
|
17
|
+
|
|
18
|
+
return ExtendedData
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def assert_extended_shape(value: ExtendedData, shape: str) -> None:
|
|
22
|
+
"""Assert that an Extended Data value has the expected broad shape."""
|
|
23
|
+
extended_data = _extended_data_type()
|
|
24
|
+
if not isinstance(value, extended_data):
|
|
25
|
+
raise TypeError(f"expected ExtendedData value, got {type(value).__name__}")
|
|
26
|
+
assert value.shape == shape, f"expected ExtendedData shape {shape!r}, got {value.shape!r}"
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def assert_builtin_round_trip(value: ExtendedData, expected: Any) -> None:
|
|
30
|
+
"""Assert that an Extended Data value lowers to the expected built-in data."""
|
|
31
|
+
extended_data = _extended_data_type()
|
|
32
|
+
if not isinstance(value, extended_data):
|
|
33
|
+
raise TypeError(f"expected ExtendedData value, got {type(value).__name__}")
|
|
34
|
+
|
|
35
|
+
actual = value.as_builtin()
|
|
36
|
+
assert actual == expected, f"expected built-in data {expected!r}, got {actual!r}"
|
|
37
|
+
|
|
38
|
+
round_trip = extended_data(actual).as_builtin()
|
|
39
|
+
assert round_trip == expected, f"expected round-trip data {expected!r}, got {round_trip!r}"
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
@pytest.fixture
|
|
43
|
+
def extended_data_factory() -> Callable[[Any], ExtendedData]:
|
|
44
|
+
"""Return the polymorphic Extended Data constructor."""
|
|
45
|
+
return _extended_data_type()
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
@pytest.fixture
|
|
49
|
+
def extended_data_payload() -> Mapping[str, Any]:
|
|
50
|
+
"""Return a representative nested mapping payload."""
|
|
51
|
+
return {
|
|
52
|
+
"service": {
|
|
53
|
+
"name": "api",
|
|
54
|
+
"ports": [8080, 8443],
|
|
55
|
+
},
|
|
56
|
+
"enabled": True,
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
@pytest.fixture
|
|
61
|
+
def extended_data_value(extended_data_payload: Mapping[str, Any]) -> ExtendedData:
|
|
62
|
+
"""Return the sample payload promoted to Extended Data."""
|
|
63
|
+
return _extended_data_type()(extended_data_payload)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from collections.abc import Callable, Mapping
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
import pytest
|
|
7
|
+
|
|
8
|
+
from extended_data import ExtendedData, ExtendedDict
|
|
9
|
+
from pytest_extended_data import assert_builtin_round_trip, assert_extended_shape, plugin
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def test_extended_data_factory_fixture_promotes_payload(
|
|
13
|
+
extended_data_factory: Callable[[Any], ExtendedData],
|
|
14
|
+
extended_data_payload: Mapping[str, Any],
|
|
15
|
+
) -> None:
|
|
16
|
+
value = extended_data_factory(extended_data_payload)
|
|
17
|
+
|
|
18
|
+
assert isinstance(value, ExtendedDict)
|
|
19
|
+
assert_extended_shape(value, "mapping")
|
|
20
|
+
assert_builtin_round_trip(value, dict(extended_data_payload))
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def test_extended_data_value_fixture_is_ready_to_assert(extended_data_value: ExtendedData) -> None:
|
|
24
|
+
assert_extended_shape(extended_data_value, "mapping")
|
|
25
|
+
assert extended_data_value["service"]["name"] == "api"
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def test_assert_extended_shape_rejects_non_extended_values() -> None:
|
|
29
|
+
with pytest.raises(TypeError, match="expected ExtendedData value"):
|
|
30
|
+
assert_extended_shape("api", "scalar")
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def test_assert_extended_shape_rejects_wrong_shape() -> None:
|
|
34
|
+
with pytest.raises(AssertionError, match="expected ExtendedData shape 'sequence'"):
|
|
35
|
+
assert_extended_shape(ExtendedData({"service": "api"}), "sequence")
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def test_assert_builtin_round_trip_rejects_non_extended_values() -> None:
|
|
39
|
+
with pytest.raises(TypeError, match="expected ExtendedData value"):
|
|
40
|
+
assert_builtin_round_trip({"service": "api"}, {"service": "api"})
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def test_assert_builtin_round_trip_rejects_wrong_builtin_value() -> None:
|
|
44
|
+
with pytest.raises(AssertionError, match="expected built-in data"):
|
|
45
|
+
assert_builtin_round_trip(ExtendedData({"service": "api"}), {"service": "worker"})
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def test_assert_builtin_round_trip_rejects_unstable_round_trip(monkeypatch: pytest.MonkeyPatch) -> None:
|
|
49
|
+
class UnstableExtendedData:
|
|
50
|
+
shape = "mapping"
|
|
51
|
+
|
|
52
|
+
def __init__(self, value: Any, *, stable: bool = False) -> None:
|
|
53
|
+
self.value = value
|
|
54
|
+
self.stable = stable
|
|
55
|
+
|
|
56
|
+
def as_builtin(self) -> Any:
|
|
57
|
+
if self.stable:
|
|
58
|
+
return self.value
|
|
59
|
+
return {"changed": self.value}
|
|
60
|
+
|
|
61
|
+
monkeypatch.setattr(plugin, "_extended_data_type", lambda: UnstableExtendedData)
|
|
62
|
+
|
|
63
|
+
with pytest.raises(AssertionError, match="expected round-trip data"):
|
|
64
|
+
plugin.assert_builtin_round_trip(UnstableExtendedData({"service": "api"}, stable=True), {"service": "api"})
|