Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Workaround for pytest issue #3542 #346

Merged
merged 4 commits into from
Sep 12, 2018
Merged

Conversation

barnabasJ
Copy link
Contributor

@barnabasJ barnabasJ commented Jul 20, 2018

There seems to be a bug in pytest (#3542) where metafunc.parametrize breaks
fixture scope. By creating a fixture and parameterizing it indirectly
scope can be maintained

barnabasJ and others added 4 commits May 29, 2018 15:50
Implements __eq__ and __ne__ methods on teh File object.
If both objects are files, the paths are getting compared,
if the other object is a string it's compared with the path directly.
Use six to ensure python 2.x compatibility
There seems to be a bug in pytest where metafunc.parametrize breaks
fixture scope. By creating a fixture and parameterizing it indirectly
scope can be maintained
@philpep
Copy link
Contributor

philpep commented Jul 23, 2018

Hi, thanks for the PR.
I remember to dig into this issue and made some similar tests with indirect = True several years ago. But IIRC this was failing due to another issue.

Do you have some tests / example alongside your PR ?

@barnabasJ
Copy link
Contributor Author

I used this to test the workaround

test_fixtures.py:

import pytest


@pytest.fixture(scope='module', params=[1, 2])
def fixture1(request):
    print "fixture1, round: %i" % request.param
    return request.param


@pytest.fixture(scope='module', params=[1, 2])
def fixture2(fixture1,  request):
    print "fixture3, round: %i" % request.param
    return request.param + fixture1


@pytest.fixture(scope='module', params=[1, 2])
def fixture3(request):
    print "fixture4, round: %i" % request.param
    return request.param


class TestScope:

    def test_host1(self, fixture2, host):
        assert 1

    def test_host2(self, fixture3, host):
        assert 1

Output of pytest --setup-show test_fixtures.py
Without the workaround:

====================================================================================================== test session starts ======================================================================================================
platform linux2 -- Python 2.7.13, pytest-3.6.3, py-1.5.4, pluggy-0.6.0
rootdir: /home/inetser/infrastructure-tests/testinfra, inifile:
plugins: xdist-1.22.2, forked-0.2, gitignore-1.3, testinfra-1.14.0
collected 6 items

test_fixtures.py
  SETUP    M fixture1[1]
  SETUP    M fixture2 (fixtures used: fixture1)[1]
  SETUP    M _testinfra_host[<testinfra.host.Host object at 0x7fd42095ee90>]
  SETUP    M host (fixtures used: _testinfra_host)
        test_fixtures.py::TestScope::()::test_host1[1-1-local] (fixtures used: _testinfra_host, fixture1, fixture2, host).
  SETUP    M fixture3[1]
        test_fixtures.py::TestScope::()::test_host2[1-local] (fixtures used: _testinfra_host, fixture3, host).
  TEARDOWN M fixture2[1]
  SETUP    M fixture2 (fixtures used: fixture1)[2]
  TEARDOWN M host
  TEARDOWN M _testinfra_host[<testinfra.host.Host object at 0x7fd42095ee90>]
  SETUP    M _testinfra_host[<testinfra.host.Host object at 0x7fd42095ee90>]
  SETUP    M host (fixtures used: _testinfra_host)
        test_fixtures.py::TestScope::()::test_host1[2-1-local] (fixtures used: _testinfra_host, fixture1, fixture2, host).
  TEARDOWN M fixture2[2]
  TEARDOWN M fixture1[1]
  SETUP    M fixture1[2]
  SETUP    M fixture2 (fixtures used: fixture1)[2]
  TEARDOWN M host
  TEARDOWN M _testinfra_host[<testinfra.host.Host object at 0x7fd42095ee90>]
  SETUP    M _testinfra_host[<testinfra.host.Host object at 0x7fd42095ee90>]
  SETUP    M host (fixtures used: _testinfra_host)
        test_fixtures.py::TestScope::()::test_host1[2-2-local] (fixtures used: _testinfra_host, fixture1, fixture2, host).
  TEARDOWN M fixture2[2]
  SETUP    M fixture2 (fixtures used: fixture1)[1]
  TEARDOWN M host
  TEARDOWN M _testinfra_host[<testinfra.host.Host object at 0x7fd42095ee90>]
  SETUP    M _testinfra_host[<testinfra.host.Host object at 0x7fd42095ee90>]
  SETUP    M host (fixtures used: _testinfra_host)
        test_fixtures.py::TestScope::()::test_host1[1-2-local] (fixtures used: _testinfra_host, fixture1, fixture2, host).
  TEARDOWN M fixture3[1]
  SETUP    M fixture3[2]
        test_fixtures.py::TestScope::()::test_host2[2-local] (fixtures used: _testinfra_host, fixture3, host).
  TEARDOWN M host
  TEARDOWN M _testinfra_host[<testinfra.host.Host object at 0x7fd42095ee90>]
  TEARDOWN M fixture3[2]
  TEARDOWN M fixture2[1]
  TEARDOWN M fixture1[2]

=================================================================================================== 6 passed in 0.04 seconds ====================================================================================================

With the workaround:

====================================================================================================== test session starts ======================================================================================================
platform linux2 -- Python 2.7.13, pytest-3.6.3, py-1.5.4, pluggy-0.6.0
rootdir: /home/inetser/infrastructure-tests/testinfra, inifile:
plugins: xdist-1.22.2, forked-0.2, gitignore-1.3, testinfra-1.14.0
collected 6 items

test_fixtures.py
  SETUP    M fixture1[1]
  SETUP    M fixture2 (fixtures used: fixture1)[1]
  SETUP    M _testinfra_host[<testinfra.host.Host object at 0x7efd76121e50>]
  SETUP    M host (fixtures used: _testinfra_host)
        test_fixtures.py::TestScope::()::test_host1[1-1-local] (fixtures used: _testinfra_host, fixture1, fixture2, host).
  TEARDOWN M fixture2[1]
  SETUP    M fixture2 (fixtures used: fixture1)[2]
        test_fixtures.py::TestScope::()::test_host1[2-1-local] (fixtures used: _testinfra_host, fixture1, fixture2, host).
  TEARDOWN M fixture2[2]
  TEARDOWN M fixture1[1]
  SETUP    M fixture1[2]
  SETUP    M fixture2 (fixtures used: fixture1)[2]
        test_fixtures.py::TestScope::()::test_host1[2-2-local] (fixtures used: _testinfra_host, fixture1, fixture2, host).
  TEARDOWN M fixture2[2]
  SETUP    M fixture2 (fixtures used: fixture1)[1]
        test_fixtures.py::TestScope::()::test_host1[1-2-local] (fixtures used: _testinfra_host, fixture1, fixture2, host).
  SETUP    M fixture3[1]
        test_fixtures.py::TestScope::()::test_host2[1-local] (fixtures used: _testinfra_host, fixture3, host).
  TEARDOWN M fixture3[1]
  SETUP    M fixture3[2]
        test_fixtures.py::TestScope::()::test_host2[2-local] (fixtures used: _testinfra_host, fixture3, host).
  TEARDOWN M host
  TEARDOWN M _testinfra_host[<testinfra.host.Host object at 0x7efd76121e50>]
  TEARDOWN M fixture3[2]
  TEARDOWN M fixture2[1]
  TEARDOWN M fixture1[2]

=================================================================================================== 6 passed in 0.03 seconds ====================================================================================================

@philpep philpep merged commit 4de836e into pytest-dev:master Sep 12, 2018
@philpep
Copy link
Contributor

philpep commented Sep 12, 2018

Hi, sorry for having a long time before merging this. I wanted to be sure to not break something...

Here's a sample test which reproduce the issue adressed in this PR (unfortunatelly, it cannot be added to the test suite since our host fixture is override to a function scoped in test/conftest.py

import pytest

V = 0


@pytest.fixture(scope="module")
def f(host):
    global V
    V += 1
    assert V == 1


@pytest.mark.parametrize("p", ["a", "b"])
def test_foo(host, f, p):
    pass

Merged, thanks for the PR !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants