pytest-expected-json 0.1.0__py3-none-any.whl

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.
@@ -0,0 +1,15 @@
1
+ """Pytest expected data fixture for loading test data from JSON files."""
2
+
3
+ from pytest_expected_json.fixture import (
4
+ ExpectedJsonConfig,
5
+ create_expected_json_config_fixture,
6
+ expected_data,
7
+ expected_json_config,
8
+ )
9
+
10
+ __all__ = [
11
+ "ExpectedJsonConfig",
12
+ "create_expected_json_config_fixture",
13
+ "expected_data",
14
+ "expected_json_config",
15
+ ]
@@ -0,0 +1,102 @@
1
+ """Pytest fixture for loading expected test data from JSON files."""
2
+
3
+ import json
4
+ from collections.abc import Callable
5
+ from dataclasses import dataclass
6
+ from pathlib import Path
7
+ from typing import Any, Literal, cast
8
+
9
+ import pytest
10
+
11
+ JsonType = dict[str, Any] | list[Any] | str | int | float | bool | None
12
+ FixtureScope = Literal["function", "class", "module", "package", "session"]
13
+
14
+
15
+ @dataclass
16
+ class ExpectedJsonConfig:
17
+ """Configuration for the expected_data fixture."""
18
+
19
+ assets_dir: Path = Path("assets")
20
+
21
+
22
+ def create_expected_json_config_fixture(
23
+ config: ExpectedJsonConfig | None = None, *, scope: FixtureScope = "session"
24
+ ) -> Callable[[], ExpectedJsonConfig]:
25
+ """
26
+ Create a fixture that returns config used by the expected_data fixture.
27
+
28
+ Override this fixture in a project to provide custom configuration.
29
+ """
30
+
31
+ def fixture() -> ExpectedJsonConfig:
32
+ """Provide configuration consumed by the expected_data fixture."""
33
+ return config or ExpectedJsonConfig()
34
+
35
+ decorated_fixture = pytest.fixture(scope=cast(Any, scope))(fixture)
36
+ return cast(Callable[[], ExpectedJsonConfig], decorated_fixture)
37
+
38
+
39
+ expected_json_config = create_expected_json_config_fixture()
40
+
41
+
42
+ @pytest.fixture()
43
+ def expected_data(
44
+ request: pytest.FixtureRequest, expected_json_config: ExpectedJsonConfig
45
+ ) -> JsonType:
46
+ """
47
+ Load the expected data from a JSON file based on the test location and name.
48
+
49
+ The fixture automatically constructs a filename from the test module
50
+ and function name. If a parametrized test is used, the parameter
51
+ is appended to the filename.
52
+
53
+ File naming convention:
54
+ {module_name}__{test_name}__{original_name}[@{param}].json
55
+
56
+ Example:
57
+ For test `test_health.py::test_get_health`, the fixture looks for:
58
+ tests/assets/saved/tests_app__test_health__test_get_health.json
59
+
60
+ Args:
61
+ request: Pytest request object containing test information.
62
+ expected_json_config: Fixture-provided configuration for asset lookup
63
+ and fallback behavior.
64
+
65
+ Returns:
66
+ Parsed JSON data from the file, or the configured default value
67
+ if file not found.
68
+
69
+ """
70
+ config = expected_json_config
71
+
72
+ # Build filename from node id path, flattening path segments with "__".
73
+ node_id_path = request.node.nodeid.split("::", 1)[0]
74
+ if not node_id_path.endswith(".py"):
75
+ return {}
76
+
77
+ module_path = node_id_path[:-3]
78
+ path_parts = [part for part in module_path.split("/") if part]
79
+ if path_parts and path_parts[0] == "tests":
80
+ path_parts = path_parts[1:]
81
+
82
+ if not path_parts:
83
+ return {}
84
+
85
+ test_name = request.node.originalname
86
+ file_name = "__".join([*path_parts, test_name])
87
+
88
+ # Add parametrize id if present
89
+ if hasattr(request, "param"):
90
+ file_name += f"::{request.param}"
91
+
92
+ # Get the tests directory
93
+ file_path = request.config.rootpath / config.assets_dir / f"{file_name}.json"
94
+
95
+ try:
96
+ if not file_path.exists():
97
+ raise FileNotFoundError(f"File not found: {file_path}")
98
+
99
+ with file_path.open(encoding="utf-8") as f:
100
+ return cast(JsonType, json.load(f))
101
+ except (FileNotFoundError, FileExistsError):
102
+ return {}
@@ -0,0 +1,5 @@
1
+ """Pytest plugin entry point for expected JSON fixtures."""
2
+
3
+ from pytest_expected_json.fixture import expected_data, expected_json_config
4
+
5
+ __all__ = ["expected_data", "expected_json_config"]
File without changes
@@ -0,0 +1,204 @@
1
+ Metadata-Version: 2.4
2
+ Name: pytest-expected-json
3
+ Version: 0.1.0
4
+ Summary: A reusable pytest fixture for loading expected test data from JSON files
5
+ Author: Maxime MARTIN
6
+ License: MIT
7
+ Keywords: fixture,json,pytest,testing
8
+ Classifier: Development Status :: 3 - Alpha
9
+ Classifier: Framework :: Pytest
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Programming Language :: Python :: 3.13
16
+ Classifier: Programming Language :: Python :: 3.14
17
+ Requires-Python: <3.15,>=3.11
18
+ Requires-Dist: pytest>=7.0
19
+ Description-Content-Type: text/markdown
20
+
21
+ # pytest-expected-json
22
+
23
+ A reusable pytest fixture for loading expected test data from JSON files.
24
+
25
+ ## Features
26
+
27
+ - 📋 Automatic file path resolution based on test location and name
28
+ - 🔧 Configurable assets directory and default return values
29
+ - 🎯 Support for parametrized tests
30
+ - 📦 Easy integration as a pytest plugin
31
+ - ✅ Type hints included
32
+
33
+ ## Installation
34
+
35
+ ### From local directory
36
+
37
+ ```bash
38
+ pip install -e /path/to/pytest-expected-json
39
+ ```
40
+
41
+ ### From another project
42
+
43
+ Once published, install via:
44
+
45
+ ```bash
46
+ pip install pytest-expected-json
47
+ ```
48
+
49
+ ## Usage
50
+
51
+ ### Basic Setup
52
+
53
+ The fixture automatically registers as a pytest plugin. Add it to your dependencies in `pyproject.toml`:
54
+
55
+ ```toml
56
+ dependencies = [
57
+ "pytest-expected-json>=0.1.0",
58
+ ]
59
+ ```
60
+
61
+ ### Using the Fixture
62
+
63
+ In your test files, use the `expected_data` fixture:
64
+
65
+ ```python
66
+ import pytest
67
+
68
+ def test_get_user(expected_data):
69
+ """Test with expected data."""
70
+ # expected_data will automatically load from:
71
+ # tests/assets/saved/tests_app__test_users__test_get_user.json
72
+ result = get_user(1)
73
+ assert result == expected_data
74
+ ```
75
+
76
+ ### File Naming Convention
77
+
78
+ The fixture automatically constructs filenames based on the test location:
79
+
80
+ ```
81
+ {module_name}__{test_file}__{test_name}[@{param}].json
82
+ ```
83
+
84
+ **Example:**
85
+ - Test file: `tests/tests_app/test_users.py`
86
+ - Test function: `test_get_user`
87
+ - Expected file: `tests/assets/saved/tests_app__test_users__test_get_user.json`
88
+
89
+ ### Parametrized Tests
90
+
91
+ For parametrized tests, the parameter is appended to the filename:
92
+
93
+ ```python
94
+ @pytest.mark.parametrize("expected_data", ["case1", "case2"], indirect=True)
95
+ def test_with_params(expected_data):
96
+ # Loads: tests/assets/saved/tests_app__test_users__test_with_params@case1.json
97
+ # Loads: tests/assets/saved/tests_app__test_users__test_with_params@case2.json
98
+ pass
99
+ ```
100
+
101
+ ### Configuration
102
+
103
+ You can configure the fixture behavior in your test conftest:
104
+
105
+ ```python
106
+ from pytest_expected_data.fixture import set_assets_dir, set_default_return
107
+
108
+ # Change the assets directory (default: "tests/assets/saved")
109
+ set_assets_dir("fixtures/expected_data")
110
+
111
+ # Change default return value when file not found (default: {})
112
+ set_default_return([])
113
+ ```
114
+
115
+ Or in `pytest.ini`:
116
+
117
+ ```ini
118
+ [pytest]
119
+ # Configuration via environment or conftest
120
+ ```
121
+
122
+ ## Directory Structure
123
+
124
+ Create your test expected data files:
125
+
126
+ ```
127
+ tests/
128
+ ├── assets/
129
+ │ └── saved/
130
+ │ ├── tests_app__test_users__test_get_user.json
131
+ │ ├── tests_app__test_users__test_list_users.json
132
+ │ └── tests_health__test_health__test_health_check.json
133
+ ├── tests_app/
134
+ │ └── test_users.py
135
+ ├── tests_health/
136
+ │ └── test_health.py
137
+ └── conftest.py
138
+ ```
139
+
140
+ ## Development
141
+
142
+ ### Setup Development Environment
143
+
144
+ ```bash
145
+ cd pytest-expected-json
146
+ pip install -e ".[dev]"
147
+ ```
148
+
149
+ ### Run Tests
150
+
151
+ ```bash
152
+ pytest
153
+ ```
154
+
155
+ ### Run Tests with Coverage
156
+
157
+ ```bash
158
+ pytest --cov=src/pytest_expected_data --cov-report=html
159
+ ```
160
+
161
+ ### Code Quality
162
+
163
+ ```bash
164
+ # Format code
165
+ black src tests
166
+
167
+ # Lint code
168
+ ruff check src tests
169
+ ```
170
+
171
+ ## API Reference
172
+
173
+ ### `expected_data(request: pytest.FixtureRequest) -> JsonType`
174
+
175
+ Pytest fixture that loads expected test data from a JSON file.
176
+
177
+ **Parameters:**
178
+ - `request`: Pytest fixture request object
179
+
180
+ **Returns:**
181
+ - Parsed JSON data (dict, list, str, int, float, bool, or None)
182
+ - Default empty dict `{}` if file not found (configurable)
183
+
184
+ **Raises:**
185
+ - `FileNotFoundError`: If JSON file doesn't exist (caught and returns default)
186
+ - `json.JSONDecodeError`: If JSON is invalid (caught and returns default)
187
+
188
+ ### `set_assets_dir(assets_dir: str) -> None`
189
+
190
+ Configure the directory where expected data JSON files are stored.
191
+
192
+ **Parameters:**
193
+ - `assets_dir`: Relative path from the tests directory (default: `"tests/assets/saved"`)
194
+
195
+ ### `set_default_return(default_value: JsonType) -> None`
196
+
197
+ Configure the default return value when expected data file is not found.
198
+
199
+ **Parameters:**
200
+ - `default_value`: Any JSON-serializable value (default: `{}`)
201
+
202
+ ## License
203
+
204
+ MIT
@@ -0,0 +1,8 @@
1
+ pytest_expected_json/__init__.py,sha256=h8_mdPyHVus6nuWejU1DubRlVWFT5MfMNRvxLaFCqDY,363
2
+ pytest_expected_json/fixture.py,sha256=LdOD_gdpbyME3Q-w_xy0vOg3kmjZo8EyoJzXmqwTp4U,3239
3
+ pytest_expected_json/plugin.py,sha256=2t4fcjZ0DprgzxTnKgPiXQI9KCwJcY7CXpyFV5upif4,191
4
+ pytest_expected_json/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
+ pytest_expected_json-0.1.0.dist-info/METADATA,sha256=8n7WDmtiaDGZ4cpSxeWbRUGGz7JzE5I34nnLdgqt1Q8,4780
6
+ pytest_expected_json-0.1.0.dist-info/WHEEL,sha256=mffPy8wBnZQn2VnJUU5jE99KsxaSfiyMHV9Yt0aLVxs,87
7
+ pytest_expected_json-0.1.0.dist-info/entry_points.txt,sha256=kLtf5qx310n0fzyj0ouYMAVwF-dT70uLkY-dfyAjmH0,62
8
+ pytest_expected_json-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.30.1
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,2 @@
1
+ [pytest11]
2
+ pytest_expected_json = pytest_expected_json.plugin