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

Parallelize the test runs via pytest-xdist #2459

Merged
merged 15 commits into from Jan 18, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/2459.change.rst
@@ -0,0 +1 @@
Tests now run in parallel via pytest-xdist, completing in about half the time. Special thanks to :user:`webknjaz` for hard work implementing test isolation. To run without parallelization, disable the plugin with ``tox -- -p no:xdist``.
3 changes: 3 additions & 0 deletions pyproject.toml
Expand Up @@ -24,6 +24,9 @@ addopts = "--flake8"
[pytest.enabler.cov]
addopts = "--cov"

[pytest.enabler.xdist]
addopts = "-n auto"

[tool.towncrier]
package = "setuptools"
package_dir = "setuptools"
Expand Down
3 changes: 2 additions & 1 deletion setup.cfg
Expand Up @@ -47,7 +47,7 @@ testing =
pytest-black >= 0.3.7; python_implementation != "PyPy"
pytest-cov
pytest-mypy; python_implementation != "PyPy"
pytest-enabler
pytest-enabler >= 1.0.1

# local
mock
Expand All @@ -58,6 +58,7 @@ testing =
paver
pip>=19.1 # For proper file:// URLs support.
jaraco.envs
pytest-xdist

docs =
# Keep these in sync with docs/requirements.txt
Expand Down
37 changes: 37 additions & 0 deletions setuptools/tests/fixtures.py
@@ -1,3 +1,7 @@
import contextlib
import sys
import shutil

import pytest

from . import contexts
Expand All @@ -21,3 +25,36 @@ def user_override(monkeypatch):
def tmpdir_cwd(tmpdir):
with tmpdir.as_cwd() as orig:
yield orig


@pytest.fixture
def tmp_src(request, tmp_path):
"""Make a copy of the source dir under `$tmp/src`.

This fixture is useful whenever it's necessary to run `setup.py`
or `pip install` against the source directory when there's no
control over the number of simultaneous invocations. Such
concurrent runs create and delete directories with the same names
under the target directory and so they influence each other's runs
when they are not being executed sequentially.
"""
tmp_src_path = tmp_path / 'src'
shutil.copytree(request.config.rootdir, tmp_src_path)
return tmp_src_path


@pytest.fixture(autouse=True, scope="session")
def workaround_xdist_376(request):
"""
Workaround pytest-dev/pytest-xdist#376

``pytest-xdist`` tends to inject '' into ``sys.path``,
which may break certain isolation expectations.
Remove the entry so the import
machinery behaves the same irrespective of xdist.
"""
if not request.config.pluginmanager.has_plugin('xdist'):
return

with contextlib.suppress(ValueError):
sys.path.remove('')
6 changes: 3 additions & 3 deletions setuptools/tests/test_build_meta.py
Expand Up @@ -11,7 +11,7 @@


class BuildBackendBase:
def __init__(self, cwd=None, env={}, backend_name='setuptools.build_meta'):
def __init__(self, cwd='.', env={}, backend_name='setuptools.build_meta'):
self.cwd = cwd
self.env = env
self.backend_name = backend_name
Expand Down Expand Up @@ -126,7 +126,7 @@ class TestBuildMetaBackend:
backend_name = 'setuptools.build_meta'

def get_build_backend(self):
return BuildBackend(cwd='.', backend_name=self.backend_name)
return BuildBackend(backend_name=self.backend_name)

@pytest.fixture(params=defns)
def build_backend(self, tmpdir, request):
Expand Down Expand Up @@ -337,7 +337,7 @@ def test_build_sdist_builds_targz_even_if_zip_indicated(self, tmpdir_cwd):
def test_build_sdist_relative_path_import(self, tmpdir_cwd):
build_files(self._relative_path_import_files)
build_backend = self.get_build_backend()
with pytest.raises(ImportError):
with pytest.raises(ImportError, match="^No module named 'hello'$"):
build_backend.build_sdist("temp")

@pytest.mark.parametrize('setup_literal, requirements', [
Expand Down
6 changes: 3 additions & 3 deletions setuptools/tests/test_distutils_adoption.py
Expand Up @@ -21,10 +21,10 @@ def run(self, cmd, *args, **kwargs):


@pytest.fixture
def venv(tmpdir):
def venv(tmp_path, tmp_src):
env = VirtualEnv()
env.root = path.Path(tmpdir)
env.req = os.getcwd()
env.root = path.Path(tmp_path / 'venv')
env.req = str(tmp_src)
return env.create()


Expand Down
8 changes: 4 additions & 4 deletions setuptools/tests/test_virtualenv.py
Expand Up @@ -43,11 +43,11 @@ def bare_virtualenv():
SOURCE_DIR = os.path.join(os.path.dirname(__file__), '../..')


def test_clean_env_install(bare_virtualenv):
def test_clean_env_install(bare_virtualenv, tmp_src):
"""
Check setuptools can be installed in a clean environment.
"""
bare_virtualenv.run(['python', 'setup.py', 'install'], cd=SOURCE_DIR)
bare_virtualenv.run(['python', 'setup.py', 'install'], cd=tmp_src)
jaraco marked this conversation as resolved.
Show resolved Hide resolved


def _get_pip_versions():
Expand Down Expand Up @@ -85,7 +85,7 @@ def _get_pip_versions():


@pytest.mark.parametrize('pip_version', _get_pip_versions())
def test_pip_upgrade_from_source(pip_version, virtualenv):
def test_pip_upgrade_from_source(pip_version, tmp_src, virtualenv):
"""
Check pip can upgrade setuptools from source.
"""
Expand All @@ -104,7 +104,7 @@ def test_pip_upgrade_from_source(pip_version, virtualenv):
virtualenv.run(' && '.join((
'python setup.py -q sdist -d {dist}',
'python setup.py -q bdist_wheel -d {dist}',
)).format(dist=dist_dir), cd=SOURCE_DIR)
)).format(dist=dist_dir), cd=tmp_src)
sdist = glob.glob(os.path.join(dist_dir, '*.zip'))[0]
wheel = glob.glob(os.path.join(dist_dir, '*.whl'))[0]
# Then update from wheel.
Expand Down