This file is indexed.

/usr/share/doc/python-pytest/html/_sources/proposals/parametrize_with_fixtures.rst.txt is in python-pytest-doc 3.3.2-2.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
:orphan:

===================================
PROPOSAL: Parametrize with fixtures
===================================

.. warning::

    This document outlines a proposal around using fixtures as input
    of parametrized tests or fixtures.

Problem
-------

As a user I have functional tests that I would like to run against various
scenarios.

In this particular example we want to generate a new project based on a
cookiecutter template. We want to test default values but also data that
emulates user input.

- use default values

- emulate user input

  - specify 'author'

  - specify 'project_slug'

  - specify 'author' and 'project_slug'

This is how a functional test could look like:

.. code-block:: python

    import pytest

    @pytest.fixture
    def default_context():
        return {'extra_context': {}}


    @pytest.fixture(params=[
        {'author': 'alice'},
        {'project_slug': 'helloworld'},
        {'author': 'bob', 'project_slug': 'foobar'},
    ])
    def extra_context(request):
        return {'extra_context': request.param}


    @pytest.fixture(params=['default', 'extra'])
    def context(request):
        if request.param == 'default':
            return request.getfuncargvalue('default_context')
        else:
            return request.getfuncargvalue('extra_context')


    def test_generate_project(cookies, context):
        """Call the cookiecutter API to generate a new project from a
        template.
        """
        result = cookies.bake(extra_context=context)

        assert result.exit_code == 0
        assert result.exception is None
        assert result.project.isdir()


Issues
------

* By using ``request.getfuncargvalue()`` we rely on actual fixture function
  execution to know what fixtures are involved, due to it's dynamic nature
* More importantly, ``request.getfuncargvalue()`` cannot be combined with
  parametrized fixtures, such as ``extra_context``
* This is very inconvenient if you wish to extend an existing test suite by
  certain parameters for fixtures that are already used by tests

pytest version 3.0 reports an error if you try to run above code::

    Failed: The requested fixture has no parameter defined for the current
    test.

    Requested fixture 'extra_context'


Proposed solution
-----------------

A new function that can be used in modules can be used to dynamically define
fixtures from existing ones.

.. code-block:: python

    pytest.define_combined_fixture(
        name='context',
        fixtures=['default_context', 'extra_context'],
    )

The new fixture ``context`` inherits the scope from the used fixtures and yield
the following values.

- ``{}``

- ``{'author': 'alice'}``

- ``{'project_slug': 'helloworld'}``

- ``{'author': 'bob', 'project_slug': 'foobar'}``

Alternative approach
--------------------

A new helper function named ``fixture_request`` would tell pytest to yield
all parameters marked as a fixture.

.. note::

    The `pytest-lazy-fixture <https://pypi.python.org/pypi/pytest-lazy-fixture>`_ plugin implements a very
    similar solution to the proposal below, make sure to check it out.

.. code-block:: python

    @pytest.fixture(params=[
        pytest.fixture_request('default_context'),
        pytest.fixture_request('extra_context'),
    ])
    def context(request):
        """Returns all values for ``default_context``, one-by-one before it
        does the same for ``extra_context``.

        request.param:
            - {}
            - {'author': 'alice'}
            - {'project_slug': 'helloworld'}
            - {'author': 'bob', 'project_slug': 'foobar'}
        """
        return request.param

The same helper can be used in combination with ``pytest.mark.parametrize``.

.. code-block:: python


    @pytest.mark.parametrize(
        'context, expected_response_code',
        [
            (pytest.fixture_request('default_context'), 0),
            (pytest.fixture_request('extra_context'), 0),
        ],
    )
    def test_generate_project(cookies, context, exit_code):
        """Call the cookiecutter API to generate a new project from a
        template.
        """
        result = cookies.bake(extra_context=context)

        assert result.exit_code == exit_code