pytest-csv-params 2.2.5__tar.gz → 2.3.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_csv_params-2.2.5 → pytest_csv_params-2.3.0}/PKG-INFO +3 -2
- {pytest_csv_params-2.2.5 → pytest_csv_params-2.3.0}/README.md +2 -1
- {pytest_csv_params-2.2.5 → pytest_csv_params-2.3.0}/_ptcsvp/exception.py +8 -0
- {pytest_csv_params-2.2.5 → pytest_csv_params-2.3.0}/_ptcsvp/parametrize.py +50 -0
- {pytest_csv_params-2.2.5 → pytest_csv_params-2.3.0}/_ptcsvp/version.py +2 -2
- {pytest_csv_params-2.2.5 → pytest_csv_params-2.3.0}/pyproject.toml +5 -3
- pytest_csv_params-2.3.0/pytest_csv_params/object.py +43 -0
- {pytest_csv_params-2.2.5 → pytest_csv_params-2.3.0}/pytest_csv_params/plugin.py +19 -7
- {pytest_csv_params-2.2.5 → pytest_csv_params-2.3.0}/pytest_csv_params/types.py +12 -0
- {pytest_csv_params-2.2.5 → pytest_csv_params-2.3.0}/.gitignore +0 -0
- {pytest_csv_params-2.2.5 → pytest_csv_params-2.3.0}/LICENSE.txt +0 -0
- {pytest_csv_params-2.2.5 → pytest_csv_params-2.3.0}/_ptcsvp/__init__.py +0 -0
- {pytest_csv_params-2.2.5 → pytest_csv_params-2.3.0}/_ptcsvp/cmdline.py +0 -0
- {pytest_csv_params-2.2.5 → pytest_csv_params-2.3.0}/_ptcsvp/configure.py +0 -0
- {pytest_csv_params-2.2.5 → pytest_csv_params-2.3.0}/_ptcsvp/plugin.py +0 -0
- {pytest_csv_params-2.2.5 → pytest_csv_params-2.3.0}/_ptcsvp/varname.py +0 -0
- {pytest_csv_params-2.2.5 → pytest_csv_params-2.3.0}/pytest_csv_params/__init__.py +0 -0
- {pytest_csv_params-2.2.5 → pytest_csv_params-2.3.0}/pytest_csv_params/decorator.py +0 -0
- {pytest_csv_params-2.2.5 → pytest_csv_params-2.3.0}/pytest_csv_params/dialect.py +0 -0
- {pytest_csv_params-2.2.5 → pytest_csv_params-2.3.0}/pytest_csv_params/exception.py +0 -0
- {pytest_csv_params-2.2.5 → pytest_csv_params-2.3.0}/pytest_csv_params/shortcut.py +0 -0
- {pytest_csv_params-2.2.5 → pytest_csv_params-2.3.0}/pytest_csv_params/warning.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: pytest-csv-params
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.3.0
|
|
4
4
|
Summary: Pytest plugin for Test Case Parametrization with CSV files
|
|
5
5
|
Project-URL: repository, https://git.codebau.dev/pytest-plugins/pytest-csv-params
|
|
6
6
|
Project-URL: homepage, https://git.codebau.dev/pytest-plugins/pytest-csv-params
|
|
@@ -107,7 +107,8 @@ Simply decorate your test method with `@csv_params` (`pytest_csv_params.decorato
|
|
|
107
107
|
| `reuse_id_col` | `bool` (optional) | Allows to re-use the ID column as test data column (since 1.3.0), defaults to `False` for backwards compatibility | `True` |
|
|
108
108
|
| `skip_when_missing_csv_file` | `bool` (optional) | When the CSV data cannot be loaded, the test will be skipped (since 2.1.0), defaults to `False` for backwards compatibility | `True` |
|
|
109
109
|
| `skip_when_empty_csv_file` | `bool` (optional) | When the CSV data file is empty, the test will be skipped (since 2.1.0), defaults to `False` for backwards compatibility | `True` |
|
|
110
|
-
| `parameters_as_dictionary` | `str` (optional) | Instead of using one method argument per column, all columns are provided in the dict named with this parameter (since 2.2.0) | `test_data` |
|
|
110
|
+
| `parameters_as_dictionary` | `str` (optional) | Instead of using one method argument per column, all columns are provided in the dict named with this parameter (since 2.2.0) | `"test_data"` |
|
|
111
|
+
| `parameters_as_object` | `str` or `(str, pytest_csv_params.object.TestCaseDataObjectFactory)` (optional) | Instead of using one method argument per column, all columns are provided as a object, either just named by `str`, or named by `str` and prepared with the given factory (since 2.3.0) | `"test_data"`, `("test_data", my_obj_factory)` |
|
|
111
112
|
|
|
112
113
|
## CSV Format
|
|
113
114
|
|
|
@@ -71,7 +71,8 @@ Simply decorate your test method with `@csv_params` (`pytest_csv_params.decorato
|
|
|
71
71
|
| `reuse_id_col` | `bool` (optional) | Allows to re-use the ID column as test data column (since 1.3.0), defaults to `False` for backwards compatibility | `True` |
|
|
72
72
|
| `skip_when_missing_csv_file` | `bool` (optional) | When the CSV data cannot be loaded, the test will be skipped (since 2.1.0), defaults to `False` for backwards compatibility | `True` |
|
|
73
73
|
| `skip_when_empty_csv_file` | `bool` (optional) | When the CSV data file is empty, the test will be skipped (since 2.1.0), defaults to `False` for backwards compatibility | `True` |
|
|
74
|
-
| `parameters_as_dictionary` | `str` (optional) | Instead of using one method argument per column, all columns are provided in the dict named with this parameter (since 2.2.0) | `test_data` |
|
|
74
|
+
| `parameters_as_dictionary` | `str` (optional) | Instead of using one method argument per column, all columns are provided in the dict named with this parameter (since 2.2.0) | `"test_data"` |
|
|
75
|
+
| `parameters_as_object` | `str` or `(str, pytest_csv_params.object.TestCaseDataObjectFactory)` (optional) | Instead of using one method argument per column, all columns are provided as a object, either just named by `str`, or named by `str` and prepared with the given factory (since 2.3.0) | `"test_data"`, `("test_data", my_obj_factory)` |
|
|
75
76
|
|
|
76
77
|
## CSV Format
|
|
77
78
|
|
|
@@ -17,3 +17,11 @@ class PytestVersionTooOldException(RuntimeError):
|
|
|
17
17
|
|
|
18
18
|
See the exception message for more details.
|
|
19
19
|
"""
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class ParametrizationConfigurationException(RuntimeError):
|
|
23
|
+
"""
|
|
24
|
+
This exception is thrown when the configuration is invalid.
|
|
25
|
+
|
|
26
|
+
See the exception message for more details.
|
|
27
|
+
"""
|
|
@@ -10,6 +10,7 @@ from warnings import warn
|
|
|
10
10
|
import pytest
|
|
11
11
|
from _pytest.mark import MarkDecorator
|
|
12
12
|
|
|
13
|
+
from _ptcsvp.exception import ParametrizationConfigurationException
|
|
13
14
|
from _ptcsvp.plugin import BASE_DIR_KEY, SKIP_EMPTY_KEY, SKIP_MISSING_KEY, Plugin
|
|
14
15
|
from _ptcsvp.varname import make_name_valid
|
|
15
16
|
from pytest_csv_params.dialect import CsvParamsDefaultDialect
|
|
@@ -19,6 +20,7 @@ from pytest_csv_params.exception import (
|
|
|
19
20
|
CsvParamsDataFileInvalid,
|
|
20
21
|
CsvParamsDataFileNotFound,
|
|
21
22
|
)
|
|
23
|
+
from pytest_csv_params.object import TestCaseDataElementObject, TestCaseDataElementType
|
|
22
24
|
from pytest_csv_params.types import (
|
|
23
25
|
BaseDir,
|
|
24
26
|
CsvDialect,
|
|
@@ -27,6 +29,7 @@ from pytest_csv_params.types import (
|
|
|
27
29
|
DictionaryName,
|
|
28
30
|
HeaderRenames,
|
|
29
31
|
IdColName,
|
|
32
|
+
ParametersObjectConfiguration,
|
|
30
33
|
SkipConfig,
|
|
31
34
|
)
|
|
32
35
|
from pytest_csv_params.warning import CsvParamsOnlyOneColumnIsUsedAsIdAndDataWarning
|
|
@@ -106,6 +109,7 @@ def add_parametrization( # pylint: disable=too-many-arguments
|
|
|
106
109
|
skip_when_missing_csv_file: SkipConfig = None,
|
|
107
110
|
skip_when_empty_csv_file: SkipConfig = None,
|
|
108
111
|
parameters_as_dictionary: DictionaryName = None,
|
|
112
|
+
parameters_as_object: ParametersObjectConfiguration = None,
|
|
109
113
|
) -> MarkDecorator:
|
|
110
114
|
"""
|
|
111
115
|
Parametrize a test function with data from a CSV file.
|
|
@@ -122,6 +126,9 @@ def add_parametrization( # pylint: disable=too-many-arguments
|
|
|
122
126
|
:param skip_when_missing_csv_file: Let tests automatically skip when CSV source is missing (since 2.1.0)
|
|
123
127
|
:param skip_when_empty_csv_file: Let tests automatically skip when CSV source does not contain any test data (since 2.1.0)
|
|
124
128
|
:param parameters_as_dictionary: Instead of using one argument per field, all arguments are passed as a dictionary with the given name (since 2.2.0)
|
|
129
|
+
:param parameters_as_object: Instead of using one argument per field, all arguments are passed as an object with the given name, or with the given name and created by the given factory (since 2.5.0)
|
|
130
|
+
|
|
131
|
+
:raises ParametersObjectConfiguration: When parameters_as_dictionary and parameters_as_object are used at the same time
|
|
125
132
|
|
|
126
133
|
:returns: :meth:`pytest.mark.parametrize` mark decorator, filled with all the data from the CSV.
|
|
127
134
|
"""
|
|
@@ -186,8 +193,26 @@ def add_parametrization( # pylint: disable=too-many-arguments
|
|
|
186
193
|
id_data = None
|
|
187
194
|
if id_col is not None:
|
|
188
195
|
id_data = [tc_data["test_id"] for tc_data in data]
|
|
196
|
+
if parameters_as_dictionary is not None and parameters_as_object is not None:
|
|
197
|
+
raise ParametrizationConfigurationException(
|
|
198
|
+
"it is not possible to use parameters_as_dictionary and parameters_as_object at the same time"
|
|
199
|
+
)
|
|
200
|
+
param_header_name = "_"
|
|
189
201
|
if parameters_as_dictionary is not None:
|
|
190
202
|
param_header_name = make_name_valid(parameters_as_dictionary)
|
|
203
|
+
elif parameters_as_object is not None:
|
|
204
|
+
if isinstance(parameters_as_object, str):
|
|
205
|
+
param_header_name = make_name_valid(parameters_as_object)
|
|
206
|
+
elif isinstance(parameters_as_object, tuple):
|
|
207
|
+
if len(parameters_as_object) != 2:
|
|
208
|
+
raise ParametrizationConfigurationException("parameters_as_object must be a tuple of length 2")
|
|
209
|
+
if isinstance(parameters_as_object[0], str):
|
|
210
|
+
param_header_name = make_name_valid(parameters_as_object[0])
|
|
211
|
+
else:
|
|
212
|
+
raise ParametrizationConfigurationException("parameters_as_object[0] must be a string")
|
|
213
|
+
else:
|
|
214
|
+
raise ParametrizationConfigurationException("parameters_as_object must be a string or a tuple")
|
|
215
|
+
if parameters_as_dictionary is not None:
|
|
191
216
|
list_of_dicts: list[dict[str, Any]] = []
|
|
192
217
|
for tc_element in [tc_data["data"] for tc_data in data]:
|
|
193
218
|
list_of_dicts.append(dict(zip(headers, tc_element)))
|
|
@@ -196,4 +221,29 @@ def add_parametrization( # pylint: disable=too-many-arguments
|
|
|
196
221
|
[pytest.param(d) for d in list_of_dicts],
|
|
197
222
|
ids=id_data,
|
|
198
223
|
)
|
|
224
|
+
elif parameters_as_object is not None:
|
|
225
|
+
object_factory = lambda: TestCaseDataElementObject()
|
|
226
|
+
if isinstance(parameters_as_object, tuple):
|
|
227
|
+
object_factory = parameters_as_object[1]
|
|
228
|
+
list_of_objects: list[TestCaseDataElementType] = []
|
|
229
|
+
for tc_element in [tc_data["data"] for tc_data in data]:
|
|
230
|
+
try:
|
|
231
|
+
tc_obj = object_factory()
|
|
232
|
+
except TypeError:
|
|
233
|
+
raise ParametrizationConfigurationException(
|
|
234
|
+
"parameters_as_object[1] must be a TestCaseDataObjectFactory"
|
|
235
|
+
)
|
|
236
|
+
for idx, element in enumerate(tc_element):
|
|
237
|
+
try:
|
|
238
|
+
tc_obj.register_value(headers[idx], element)
|
|
239
|
+
except (AttributeError, TypeError):
|
|
240
|
+
raise ParametrizationConfigurationException(
|
|
241
|
+
"parameters_as_object[1] must be a TestCaseDataObjectFactory"
|
|
242
|
+
)
|
|
243
|
+
list_of_objects.append(tc_obj)
|
|
244
|
+
return pytest.mark.parametrize(
|
|
245
|
+
param_header_name,
|
|
246
|
+
[pytest.param(o) for o in list_of_objects],
|
|
247
|
+
ids=id_data,
|
|
248
|
+
)
|
|
199
249
|
return pytest.mark.parametrize(headers, [tc_data["data"] for tc_data in data], ids=id_data)
|
|
@@ -26,7 +26,7 @@ def check_python_version(min_version: tuple[int, int] = (3, 10), deprecation_bel
|
|
|
26
26
|
raise PythonVersionTooOldException(f"At least Python {'.'.join(map(str, min_version))} required")
|
|
27
27
|
|
|
28
28
|
if sys.version_info < deprecation_below:
|
|
29
|
-
warnings.warn(f"Python {'.'.join(map(str, deprecation_below))} is deprecated", DeprecationWarning)
|
|
29
|
+
warnings.warn(f"Python <{'.'.join(map(str, deprecation_below))} is deprecated", DeprecationWarning)
|
|
30
30
|
|
|
31
31
|
|
|
32
32
|
def check_pytest_version(min_version: tuple[int, int] = (8, 3), deprecation_below: tuple[int, int] = (9, 0)) -> None:
|
|
@@ -47,4 +47,4 @@ def check_pytest_version(min_version: tuple[int, int] = (8, 3), deprecation_belo
|
|
|
47
47
|
raise PytestVersionTooOldException(f"At least Pytest {pytest_min_version} required")
|
|
48
48
|
|
|
49
49
|
if parsed_actual_version < parse(".".join(map(str, deprecation_below))):
|
|
50
|
-
warnings.warn(f"Pytest {'.'.join(map(str, deprecation_below))} is deprecated", DeprecationWarning)
|
|
50
|
+
warnings.warn(f"Pytest <{'.'.join(map(str, deprecation_below))} is deprecated", DeprecationWarning)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "pytest-csv-params"
|
|
3
|
-
version = "2.
|
|
3
|
+
version = "2.3.0"
|
|
4
4
|
description = "Pytest plugin for Test Case Parametrization with CSV files"
|
|
5
5
|
authors = [
|
|
6
6
|
{ name = "Juergen Edelbluth", email = "csv_params@jued.de" },
|
|
@@ -75,8 +75,10 @@ homepage = "https://git.codebau.dev/pytest-plugins/pytest-csv-params"
|
|
|
75
75
|
[tool.pytest.ini_options]
|
|
76
76
|
addopts = "--cov --cov-report=term-missing --cov-report=xml --junitxml=test-reports/pytest_csv_params.xml"
|
|
77
77
|
filterwarnings=[
|
|
78
|
-
"ignore
|
|
79
|
-
"ignore:
|
|
78
|
+
"ignore::_pytest.warning_types.PytestRemovedIn10Warning",
|
|
79
|
+
"ignore:Python <3.11 is deprecated",
|
|
80
|
+
"ignore:Pytest <9.0 is deprecated",
|
|
81
|
+
"ignore::pytest_csv_params.warning.CsvParamsOnlyOneColumnIsUsedAsIdAndDataWarning",
|
|
80
82
|
]
|
|
81
83
|
junit_family = "xunit2"
|
|
82
84
|
junit_logging = "all"
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This module defines the smart object as test case data object.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from collections.abc import Callable
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class TestCaseDataElementType:
|
|
10
|
+
"""
|
|
11
|
+
This class represents an abstract test case data element.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
def register_value(self, key: str, value: Any):
|
|
15
|
+
"""
|
|
16
|
+
This method registers a value for a given key and is called by the csv_params plugin in order to populate the
|
|
17
|
+
test case data object.
|
|
18
|
+
"""
|
|
19
|
+
raise NotImplementedError("register_value is not implemented")
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class TestCaseDataElementObject(TestCaseDataElementType):
|
|
23
|
+
"""
|
|
24
|
+
This class represents a test case data element.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
def register_value(self, key: str, value: Any):
|
|
28
|
+
"""
|
|
29
|
+
Simply add the value as an attribute to the instance.
|
|
30
|
+
"""
|
|
31
|
+
setattr(self, key, value)
|
|
32
|
+
|
|
33
|
+
def __getattribute__(self, name: str, /) -> Any:
|
|
34
|
+
return object.__getattribute__(self, name)
|
|
35
|
+
|
|
36
|
+
def __getattr__(self, name: str) -> None:
|
|
37
|
+
raise AttributeError(f"Attribute '{name}' not found")
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
TestCaseDataObjectFactory = Callable[[], TestCaseDataElementType]
|
|
41
|
+
"""
|
|
42
|
+
This is how a factory function has to look like to build a test case data object.
|
|
43
|
+
"""
|
|
@@ -4,20 +4,32 @@ This module contains all the code to initialize the pytest plugin. This is the e
|
|
|
4
4
|
`pyproject.toml` as `pytest11`.
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
|
+
from _pytest.config import Config
|
|
8
|
+
|
|
7
9
|
from _ptcsvp.cmdline import pytest_addoption as _pytest_addoption
|
|
8
10
|
from _ptcsvp.configure import pytest_configure as _pytest_configure
|
|
9
11
|
from _ptcsvp.configure import pytest_unconfigure as _pytest_unconfigure
|
|
10
12
|
from _ptcsvp.version import check_pytest_version, check_python_version
|
|
11
13
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
14
|
+
|
|
15
|
+
# First at all, check if the python & pytest version matches
|
|
16
|
+
def version_check():
|
|
17
|
+
"""
|
|
18
|
+
Check if the python & pytest version matches the required versions
|
|
19
|
+
"""
|
|
20
|
+
check_python_version()
|
|
21
|
+
check_pytest_version()
|
|
22
|
+
|
|
15
23
|
|
|
16
24
|
# Basic config
|
|
17
|
-
pytest_configure =
|
|
18
|
-
"""
|
|
19
|
-
Hook our :meth:`_ptcsvp.configure.pytest_configure` method to setup the plugin setup
|
|
20
|
-
|
|
25
|
+
def pytest_configure(config: Config, plugin_name: str = "csv_params"):
|
|
26
|
+
"""
|
|
27
|
+
Hook our :meth:`_ptcsvp.configure.pytest_configure` method to setup the plugin setup,
|
|
28
|
+
after executing version checks.
|
|
29
|
+
"""
|
|
30
|
+
version_check()
|
|
31
|
+
_pytest_configure(config, plugin_name)
|
|
32
|
+
|
|
21
33
|
|
|
22
34
|
pytest_unconfigure = _pytest_unconfigure
|
|
23
35
|
"""
|
|
@@ -8,6 +8,8 @@ import csv
|
|
|
8
8
|
from collections.abc import Callable
|
|
9
9
|
from typing import Any
|
|
10
10
|
|
|
11
|
+
from pytest_csv_params.object import TestCaseDataObjectFactory
|
|
12
|
+
|
|
11
13
|
DataCast = Callable[[str], Any]
|
|
12
14
|
"""
|
|
13
15
|
A :class:`DataCast` describes how a data casting callable must be implemented. It requires one parameter of the type
|
|
@@ -77,3 +79,13 @@ DictionaryName = str | None
|
|
|
77
79
|
The :class:`DictionaryName` describes the type of the `parameters_as_dictionary` parameter of the
|
|
78
80
|
:meth:`~pytest_csv_params.decorator.csv_params` decorator. It is just an optional :class:`str`.
|
|
79
81
|
"""
|
|
82
|
+
|
|
83
|
+
ParametersObjectConfiguration = str | tuple[str, TestCaseDataObjectFactory] | None
|
|
84
|
+
"""
|
|
85
|
+
The :class:`ParametersObjectConfiguration` describes the type of the `parameters_as_object` parameter of the
|
|
86
|
+
:meth:`~pytest_csv_params.decorator.csv_params` decorator.
|
|
87
|
+
|
|
88
|
+
- It can be either a :class:`str` which describes only the parameter name.
|
|
89
|
+
- It can be a :class:`tuple` of :class:`str` and :class:`TestCaseDataObjectFactory` to describe the name and the factory.
|
|
90
|
+
- Default is :obj:`None`, to disable the feature.
|
|
91
|
+
"""
|
|
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
|