Merge pull request #3861 from jonozzz/fix-3854

Fix #3854
This commit is contained in:
Bruno Oliveira 2018-08-25 10:44:08 -03:00 committed by GitHub
commit be4b359c74
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 123 additions and 6 deletions

View File

@ -0,0 +1,2 @@
Fixed an issue where teardown of fixtures of consecutive sub-packages were executed once, at the end of the outer
package.

View File

@ -0,0 +1 @@
Fixes double collection of tests within packages when the filename starts with a capital letter.

View File

@ -2,7 +2,6 @@ from __future__ import absolute_import, division, print_function
import functools import functools
import inspect import inspect
import os
import sys import sys
import warnings import warnings
from collections import OrderedDict, deque, defaultdict from collections import OrderedDict, deque, defaultdict
@ -93,7 +92,7 @@ def get_scope_package(node, fixturedef):
cls = pytest.Package cls = pytest.Package
current = node current = node
fixture_package_name = os.path.join(fixturedef.baseid, "__init__.py") fixture_package_name = "%s/%s" % (fixturedef.baseid, "__init__.py")
while current and ( while current and (
type(current) is not cls or fixture_package_name != current.nodeid type(current) is not cls or fixture_package_name != current.nodeid
): ):

View File

@ -590,17 +590,28 @@ class Package(Module):
self.session.config.pluginmanager._duplicatepaths.remove(path) self.session.config.pluginmanager._duplicatepaths.remove(path)
this_path = self.fspath.dirpath() this_path = self.fspath.dirpath()
pkg_prefix = None pkg_prefixes = set()
for path in this_path.visit(rec=self._recurse, bf=True, sort=True): for path in this_path.visit(rec=self._recurse, bf=True, sort=True):
# we will visit our own __init__.py file, in which case we skip it # we will visit our own __init__.py file, in which case we skip it
skip = False
if path.basename == "__init__.py" and path.dirpath() == this_path: if path.basename == "__init__.py" and path.dirpath() == this_path:
continue continue
if pkg_prefix and pkg_prefix in path.parts():
for pkg_prefix in pkg_prefixes:
if (
pkg_prefix in path.parts()
and pkg_prefix.join("__init__.py") != path
):
skip = True
if skip:
continue continue
if path.isdir() and path.join("__init__.py").check(file=1):
pkg_prefixes.add(path)
for x in self._collectfile(path): for x in self._collectfile(path):
yield x yield x
if isinstance(x, Package):
pkg_prefix = path.dirpath()
def _get_xunit_setup_teardown(holder, attr_name, param_obj=None): def _get_xunit_setup_teardown(holder, attr_name, param_obj=None):

View File

@ -1624,3 +1624,38 @@ def test_package_with_modules(testdir):
root.chdir() root.chdir()
result = testdir.runpytest("-v", "-s") result = testdir.runpytest("-v", "-s")
result.assert_outcomes(passed=2) result.assert_outcomes(passed=2)
def test_package_ordering(testdir):
"""
.
root
Test_root.py
__init__.py
sub1
Test_sub1.py
__init__.py
sub2
test
test_sub2.py
"""
testdir.makeini(
"""
[pytest]
python_files=*.py
"""
)
root = testdir.mkpydir("root")
sub1 = root.mkdir("sub1")
sub1.ensure("__init__.py")
sub2 = root.mkdir("sub2")
sub2_test = sub2.mkdir("sub2")
root.join("Test_root.py").write("def test_1(): pass")
sub1.join("Test_sub1.py").write("def test_2(): pass")
sub2_test.join("test_sub2.py").write("def test_3(): pass")
# Execute from .
result = testdir.runpytest("-v", "-s")
result.assert_outcomes(passed=3)

View File

@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-
import textwrap import textwrap
import pytest import pytest
@ -3977,3 +3978,71 @@ class TestScopeOrdering(object):
items, _ = testdir.inline_genitems() items, _ = testdir.inline_genitems()
request = FixtureRequest(items[0]) request = FixtureRequest(items[0])
assert request.fixturenames == "s1 p1 m1 m2 c1 f2 f1".split() assert request.fixturenames == "s1 p1 m1 m2 c1 f2 f1".split()
def test_multiple_packages(self, testdir):
"""Complex test involving multiple package fixtures. Make sure teardowns
are executed in order.
.
root
__init__.py
sub1
__init__.py
conftest.py
test_1.py
sub2
__init__.py
conftest.py
test_2.py
"""
root = testdir.mkdir("root")
root.join("__init__.py").write("values = []")
sub1 = root.mkdir("sub1")
sub1.ensure("__init__.py")
sub1.join("conftest.py").write(
textwrap.dedent(
"""\
import pytest
from .. import values
@pytest.fixture(scope="package")
def fix():
values.append("pre-sub1")
yield values
assert values.pop() == "pre-sub1"
"""
)
)
sub1.join("test_1.py").write(
textwrap.dedent(
"""\
from .. import values
def test_1(fix):
assert values == ["pre-sub1"]
"""
)
)
sub2 = root.mkdir("sub2")
sub2.ensure("__init__.py")
sub2.join("conftest.py").write(
textwrap.dedent(
"""\
import pytest
from .. import values
@pytest.fixture(scope="package")
def fix():
values.append("pre-sub2")
yield values
assert values.pop() == "pre-sub2"
"""
)
)
sub2.join("test_2.py").write(
textwrap.dedent(
"""\
from .. import values
def test_2(fix):
assert values == ["pre-sub2"]
"""
)
)
reprec = testdir.inline_run()
reprec.assertoutcome(passed=2)