Skip to content

Fixture parametrization overwrite each other. #4948

Closed

Description

@lexa
  • Include a detailed description of the bug or suggestion

I'm trying to parametrize a fixture using pytest_generate_tests(), with one
caveat: parametrization is different for each test function and depends on the
function name. I want a fixture to have a different value for different
test-cases.

When metafunc.parametrize('fixture_name', ...) is called with different
arguments, it somehow overwrites global parametrization for 'fixture_name', not
a per test-function parametrization.

  • pip list of the virtual environment you are using
Details
Package                       Version               
----------------------------- ----------------------
appdirs                       1.4.3                 
apturl                        0.5.2                 
asn1crypto                    0.24.0                
atomicwrites                  1.3.0                 
attrs                         18.2.0                
autobahn                      19.2.1                
Automat                       0.7.0                 
backports.ssl                 0.0.9                 
beautifulsoup4                4.4.1                 
blinker                       1.3                   
Brlapi                        0.6.4                 
buildbot                      2.0.1                 
buildbot-console-view         2.0.1                 
buildbot-grid-view            2.0.1                 
buildbot-waterfall-view       2.0.1                 
buildbot-worker               2.0.1                 
buildbot-www                  2.0.1                 
cffi                          1.11.2                
chardet                       2.3.0                 
checkbox-support              0.22                  
chrome-gnome-shell            0.0.0                 
click                         6.7                   
colorama                      0.3.9                 
command-not-found             0.3                   
constantly                    15.1.0                
cryptography                  2.1.4                 
decorator                     4.0.6                 
defer                         1.0.6                 
feedparser                    5.1.3                 
future                        0.17.1                
guacamole                     0.9.2                 
html5lib                      0.999                 
httplib2                      0.9.1                 
hyperlink                     18.0.0                
idna                          2.6                   
ifaddr                        0.1.6                 
IMAPClient                    1.1.0                 
incremental                   17.5.0                
ipython                       2.4.1                 
Jinja2                        2.8                   
junitxml                      0.6                   
language-selector             0.1                   
libtmux                       0.7.7                 
louis                         2.6.4                 
lxml                          3.5.0                 
mailsync                      1.0                   
Mako                          1.0.3                 
MarkupSafe                    0.23                  
more-itertools                6.0.0                 
oauthlib                      1.0.3                 
onboard                       1.2.0                 
padme                         1.1.1                 
pathlib2                      2.3.3                 
pbr                           5.1.2                 
pexpect                       4.0.1                 
Pillow                        3.1.2                 
pip                           19.0.3                
plainbox                      0.25                  
pluggy                        0.9.0                 
ply                           3.11                  
ptyprocess                    0.5                   
py                            1.8.0                 
pyasn1                        0.1.9                 
pyasn1-modules                0.2.4                 
pycparser                     2.18                  
pycups                        1.9.73                
pycurl                        7.43.0                
pygobject                     3.20.0                
PyHamcrest                    1.9.0                 
PyJWT                         1.3.0                 
pyOpenSSL                     17.5.0                
pyparsing                     2.0.3                 
pytest                        4.3.1                 
python-apt                    1.1.0b1+ubuntu0.16.4.2
python-dateutil               2.8.0                 
python-debian                 0.1.27                
python-systemd                231                   
pyxdg                         0.25                  
PyYAML                        3.12                  
reportlab                     3.3.0                 
requests                      2.9.1                 
service-identity              18.1.0                
sessioninstaller              0.0.0                 
setuptools                    20.7.0                
simplegeneric                 0.8.1                 
six                           1.11.0                
SQLAlchemy                    1.2.18                
sqlalchemy-migrate            0.12.0                
sqlparse                      0.2.4                 
ssh-import-id                 5.5                   
system-service                0.3                   
Tempita                       0.5.2                 
thriftpy                      0.3.9                 
Twisted                       18.9.0                
txaio                         18.8.1                
ubuntu-drivers-common         0.0.0                 
ufw                           0.35                  
unattended-upgrades           0.1                   
unity-scope-calculator        0.1                   
unity-scope-chromiumbookmarks 0.1                   
unity-scope-colourlovers      0.1                   
unity-scope-devhelp           0.1                   
unity-scope-firefoxbookmarks  0.1                   
unity-scope-gdrive            0.7                   
unity-scope-manpages          0.1                   
unity-scope-openclipart       0.1                   
unity-scope-texdoc            0.1                   
unity-scope-tomboy            0.1                   
unity-scope-virtualbox        0.1                   
unity-scope-yelp              0.1                   
unity-scope-zotero            0.1                   
urllib3                       1.13.1                
usb-creator                   0.3.0                 
vboxapi                       1.0                   
wheel                         0.29.0                
xdiagnose                     3.8.4.1               
xkit                          0.0.0                 
XlsxWriter                    0.7.3                 
zeroconf                      0.21.3                
zope.interface                4.6.0               
  • pytest and operating system versions
    $ pytest --version
    This is pytest version 4.3.1

    $ lsb_release -a
    No LSB modules are available.
    Distributor ID: Ubuntu
    Description: Ubuntu 16.04.6 LTS
    Release: 16.04
    Codename: xenial
    `

  • Minimal example if possible

test.py:

    def test_one(heavy_fixture):
        assert heavy_fixture == 'A'
    
    def test_two(heavy_fixture):
        assert heavy_fixture == 'B'
conftest.py:

    import pytest
    
    def pytest_generate_tests(metafunc):
        if metafunc.function.__name__ == 'test_one':
            params = ['A']
        else:
            params = ['B']
    
        metafunc.parametrize('heavy_fixture', params, scope="session", indirect=True)
    
    @pytest.fixture
    def heavy_fixture(request):
        # Do a lot of heavy computation here
        return request.param

results:

    $ pytest  test.py  
    ============================================================================ test session starts =============================================================================
    platform linux -- Python 3.5.2, pytest-4.3.1, py-1.8.0, pluggy-0.9.0
    rootdir: /home/afe/pytest3_fail, inifile:
    collected 2 items                                                                                                                                                            
    
    test.py .F                                                                                                                                                             [100%]
    
    ================================================================================== FAILURES ==================================================================================
    ________________________________________________________________________________ test_two[B] _________________________________________________________________________________
    
    heavy_fixture = 'A'
    
        def test_two(heavy_fixture):
    >       assert heavy_fixture == 'B'
    E       AssertionError: assert 'A' == 'B'
    E         - A
    E         + B
    
    test.py:5: AssertionError
    ===================================================================== 1 failed, 1 passed in 0.02 seconds =====================================================================

Activity

  1. changed the title [-]Fixtu[/-] [+]Fixture parametrization overwrite each other.[/+] on Mar 18, 2019
  2. HunterMcGushion commented on Mar 20, 2019

    @HunterMcGushion

    Hi, I may be misunderstanding what you're saying here

    When metafunc.parametrize('fixture_name', ...) is called with different
    arguments, it somehow overwrites global parametrization for 'fixture_name', not
    a per test-function parametrization.

    However, is there a reason you can't use scope="function" in the conftest.pytest_generate_tests function's call to metafunc.parameterize?

    Here's the updated conftest.py, which makes your tests pass:

    def pytest_generate_tests(metafunc):
        if metafunc.function.__name__ == 'test_one':
            params = ['A']
        else:
            params = ['B']
    
        # Below line was changed
        metafunc.parametrize('heavy_fixture', params, scope="function", indirect=True)
    
    
    @pytest.fixture
    def heavy_fixture(request):
        # Do a lot of heavy computation here
        return request.param
  3. lexa commented on Mar 20, 2019

    @lexa
    Author

    However, is there a reason you can't use scope="function" in the conftest.pytest_generate_tests function's call to metafunc.parameterize?

    The reason to use score="session" is that the fixture is very computationally heavy and I want to minimize the number of times it is called.

    in the example below the fixture is called 4 times, while it is enough to call it only twice with scope="session"

    def pytest_generate_tests(metafunc):
        params = ['A', 'B']
        metafunc.parametrize('heavy_fixture', params, scope="function", indirect=True)
    
  4. added
    topic: fixturesanything involving fixtures directly or indirectly
    on Apr 6, 2019
  5. bluetech commented on Sep 12, 2020

    @bluetech
    Member

    This has been fixed by @aklajnert in #5798 (pytest 5.1.2).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    topic: fixturesanything involving fixtures directly or indirectlytopic: parametrizerelated to @pytest.mark.parametrize

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions