Skip to content

Commit 1e71a2c

Browse files
author
Sylvain MARIE
committed
A few docstring edits and documentation update
1 parent 9f12605 commit 1e71a2c

File tree

3 files changed

+90
-18
lines changed

3 files changed

+90
-18
lines changed

docs/api_reference.md

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,3 +239,65 @@ Lists all desired cases for a given user query. This function may be convenient
239239
- `this_module_object`: any variable defined in the module of interest, for example a function. It is used to find "this module", when `module` contains `THIS_MODULE`.
240240
- `has_tag`: an optional tag used to filter the cases in the `module`. Only cases with the given tag will be selected.
241241
- `filter`: an optional filtering function taking as an input a list of tags associated with a case, and returning a boolean indicating if the case should be selected. It will be used to filter the cases in the `module`. It both `has_tag` and `filter` are set, both will be applied in sequence.
242+
243+
244+
## 3 - Pytest goodies
245+
246+
### `@pytest_fixture_plus`
247+
248+
`pytest_fixture_plus(scope="function", autouse=False, name=None, **kwargs)`
249+
250+
Identical to `@pytest.fixture` decorator, except that it supports multi-parametrization with `@pytest.mark.parametrize` as requested in [pytest#3960](https://github.com/pytest-dev/pytest/issues/3960).
251+
252+
As a consequence it does not support the `params` and `ids` arguments anymore.
253+
254+
### `fixture_union`
255+
256+
`fixture_union(name, fixtures, scope="function", idstyle='explicit',
257+
ids=fixture_alternative_to_str, autouse=False, **kwargs)
258+
-> <Fixture>`
259+
260+
Creates a fixture that will take all values of the provided fixtures in order. That fixture is automatically registered into the callers' module, but you may wish to assign it to a variable for convenience. In that case make sure that you use the same name, e.g. `a = fixture_union('a', ['b', 'c'])`
261+
262+
The style of test ids corresponding to the union alternatives can be changed with `idstyle`. Three values are allowed:
263+
264+
- `'explicit'` (default) favors readability,
265+
- `'compact'` adds a small mark so that at least one sees which parameters are union parameters and which others are normal parameters,
266+
- `None` does not change the ids.
267+
268+
**Parameters:**
269+
270+
- `name`: the name of the fixture to create
271+
- `fixtures`: an array-like containing fixture names and/or fixture symbols
272+
- `scope`: the scope of the union. Since the union depends on the sub-fixtures, it should be smaller than the smallest scope of fixtures referenced.
273+
- `idstyle`: The style of test ids corresponding to the union alternatives. One of `'explicit'` (default), `'compact'`, or `None`.
274+
- `ids`: as in pytest. The default value returns the correct fixture
275+
- `autouse`: as in pytest
276+
- `kwargs`: other pytest fixture options. They might not be supported correctly.
277+
278+
**Outputs:** the new fixture. Note: you do not need to capture that output in a symbol, since the fixture is automatically registered in your module. However if you decide to do so make sure that you use the same name.
279+
280+
### `param_fixtures`
281+
282+
`param_fixtures(argnames, argvalues, autouse=False, ids=None, scope="function", **kwargs)`
283+
284+
Creates one or several "parameters" fixtures - depending on the number or coma-separated names in `argnames`. The created fixtures are automatically registered into the callers' module, but you may wish to assign them to variables for convenience. In that case make sure that you use the same names, e.g. `p, q = param_fixtures('p,q', [(0, 1), (2, 3)])`.
285+
286+
287+
Note that the `(argnames, argvalues, ids)` signature is similar to `@pytest.mark.parametrize` for consistency, see https://docs.pytest.org/en/latest/reference.html?highlight=pytest.param#pytest-mark-parametrize
288+
289+
290+
### `param_fixture`
291+
292+
`param_fixture(argname, argvalues, autouse=False, ids=None, scope="function", **kwargs)`
293+
294+
Identical to `param_fixtures` but for a single parameter name, so that you can assign its output to a single variable.
295+
296+
297+
### `@pytest_parametrize_plus`
298+
299+
`pytest_parametrize_plus(argnames, argvalues, indirect=False, ids=None, scope=None, **kwargs)`
300+
301+
Equivalent to `@pytest.mark.parametrize` but also supports the fact that in argvalues one can include references to fixtures with `fixture_ref(<fixture>)` where <fixture> can be the fixture name or fixture function.
302+
303+
When such a fixture reference is detected in the argvalues, a new function-scope fixture will be created with a unique name, and the test function will be wrapped so as to be injected with the correct parameters. Special test ids will be created to illustrate the switching between normal parameters and fixtures.

docs/index.md

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@
88

99
!!! success "New `fixture_union` and `@pytest_parametrize_plus` are there, [check them out](#fixture_union) !"
1010

11+
!!! warning "Test execution order"
12+
Installing pytest-cases now has effects on the order of `pytest` tests execution, even if you do not use its features. One positive side effect is that it fixed [pytest#5054](https://github.com/pytest-dev/pytest/issues/5054). But if you see less desirable ordering please [report it](https://github.com/smarie/python-pytest-cases/issues).
13+
14+
1115
Did you ever thought that most of your test functions were actually *the same test code*, but with *different data inputs* and expected results/exceptions ?
1216

1317
`pytest-cases` leverages `pytest` and its great `@pytest.mark.parametrize` decorator, so that you can **separate your test cases from your test functions**. For example with `pytest-cases` you can now write your tests with the following pattern:
@@ -235,7 +239,7 @@ def test_uses_param2(arg1, arg2, fixture_uses_param2):
235239

236240
As of `pytest` 4, it is not possible to create a "union" fixture, i.e. a parametrized fixture that will first take all the possible values of fixture A, then all possible values of fixture B, etc.
237241

238-
The topic has been largely discussed in [pytest-dev](https://github.com/pytest-dev/pytest/issues/349) and a [request for proposal](https://docs.pytest.org/en/latest/proposals/parametrize_with_fixtures.html) has been finally made.
242+
The topic has been largely discussed in [pytest-dev#349](https://github.com/pytest-dev/pytest/issues/349) and a [request for proposal](https://docs.pytest.org/en/latest/proposals/parametrize_with_fixtures.html) has been finally made.
239243

240244
`fixture_union` is an implementation of this proposal.
241245

@@ -260,14 +264,13 @@ def test_basic_union(c):
260264
yields
261265

262266
```
263-
<...>::test_basic_union[first] hello
264-
PASSED
265-
<...>::test_basic_union[second-a] a
266-
PASSED
267-
<...>::test_basic_union[second-b] b
268-
PASSED
267+
<...>::test_basic_union[c_is_first] hello PASSED
268+
<...>::test_basic_union[c_is_second-a] a PASSED
269+
<...>::test_basic_union[c_is_second-b] b PASSED
269270
```
270271

272+
As you can see the ids of union fixtures are slightly different from standard ids, so that you can easily understand what is going on. You can change this feature with `ìdstyle`, see [API documentation](./api_reference.md#fixture_union) for details.
273+
271274
This feature has been tested in very complex cases (several union fixtures, fixtures that are not selected by a given union but that is requested by the test function, etc.). But if you find some strange behaviour don't hesitate to report it in the [issues](https://github.com/smarie/python-pytest-cases/issues) page !
272275

273276
**IMPORTANT** if you do not use `@pytest_fixture_plus` but only `@pytest.fixture`, then you will see that your fixtures are called even when they are not used, with a parameter `NOT_USED`. This symbol is automatically ignored if you use `@pytest_fixture_plus`, otherwise you have to handle it.
@@ -307,17 +310,20 @@ yields the following
307310

308311
```bash
309312
> pytest -s -v
310-
nothing?
311-
nothing!
312-
world?
313-
world!
314-
hello world?
315-
hello world!
316-
hello you?
317-
hello you!
313+
collected 9 items
314+
test_prints[test_prints_main_msg_is_0-nothing-?] nothing? PASSED
315+
test_prints[test_prints_main_msg_is_0-nothing-!] nothing! PASSED
316+
test_prints[test_prints_main_msg_is_world_str-?] world? PASSED
317+
test_prints[test_prints_main_msg_is_world_str-!] world! PASSED
318+
test_prints[test_prints_main_msg_is_greetings-greetings_who_is_world_str-?] hello world? PASSED
319+
test_prints[test_prints_main_msg_is_greetings-greetings_who_is_world_str-!] hello world! PASSED
320+
test_prints[test_prints_main_msg_is_greetings-greetings_who_is_1-you-?] hello you? PASSED
321+
test_prints[test_prints_main_msg_is_greetings-greetings_who_is_1-you-!] hello you! PASSED
318322
```
319323

320-
Note: for this to be performed, the parameters are replaced with a union fixture. Therefore the relative priority order with standard 'mark' parameters will get impacted. You may solve this by replacing your mark parameters with `param_fixture`s (see [above](#param_fixtures).)
324+
As you can see, the ids are a bit more explicit than usual. As opposed to `fixture_union`, the style of these ids is not configurable for now but feel free to propose alternatives in the [issues page](https://github.com/smarie/python-pytest-cases/issues).
325+
326+
Note: for this to be performed, the parameters are replaced with a union fixture. Therefore the relative priority order of these parameters with other standard `pytest.mark.parametrize` parameters that you would place on the same function, will get impacted. You may solve this by replacing your mark parameters with `param_fixture`s (see [above](#param_fixtures).)
321327

322328
## Main features / benefits
323329

pytest_cases/main_fixtures.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@
4545

4646
def param_fixture(argname, argvalues, autouse=False, ids=None, scope="function", **kwargs):
4747
"""
48-
Identical to `param_fixtures` but for a single parameter name.
48+
Identical to `param_fixtures` but for a single parameter name, so that you can assign its output to a single
49+
variable.
4950
5051
:param argname: see fixture `name`
5152
:param argvalues: see fixture `params`
@@ -149,7 +150,10 @@ def check_name_available(module,
149150

150151
def param_fixtures(argnames, argvalues, autouse=False, ids=None, scope="function", **kwargs):
151152
"""
152-
Creates one or several "parameters" fixtures - depending on the number or coma-separated names in `argnames`.
153+
Creates one or several "parameters" fixtures - depending on the number or coma-separated names in `argnames`. The
154+
created fixtures are automatically registered into the callers' module, but you may wish to assign them to
155+
variables for convenience. In that case make sure that you use the same names, e.g.
156+
`p, q = param_fixtures('p,q', [(0, 1), (2, 3)])`.
153157
154158
Note that the (argnames, argvalues, ids) signature is similar to `@pytest.mark.parametrize` for consistency,
155159
see https://docs.pytest.org/en/latest/reference.html?highlight=pytest.param#pytest-mark-parametrize

0 commit comments

Comments
 (0)