@@ -688,3 +688,70 @@ For example:
688
688
In the example above, the first three test cases should run without any
689
689
exceptions, while the fourth should raise a ``ZeroDivisionError `` exception,
690
690
which is expected by pytest.
691
+
692
+ .. _`parametrize_dependent` :
693
+
694
+ Adding parameters depending on previous parametrizations
695
+ --------------------------------------------------------------------
696
+
697
+ By default, :hook: `pytest_generate_tests ` hooks and
698
+ :ref: `pytest.mark.parametrize <pytest.mark.parametrize ref >` generate
699
+ a Cartesian product of parameter sets in case of multiple parametrizations,
700
+ see :ref: `parametrize-basics ` for some examples.
701
+
702
+ Sometimes, values of some parameters need to be generated based on values
703
+ of previous parameters or based on their associated marks.
704
+
705
+ In such cases ``parametrize `` can be passed a callable for ``argvalues ``,
706
+ which will decide how to further parametrize each test instance:
707
+
708
+ .. code-block :: python
709
+
710
+ # content of test_parametrize_dependent.py
711
+ def pytest_generate_tests (metafunc : pytest.Metafunc):
712
+ if " bar" in metafunc.fixturenames:
713
+ # parametrize "bar" arg based on "bar_params" mark
714
+ base_bar_marks = list (metafunc.definition.iter_markers(" bar_params" ))
715
+
716
+ def gen_params (callspec : pytest.CallSpec):
717
+ # collect all marks
718
+ bar_marks = base_bar_marks + [
719
+ mark for mark in callspec.marks if mark.name == " bar_params"
720
+ ]
721
+ # collect all args from all marks
722
+ return [arg for mark in bar_marks for arg in mark.args]
723
+
724
+ metafunc.parametrize(" bar" , gen_params)
725
+
726
+
727
+ @pytest.mark.bar_params (" x" )
728
+ @pytest.mark.parametrize (
729
+ " foo" ,
730
+ [
731
+ " a" ,
732
+ pytest.param(" b" , marks = [pytest.mark.bar_params(" y" , " z" )]),
733
+ pytest.param(" c" , marks = [pytest.mark.bar_params(" w" )]),
734
+ ],
735
+ )
736
+ def test_function (foo , bar ):
737
+ pass
738
+
739
+ Running ``pytest `` with verbose mode outputs:
740
+
741
+ .. code-block :: pytest
742
+
743
+ $ pytest -v
744
+ =========================== test session starts ============================
745
+ platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python
746
+ cachedir: .pytest_cache
747
+ rootdir: /home/sweet/project
748
+ collecting ... collected 6 items
749
+
750
+ test_parametrize_dependent.py::test_function[a-x] PASSED [ 16%]
751
+ test_parametrize_dependent.py::test_function[b-x] PASSED [ 33%]
752
+ test_parametrize_dependent.py::test_function[b-y] PASSED [ 50%]
753
+ test_parametrize_dependent.py::test_function[b-z] PASSED [ 66%]
754
+ test_parametrize_dependent.py::test_function[c-x] PASSED [ 83%]
755
+ test_parametrize_dependent.py::test_function[c-w] PASSED [100%]
756
+
757
+ ============================ 6 passed in 0.12s =============================
0 commit comments