Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6ec967a3f2 | ||
|
|
0722ea12ef | ||
|
|
bb91f5459d | ||
|
|
00b7c4553a | ||
|
|
9ff6fc10d0 | ||
|
|
a06e75cc78 | ||
|
|
04882074e1 | ||
|
|
06593498cd | ||
|
|
57d09c2622 | ||
|
|
663bbd5338 | ||
|
|
137b939a27 | ||
|
|
17f6257a24 | ||
|
|
78fcf725cf | ||
|
|
8d94fca964 | ||
|
|
b06c52a5d2 | ||
|
|
fd2e8a6711 | ||
|
|
98ae25c12c | ||
|
|
182d1f6433 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -30,5 +30,6 @@ issue/
|
|||||||
pytestdebug.log
|
pytestdebug.log
|
||||||
.tox/
|
.tox/
|
||||||
.cache/
|
.cache/
|
||||||
|
.pytest_cache/
|
||||||
.eggs/
|
.eggs/
|
||||||
.idea/
|
.idea/
|
||||||
|
|||||||
@@ -25,6 +25,11 @@ env:
|
|||||||
install: pip install tox setuptools_scm
|
install: pip install tox setuptools_scm
|
||||||
script: tox
|
script: tox
|
||||||
|
|
||||||
|
stages:
|
||||||
|
- test
|
||||||
|
- name: deploy
|
||||||
|
if: repo = pytest-dev/pytest-xdist AND tag IS present
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
include:
|
include:
|
||||||
- stage: test
|
- stage: test
|
||||||
@@ -50,7 +55,7 @@ jobs:
|
|||||||
deploy:
|
deploy:
|
||||||
provider: pypi
|
provider: pypi
|
||||||
user: ronny
|
user: ronny
|
||||||
distributions: sdist bdist_wheel
|
distributions: sdist bdist_wheel
|
||||||
skip_upload_docs: true
|
skip_upload_docs: true
|
||||||
password:
|
password:
|
||||||
secure: cxmSDho5d+PYKEM4ZCg8ms1P4lzhYkrw6fEOm2HtTcsuCyY6aZMSgImWAnEYbJHSkdzgcxlXK9UKJ9B0YenXmBCkAr7UjdnpNXNmkySr0sYzlH/sfqt/dDATCHFaRKxnkOSOVywaDYhT9n8YudbXI77pXwD12i/CeSSJDbHhsu0JYUfAcb+D6YjRYoA2SEGCnzSzg+gDDfwXZx4ZiODCGLVwieNp1klCg88YROUE1BaYYNuUOONvfXX8+TWowbCF6ChH1WL/bZ49OStEYQNuYxZQZr4yClIqu9VJbchrU8j860K9ott2kkGTgfB/dDrQB/XncBubyIX9ikzCQAmmBXWAI3eyvWLPDk2Jz7kW2l2RT7syct80tCq3JhvQ1qdwr5ap7siocTLgnBW0tF4tkHSTFN3510fkc43npnp6FThebESQpnI24vqpwJ9hI/kW5mYi014Og2E/cpCXnz2XO8iZPDbqAMQpDsqEQoyhfGNgPTGp4K30TxRtwZBI5hHhDKnnR16fXtRgt1gYPvz/peUQvvpOm4JzIzGXPzluuutpnCBy75v5+oiwT3YRrLL/Meims9FtDDXL3qQubAE/ezIOOpm0N5XXV8DxIom8EN71yq5ab1tqhM+tBX7owRjy4FR4If2Q8feBdmTuh26DIQt/y+qSG8VkB9Sw/JCjc7c=
|
secure: cxmSDho5d+PYKEM4ZCg8ms1P4lzhYkrw6fEOm2HtTcsuCyY6aZMSgImWAnEYbJHSkdzgcxlXK9UKJ9B0YenXmBCkAr7UjdnpNXNmkySr0sYzlH/sfqt/dDATCHFaRKxnkOSOVywaDYhT9n8YudbXI77pXwD12i/CeSSJDbHhsu0JYUfAcb+D6YjRYoA2SEGCnzSzg+gDDfwXZx4ZiODCGLVwieNp1klCg88YROUE1BaYYNuUOONvfXX8+TWowbCF6ChH1WL/bZ49OStEYQNuYxZQZr4yClIqu9VJbchrU8j860K9ott2kkGTgfB/dDrQB/XncBubyIX9ikzCQAmmBXWAI3eyvWLPDk2Jz7kW2l2RT7syct80tCq3JhvQ1qdwr5ap7siocTLgnBW0tF4tkHSTFN3510fkc43npnp6FThebESQpnI24vqpwJ9hI/kW5mYi014Og2E/cpCXnz2XO8iZPDbqAMQpDsqEQoyhfGNgPTGp4K30TxRtwZBI5hHhDKnnR16fXtRgt1gYPvz/peUQvvpOm4JzIzGXPzluuutpnCBy75v5+oiwT3YRrLL/Meims9FtDDXL3qQubAE/ezIOOpm0N5XXV8DxIom8EN71yq5ab1tqhM+tBX7owRjy4FR4If2Q8feBdmTuh26DIQt/y+qSG8VkB9Sw/JCjc7c=
|
||||||
|
|||||||
@@ -1,3 +1,18 @@
|
|||||||
|
pytest-xdist 1.22.3 (2018-07-23)
|
||||||
|
================================
|
||||||
|
|
||||||
|
Bug Fixes
|
||||||
|
---------
|
||||||
|
|
||||||
|
- Fix issue of virtualized or containerized environments not reporting the number of CPUs correctly. (`#9 <https://github.com/pytest-dev/pytest-xdist/issues/9>`_)
|
||||||
|
|
||||||
|
|
||||||
|
Trivial Changes
|
||||||
|
---------------
|
||||||
|
|
||||||
|
- Make all classes subclass from ``object`` and fix ``super()`` call in ``LoadFileScheduling``; (`#297 <https://github.com/pytest-dev/pytest-xdist/issues/297>`_)
|
||||||
|
|
||||||
|
|
||||||
pytest-xdist 1.22.2 (2018-02-26)
|
pytest-xdist 1.22.2 (2018-02-26)
|
||||||
================================
|
================================
|
||||||
|
|
||||||
|
|||||||
@@ -24,13 +24,13 @@ To publish a new release ``X.Y.Z``, the steps are as follows:
|
|||||||
|
|
||||||
#. Create a new branch named ``release-X.Y.Z`` from the latest ``master``.
|
#. Create a new branch named ``release-X.Y.Z`` from the latest ``master``.
|
||||||
|
|
||||||
#. Install ``pytest-xdist`` and dev requirements in a virtualenv::
|
#. Install ``tox`` in a virtualenv::
|
||||||
|
|
||||||
$ pip install -e . -U -r dev-requirements.txt
|
$ pip install tox
|
||||||
|
|
||||||
#. Update ``CHANGELOG.rst`` file by running::
|
#. Update the necessary files with::
|
||||||
|
|
||||||
$ towncrier --version X.Y.Z --yes
|
$ tox -e release -- X.Y.Z
|
||||||
|
|
||||||
#. Commit and push the branch for review.
|
#. Commit and push the branch for review.
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ tag: feature
|
|||||||
|
|
||||||
allow to run xdist own tests using its own mechanism.
|
allow to run xdist own tests using its own mechanism.
|
||||||
currently this doesn't work because the remote side
|
currently this doesn't work because the remote side
|
||||||
has no py.test plugin. How to configure/do
|
has no pytest plugin. How to configure/do
|
||||||
register "xdist.plugin" on the remote side?
|
register "xdist.plugin" on the remote side?
|
||||||
|
|
||||||
see to avoid any "from _pytest" internal imports
|
see to avoid any "from _pytest" internal imports
|
||||||
|
|||||||
24
README.rst
24
README.rst
@@ -23,7 +23,7 @@
|
|||||||
xdist: pytest distributed testing plugin
|
xdist: pytest distributed testing plugin
|
||||||
========================================
|
========================================
|
||||||
|
|
||||||
The `pytest-xdist`_ plugin extends py.test with some unique
|
The `pytest-xdist`_ plugin extends pytest with some unique
|
||||||
test execution modes:
|
test execution modes:
|
||||||
|
|
||||||
* test run parallelization_: if you have multiple CPUs or hosts you can use
|
* test run parallelization_: if you have multiple CPUs or hosts you can use
|
||||||
@@ -32,14 +32,14 @@ test execution modes:
|
|||||||
|
|
||||||
|
|
||||||
* ``--looponfail``: run your tests repeatedly in a subprocess. After each run
|
* ``--looponfail``: run your tests repeatedly in a subprocess. After each run
|
||||||
py.test waits until a file in your project changes and then re-runs
|
pytest waits until a file in your project changes and then re-runs
|
||||||
the previously failing tests. This is repeated until all tests pass
|
the previously failing tests. This is repeated until all tests pass
|
||||||
after which again a full run is performed.
|
after which again a full run is performed.
|
||||||
|
|
||||||
* `Multi-Platform`_ coverage: you can specify different Python interpreters
|
* `Multi-Platform`_ coverage: you can specify different Python interpreters
|
||||||
or different platforms and run tests in parallel on all of them.
|
or different platforms and run tests in parallel on all of them.
|
||||||
|
|
||||||
Before running tests remotely, ``py.test`` efficiently "rsyncs" your
|
Before running tests remotely, ``pytest`` efficiently "rsyncs" your
|
||||||
program source code to the remote place. All test results
|
program source code to the remote place. All test results
|
||||||
are reported back and displayed to your local terminal.
|
are reported back and displayed to your local terminal.
|
||||||
You may specify different Python versions and interpreters.
|
You may specify different Python versions and interpreters.
|
||||||
@@ -67,7 +67,7 @@ Speed up test runs by sending tests to multiple CPUs
|
|||||||
|
|
||||||
To send tests to multiple CPUs, type::
|
To send tests to multiple CPUs, type::
|
||||||
|
|
||||||
py.test -n NUM
|
pytest -n NUM
|
||||||
|
|
||||||
Especially for longer running tests or tests requiring
|
Especially for longer running tests or tests requiring
|
||||||
a lot of I/O this can lead to considerable speed ups. This option can
|
a lot of I/O this can lead to considerable speed ups. This option can
|
||||||
@@ -98,7 +98,7 @@ Running tests in a Python subprocess
|
|||||||
|
|
||||||
To instantiate a python3.5 subprocess and send tests to it, you may type::
|
To instantiate a python3.5 subprocess and send tests to it, you may type::
|
||||||
|
|
||||||
py.test -d --tx popen//python=python3.5
|
pytest -d --tx popen//python=python3.5
|
||||||
|
|
||||||
This will start a subprocess which is run with the ``python3.5``
|
This will start a subprocess which is run with the ``python3.5``
|
||||||
Python interpreter, found in your system binary lookup path.
|
Python interpreter, found in your system binary lookup path.
|
||||||
@@ -129,10 +129,10 @@ tests that you can successfully run locally. And you
|
|||||||
have a ssh-reachable machine ``myhost``. Then
|
have a ssh-reachable machine ``myhost``. Then
|
||||||
you can ad-hoc distribute your tests by typing::
|
you can ad-hoc distribute your tests by typing::
|
||||||
|
|
||||||
py.test -d --tx ssh=myhostpopen --rsyncdir mypkg mypkg
|
pytest -d --tx ssh=myhostpopen --rsyncdir mypkg mypkg
|
||||||
|
|
||||||
This will synchronize your :code:`mypkg` package directory
|
This will synchronize your :code:`mypkg` package directory
|
||||||
to an remote ssh account and then locally collect tests
|
to a remote ssh account and then locally collect tests
|
||||||
and send them to remote places for execution.
|
and send them to remote places for execution.
|
||||||
|
|
||||||
You can specify multiple :code:`--rsyncdir` directories
|
You can specify multiple :code:`--rsyncdir` directories
|
||||||
@@ -140,11 +140,11 @@ to be sent to the remote side.
|
|||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
For py.test to collect and send tests correctly
|
For pytest to collect and send tests correctly
|
||||||
you not only need to make sure all code and tests
|
you not only need to make sure all code and tests
|
||||||
directories are rsynced, but that any test (sub) directory
|
directories are rsynced, but that any test (sub) directory
|
||||||
also has an :code:`__init__.py` file because internally
|
also has an :code:`__init__.py` file because internally
|
||||||
py.test references tests as a fully qualified python
|
pytest references tests as a fully qualified python
|
||||||
module path. **You will otherwise get strange errors**
|
module path. **You will otherwise get strange errors**
|
||||||
during setup of the remote side.
|
during setup of the remote side.
|
||||||
|
|
||||||
@@ -168,7 +168,7 @@ It will tell you that it starts listening on the default
|
|||||||
port. You can now on your home machine specify this
|
port. You can now on your home machine specify this
|
||||||
new socket host with something like this::
|
new socket host with something like this::
|
||||||
|
|
||||||
py.test -d --tx socket=192.168.1.102:8888 --rsyncdir mypkg mypkg
|
pytest -d --tx socket=192.168.1.102:8888 --rsyncdir mypkg mypkg
|
||||||
|
|
||||||
|
|
||||||
.. _`atonce`:
|
.. _`atonce`:
|
||||||
@@ -180,7 +180,7 @@ Running tests on many platforms at once
|
|||||||
|
|
||||||
The basic command to run tests on multiple platforms is::
|
The basic command to run tests on multiple platforms is::
|
||||||
|
|
||||||
py.test --dist=each --tx=spec1 --tx=spec2
|
pytest --dist=each --tx=spec1 --tx=spec2
|
||||||
|
|
||||||
If you specify a windows host, an OSX host and a Linux
|
If you specify a windows host, an OSX host and a Linux
|
||||||
environment this command will send each tests to all
|
environment this command will send each tests to all
|
||||||
@@ -242,7 +242,7 @@ You can also add default environments like this:
|
|||||||
|
|
||||||
and then just type::
|
and then just type::
|
||||||
|
|
||||||
py.test --dist=each
|
pytest --dist=each
|
||||||
|
|
||||||
to run tests in each of the environments.
|
to run tests in each of the environments.
|
||||||
|
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
towncrier
|
|
||||||
@@ -25,7 +25,7 @@ to run each test in a controlled subprocess. Here is a basic example::
|
|||||||
|
|
||||||
If you run this with::
|
If you run this with::
|
||||||
|
|
||||||
$ py.test -n1
|
$ pytest -n1
|
||||||
=========================== test session starts ============================
|
=========================== test session starts ============================
|
||||||
platform linux2 -- Python 2.7.3 -- pytest-2.3.0.dev8
|
platform linux2 -- Python 2.7.3 -- pytest-2.3.0.dev8
|
||||||
plugins: xdist, bugzilla, cache, oejskit, cli, pep8, cov
|
plugins: xdist, bugzilla, cache, oejskit, cli, pep8, cov
|
||||||
@@ -46,7 +46,7 @@ You'll see that a couple of tests are reported as crashing, indicated
|
|||||||
by lower-case ``f`` and the respective failure summary. You can also use
|
by lower-case ``f`` and the respective failure summary. You can also use
|
||||||
the xdist-provided parallelization feature to speed up your testing::
|
the xdist-provided parallelization feature to speed up your testing::
|
||||||
|
|
||||||
$ py.test -n3
|
$ pytest -n3
|
||||||
=========================== test session starts ============================
|
=========================== test session starts ============================
|
||||||
platform linux2 -- Python 2.7.3 -- pytest-2.3.0.dev8
|
platform linux2 -- Python 2.7.3 -- pytest-2.3.0.dev8
|
||||||
plugins: xdist, bugzilla, cache, oejskit, cli, pep8, cov
|
plugins: xdist, bugzilla, cache, oejskit, cli, pep8, cov
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ passenv = http_proxy https_proxy
|
|||||||
deps = -rrequirements.txt
|
deps = -rrequirements.txt
|
||||||
changedir = {envtmpdir}
|
changedir = {envtmpdir}
|
||||||
commands =
|
commands =
|
||||||
py.test -s -v \
|
pytest -s -v \
|
||||||
--doctest-modules \
|
--doctest-modules \
|
||||||
--junitxml=tests.xml \
|
--junitxml=tests.xml \
|
||||||
--dist=loadscope \
|
--dist=loadscope \
|
||||||
|
|||||||
2
setup.py
2
setup.py
@@ -6,7 +6,7 @@ install_requires = ['execnet>=1.1', 'pytest>=3.0.0', 'pytest-forked']
|
|||||||
setup(
|
setup(
|
||||||
name="pytest-xdist",
|
name="pytest-xdist",
|
||||||
use_scm_version={'write_to': 'xdist/_version.py'},
|
use_scm_version={'write_to': 'xdist/_version.py'},
|
||||||
description='py.test xdist plugin for distributed testing'
|
description='pytest xdist plugin for distributed testing'
|
||||||
' and loop-on-failing modes',
|
' and loop-on-failing modes',
|
||||||
long_description=open('README.rst').read(),
|
long_description=open('README.rst').read(),
|
||||||
license='MIT',
|
license='MIT',
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
|
import os
|
||||||
import re
|
import re
|
||||||
|
import textwrap
|
||||||
|
|
||||||
import py
|
import py
|
||||||
import pytest
|
import pytest
|
||||||
@@ -54,8 +56,8 @@ class TestDistribution:
|
|||||||
def test_n1_skip(self, testdir):
|
def test_n1_skip(self, testdir):
|
||||||
p1 = testdir.makepyfile("""
|
p1 = testdir.makepyfile("""
|
||||||
def test_skip():
|
def test_skip():
|
||||||
import py
|
import pytest
|
||||||
py.test.skip("myreason")
|
pytest.skip("myreason")
|
||||||
""")
|
""")
|
||||||
result = testdir.runpytest(p1, "-n1")
|
result = testdir.runpytest(p1, "-n1")
|
||||||
assert result.ret == 0
|
assert result.ret == 0
|
||||||
@@ -78,7 +80,7 @@ class TestDistribution:
|
|||||||
def test_manytests_to_one_popen(self, testdir):
|
def test_manytests_to_one_popen(self, testdir):
|
||||||
p1 = testdir.makepyfile(
|
p1 = testdir.makepyfile(
|
||||||
"""
|
"""
|
||||||
import py
|
import pytest
|
||||||
def test_fail0():
|
def test_fail0():
|
||||||
assert 0
|
assert 0
|
||||||
def test_fail1():
|
def test_fail1():
|
||||||
@@ -86,7 +88,7 @@ class TestDistribution:
|
|||||||
def test_ok():
|
def test_ok():
|
||||||
pass
|
pass
|
||||||
def test_skip():
|
def test_skip():
|
||||||
py.test.skip("hello")
|
pytest.skip("hello")
|
||||||
""", )
|
""", )
|
||||||
result = testdir.runpytest(p1, "-v", '-d', '--tx=popen', '--tx=popen')
|
result = testdir.runpytest(p1, "-v", '-d', '--tx=popen', '--tx=popen')
|
||||||
result.stdout.fnmatch_lines([
|
result.stdout.fnmatch_lines([
|
||||||
@@ -124,7 +126,7 @@ class TestDistribution:
|
|||||||
def test_dist_ini_specified(self, testdir):
|
def test_dist_ini_specified(self, testdir):
|
||||||
p1 = testdir.makepyfile(
|
p1 = testdir.makepyfile(
|
||||||
"""
|
"""
|
||||||
import py
|
import pytest
|
||||||
def test_fail0():
|
def test_fail0():
|
||||||
assert 0
|
assert 0
|
||||||
def test_fail1():
|
def test_fail1():
|
||||||
@@ -132,7 +134,7 @@ class TestDistribution:
|
|||||||
def test_ok():
|
def test_ok():
|
||||||
pass
|
pass
|
||||||
def test_skip():
|
def test_skip():
|
||||||
py.test.skip("hello")
|
pytest.skip("hello")
|
||||||
""", )
|
""", )
|
||||||
testdir.makeini("""
|
testdir.makeini("""
|
||||||
[pytest]
|
[pytest]
|
||||||
@@ -145,13 +147,13 @@ class TestDistribution:
|
|||||||
])
|
])
|
||||||
assert result.ret == 1
|
assert result.ret == 1
|
||||||
|
|
||||||
@py.test.mark.xfail("sys.platform.startswith('java')", run=False)
|
@pytest.mark.xfail("sys.platform.startswith('java')", run=False)
|
||||||
def test_dist_tests_with_crash(self, testdir):
|
def test_dist_tests_with_crash(self, testdir):
|
||||||
if not hasattr(py.std.os, 'kill'):
|
if not hasattr(os, 'kill'):
|
||||||
py.test.skip("no os.kill")
|
pytest.skip("no os.kill")
|
||||||
|
|
||||||
p1 = testdir.makepyfile("""
|
p1 = testdir.makepyfile("""
|
||||||
import py
|
import pytest
|
||||||
def test_fail0():
|
def test_fail0():
|
||||||
assert 0
|
assert 0
|
||||||
def test_fail1():
|
def test_fail1():
|
||||||
@@ -159,7 +161,7 @@ class TestDistribution:
|
|||||||
def test_ok():
|
def test_ok():
|
||||||
pass
|
pass
|
||||||
def test_skip():
|
def test_skip():
|
||||||
py.test.skip("hello")
|
pytest.skip("hello")
|
||||||
def test_crash():
|
def test_crash():
|
||||||
import time
|
import time
|
||||||
import os
|
import os
|
||||||
@@ -299,7 +301,7 @@ class TestDistEach:
|
|||||||
assert not result.ret
|
assert not result.ret
|
||||||
result.stdout.fnmatch_lines(["*2 pass*"])
|
result.stdout.fnmatch_lines(["*2 pass*"])
|
||||||
|
|
||||||
@py.test.mark.xfail(
|
@pytest.mark.xfail(
|
||||||
run=False,
|
run=False,
|
||||||
reason="other python versions might not have py.test installed")
|
reason="other python versions might not have py.test installed")
|
||||||
def test_simple_diffoutput(self, testdir):
|
def test_simple_diffoutput(self, testdir):
|
||||||
@@ -307,7 +309,7 @@ class TestDistEach:
|
|||||||
for name in ("python2.5", "python2.6"):
|
for name in ("python2.5", "python2.6"):
|
||||||
interp = py.path.local.sysfind(name)
|
interp = py.path.local.sysfind(name)
|
||||||
if interp is None:
|
if interp is None:
|
||||||
py.test.skip("%s not found" % name)
|
pytest.skip("%s not found" % name)
|
||||||
interpreters.append(interp)
|
interpreters.append(interp)
|
||||||
|
|
||||||
testdir.makepyfile(
|
testdir.makepyfile(
|
||||||
@@ -330,11 +332,11 @@ class TestDistEach:
|
|||||||
class TestTerminalReporting:
|
class TestTerminalReporting:
|
||||||
def test_pass_skip_fail(self, testdir):
|
def test_pass_skip_fail(self, testdir):
|
||||||
testdir.makepyfile("""
|
testdir.makepyfile("""
|
||||||
import py
|
import pytest
|
||||||
def test_ok():
|
def test_ok():
|
||||||
pass
|
pass
|
||||||
def test_skip():
|
def test_skip():
|
||||||
py.test.skip("xx")
|
pytest.skip("xx")
|
||||||
def test_func():
|
def test_func():
|
||||||
assert 0
|
assert 0
|
||||||
""")
|
""")
|
||||||
@@ -421,7 +423,7 @@ def test_teardownfails_one_function(testdir):
|
|||||||
["*def teardown_function(function):*", "*1 passed*1 error*"])
|
["*def teardown_function(function):*", "*1 passed*1 error*"])
|
||||||
|
|
||||||
|
|
||||||
@py.test.mark.xfail
|
@pytest.mark.xfail
|
||||||
def test_terminate_on_hangingnode(testdir):
|
def test_terminate_on_hangingnode(testdir):
|
||||||
p = testdir.makeconftest("""
|
p = testdir.makeconftest("""
|
||||||
def pytest_sessionfinish(session):
|
def pytest_sessionfinish(session):
|
||||||
@@ -585,7 +587,7 @@ def test_skipping(testdir):
|
|||||||
|
|
||||||
def test_issue34_pluginloading_in_subprocess(testdir):
|
def test_issue34_pluginloading_in_subprocess(testdir):
|
||||||
testdir.tmpdir.join("plugin123.py").write(
|
testdir.tmpdir.join("plugin123.py").write(
|
||||||
py.code.Source("""
|
textwrap.dedent("""
|
||||||
def pytest_namespace():
|
def pytest_namespace():
|
||||||
return {'sample_variable': 'testing'}
|
return {'sample_variable': 'testing'}
|
||||||
"""))
|
"""))
|
||||||
|
|||||||
@@ -31,7 +31,9 @@ def test_dist_options(testdir):
|
|||||||
|
|
||||||
def test_auto_detect_cpus(testdir, monkeypatch):
|
def test_auto_detect_cpus(testdir, monkeypatch):
|
||||||
import os
|
import os
|
||||||
if hasattr(os, 'cpu_count'):
|
if hasattr(os, 'sched_getaffinity'):
|
||||||
|
monkeypatch.setattr(os, 'sched_getaffinity', lambda _pid: set(range(99)))
|
||||||
|
elif hasattr(os, 'cpu_count'):
|
||||||
monkeypatch.setattr(os, 'cpu_count', lambda: 99)
|
monkeypatch.setattr(os, 'cpu_count', lambda: 99)
|
||||||
else:
|
else:
|
||||||
import multiprocessing
|
import multiprocessing
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import py
|
import py
|
||||||
|
import pprint
|
||||||
import pytest
|
import pytest
|
||||||
from xdist.workermanage import WorkerController, unserialize_report
|
from xdist.workermanage import WorkerController, unserialize_report
|
||||||
from xdist.remote import serialize_report
|
from xdist.remote import serialize_report
|
||||||
@@ -14,7 +15,7 @@ def check_marshallable(d):
|
|||||||
try:
|
try:
|
||||||
marshal.dumps(d)
|
marshal.dumps(d)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
py.std.pprint.pprint(d)
|
pprint.pprint(d)
|
||||||
raise ValueError("not marshallable")
|
raise ValueError("not marshallable")
|
||||||
|
|
||||||
|
|
||||||
@@ -344,7 +345,7 @@ class TestWorkerInteractor:
|
|||||||
for data in worker.slp.channel:
|
for data in worker.slp.channel:
|
||||||
worker.slp.process_from_remote(data)
|
worker.slp.process_from_remote(data)
|
||||||
worker.slp.process_from_remote(worker.slp.ENDMARK)
|
worker.slp.process_from_remote(worker.slp.ENDMARK)
|
||||||
py.std.pprint.pprint(hookrec.hookrecorder.calls)
|
pprint.pprint(hookrec.hookrecorder.calls)
|
||||||
hookrec.hookrecorder.contains([
|
hookrec.hookrecorder.contains([
|
||||||
("pytest_collectstart", "collector.fspath == aaa"),
|
("pytest_collectstart", "collector.fspath == aaa"),
|
||||||
("pytest_pycollect_makeitem", "name == 'test_func'"),
|
("pytest_pycollect_makeitem", "name == 'test_func'"),
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import py
|
import py
|
||||||
import pytest
|
import pytest
|
||||||
|
import textwrap
|
||||||
import execnet
|
import execnet
|
||||||
from _pytest.pytester import HookRecorder
|
from _pytest.pytester import HookRecorder
|
||||||
from xdist import workermanage, newhooks
|
from xdist import workermanage, newhooks
|
||||||
@@ -198,7 +199,7 @@ class TestNodeManager:
|
|||||||
source.ensure("dir1", "somefile", dir=1)
|
source.ensure("dir1", "somefile", dir=1)
|
||||||
dir2.ensure("hello")
|
dir2.ensure("hello")
|
||||||
source.ensure("bogusdir", "file")
|
source.ensure("bogusdir", "file")
|
||||||
source.join("tox.ini").write(py.std.textwrap.dedent("""
|
source.join("tox.ini").write(textwrap.dedent("""
|
||||||
[pytest]
|
[pytest]
|
||||||
rsyncdirs=dir1/dir2
|
rsyncdirs=dir1/dir2
|
||||||
"""))
|
"""))
|
||||||
@@ -217,7 +218,7 @@ class TestNodeManager:
|
|||||||
dir2.ensure("hello")
|
dir2.ensure("hello")
|
||||||
source.ensure("foo", "bar")
|
source.ensure("foo", "bar")
|
||||||
source.ensure("bar", "foo")
|
source.ensure("bar", "foo")
|
||||||
source.join("tox.ini").write(py.std.textwrap.dedent("""
|
source.join("tox.ini").write(textwrap.dedent("""
|
||||||
[pytest]
|
[pytest]
|
||||||
rsyncdirs = dir1 dir5
|
rsyncdirs = dir1 dir5
|
||||||
rsyncignore = dir1/dir2 dir5/dir6 foo*
|
rsyncignore = dir1/dir2 dir5/dir6 foo*
|
||||||
|
|||||||
15
tox.ini
15
tox.ini
@@ -27,7 +27,7 @@ platform=
|
|||||||
commands=
|
commands=
|
||||||
# always clean to avoid code unmarshal mismatch on old python/pytest
|
# always clean to avoid code unmarshal mismatch on old python/pytest
|
||||||
py.cleanup -aq
|
py.cleanup -aq
|
||||||
py.test {posargs}
|
pytest {posargs}
|
||||||
|
|
||||||
[testenv:flakes]
|
[testenv:flakes]
|
||||||
changedir=
|
changedir=
|
||||||
@@ -40,7 +40,18 @@ deps = readme
|
|||||||
skip_install = true
|
skip_install = true
|
||||||
commands = python setup.py check -r -s
|
commands = python setup.py check -r -s
|
||||||
|
|
||||||
|
[testenv:release]
|
||||||
|
changedir=
|
||||||
|
decription = do a release, required posarg of the version number
|
||||||
|
basepython = python3.6
|
||||||
|
skipsdist = True
|
||||||
|
usedevelop = True
|
||||||
|
passenv = *
|
||||||
|
deps =
|
||||||
|
towncrier
|
||||||
|
commands =
|
||||||
|
towncrier --version {posargs} --yes
|
||||||
|
|
||||||
[pytest]
|
[pytest]
|
||||||
addopts = -rsfxX
|
addopts = -rsfxX
|
||||||
;; hello
|
|
||||||
|
|||||||
@@ -17,8 +17,8 @@ class Interrupted(KeyboardInterrupt):
|
|||||||
""" signals an immediate interruption. """
|
""" signals an immediate interruption. """
|
||||||
|
|
||||||
|
|
||||||
class DSession:
|
class DSession(object):
|
||||||
"""A py.test plugin which runs a distributed test session
|
"""A pytest plugin which runs a distributed test session
|
||||||
|
|
||||||
At the beginning of the test session this creates a NodeManager
|
At the beginning of the test session this creates a NodeManager
|
||||||
instance which creates and starts all nodes. Nodes then emit
|
instance which creates and starts all nodes. Nodes then emit
|
||||||
@@ -26,7 +26,7 @@ class DSession:
|
|||||||
methods.
|
methods.
|
||||||
|
|
||||||
Once a node is started it will automatically start running the
|
Once a node is started it will automatically start running the
|
||||||
py.test mainloop with some custom hooks. This means a node
|
pytest mainloop with some custom hooks. This means a node
|
||||||
automatically starts collecting tests. Once tests are collected
|
automatically starts collecting tests. Once tests are collected
|
||||||
it will wait for instructions.
|
it will wait for instructions.
|
||||||
"""
|
"""
|
||||||
@@ -316,7 +316,7 @@ class DSession:
|
|||||||
self.config.hook.pytest_runtest_logreport(report=rep)
|
self.config.hook.pytest_runtest_logreport(report=rep)
|
||||||
|
|
||||||
|
|
||||||
class TerminalDistReporter:
|
class TerminalDistReporter(object):
|
||||||
def __init__(self, config):
|
def __init__(self, config):
|
||||||
self.config = config
|
self.config = config
|
||||||
self.tr = config.pluginmanager.getplugin("terminalreporter")
|
self.tr = config.pluginmanager.getplugin("terminalreporter")
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
"""
|
"""
|
||||||
Implement -f aka looponfailing for py.test.
|
Implement -f aka looponfailing for pytest.
|
||||||
|
|
||||||
NOTE that we try to avoid loading and depending on application modules
|
NOTE that we try to avoid loading and depending on application modules
|
||||||
within the controlling process (the one that starts repeatedly test
|
within the controlling process (the one that starts repeatedly test
|
||||||
@@ -10,6 +10,7 @@
|
|||||||
import py
|
import py
|
||||||
import pytest
|
import pytest
|
||||||
import sys
|
import sys
|
||||||
|
import time
|
||||||
import execnet
|
import execnet
|
||||||
|
|
||||||
|
|
||||||
@@ -157,7 +158,7 @@ def init_worker_session(channel, args, option_dict):
|
|||||||
WorkerFailSession(config, channel).main()
|
WorkerFailSession(config, channel).main()
|
||||||
|
|
||||||
|
|
||||||
class WorkerFailSession:
|
class WorkerFailSession(object):
|
||||||
def __init__(self, config, channel):
|
def __init__(self, config, channel):
|
||||||
self.config = config
|
self.config = config
|
||||||
self.channel = channel
|
self.channel = channel
|
||||||
@@ -211,7 +212,7 @@ class WorkerFailSession:
|
|||||||
self.channel.send((trails, failreports, self.collection_failed))
|
self.channel.send((trails, failreports, self.collection_failed))
|
||||||
|
|
||||||
|
|
||||||
class StatRecorder:
|
class StatRecorder(object):
|
||||||
def __init__(self, rootdirlist):
|
def __init__(self, rootdirlist):
|
||||||
self.rootdirlist = rootdirlist
|
self.rootdirlist = rootdirlist
|
||||||
self.statcache = {}
|
self.statcache = {}
|
||||||
@@ -228,7 +229,7 @@ class StatRecorder:
|
|||||||
changed = self.check()
|
changed = self.check()
|
||||||
if changed:
|
if changed:
|
||||||
return
|
return
|
||||||
py.std.time.sleep(checkinterval)
|
time.sleep(checkinterval)
|
||||||
|
|
||||||
def check(self, removepycfiles=True): # noqa, too complex
|
def check(self, removepycfiles=True): # noqa, too complex
|
||||||
changed = False
|
changed = False
|
||||||
|
|||||||
@@ -5,9 +5,16 @@ import pytest
|
|||||||
def parse_numprocesses(s):
|
def parse_numprocesses(s):
|
||||||
if s == 'auto':
|
if s == 'auto':
|
||||||
try:
|
try:
|
||||||
from os import cpu_count
|
from os import sched_getaffinity
|
||||||
except ImportError:
|
except ImportError:
|
||||||
from multiprocessing import cpu_count
|
try:
|
||||||
|
from os import cpu_count
|
||||||
|
except ImportError:
|
||||||
|
from multiprocessing import cpu_count
|
||||||
|
else:
|
||||||
|
def cpu_count():
|
||||||
|
return len(sched_getaffinity(0))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
n = cpu_count()
|
n = cpu_count()
|
||||||
except NotImplementedError:
|
except NotImplementedError:
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import _pytest.hookspec
|
|||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
class WorkerInteractor:
|
class WorkerInteractor(object):
|
||||||
def __init__(self, config, channel):
|
def __init__(self, config, channel):
|
||||||
self.config = config
|
self.config = config
|
||||||
self.workerid = config.workerinput.get('workerid', "?")
|
self.workerid = config.workerinput.get('workerid', "?")
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ from xdist.workermanage import parse_spec_config
|
|||||||
from xdist.report import report_collection_diff
|
from xdist.report import report_collection_diff
|
||||||
|
|
||||||
|
|
||||||
class EachScheduling:
|
class EachScheduling(object):
|
||||||
"""Implement scheduling of test items on all nodes
|
"""Implement scheduling of test items on all nodes
|
||||||
|
|
||||||
If a node gets added after the test run is started then it is
|
If a node gets added after the test run is started then it is
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ class LoadFileScheduling(LoadScopeScheduling):
|
|||||||
This class behaves very much like LoadScopeScheduling, but with a file-level scope.
|
This class behaves very much like LoadScopeScheduling, but with a file-level scope.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init(self, config, log=None):
|
def __init__(self, config, log=None):
|
||||||
super(LoadFileScheduling, self).__init__(config, log)
|
super(LoadFileScheduling, self).__init__(config, log)
|
||||||
if log is None:
|
if log is None:
|
||||||
self.log = Producer('loadfilesched')
|
self.log = Producer('loadfilesched')
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ from xdist.workermanage import parse_spec_config
|
|||||||
from xdist.report import report_collection_diff
|
from xdist.report import report_collection_diff
|
||||||
|
|
||||||
|
|
||||||
class LoadScheduling:
|
class LoadScheduling(object):
|
||||||
"""Implement load scheduling across nodes.
|
"""Implement load scheduling across nodes.
|
||||||
|
|
||||||
This distributes the tests collected across all nodes so each test
|
This distributes the tests collected across all nodes so each test
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ from xdist.report import report_collection_diff
|
|||||||
from xdist.workermanage import parse_spec_config
|
from xdist.workermanage import parse_spec_config
|
||||||
|
|
||||||
|
|
||||||
class LoadScopeScheduling:
|
class LoadScopeScheduling(object):
|
||||||
"""Implement load scheduling across nodes, but grouping test by scope.
|
"""Implement load scheduling across nodes, but grouping test by scope.
|
||||||
|
|
||||||
This distributes the tests collected across all nodes so each test is run
|
This distributes the tests collected across all nodes so each test is run
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import fnmatch
|
import fnmatch
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
import threading
|
||||||
|
|
||||||
import py
|
import py
|
||||||
import pytest
|
import pytest
|
||||||
@@ -32,7 +33,7 @@ class NodeManager(object):
|
|||||||
|
|
||||||
def __init__(self, config, specs=None, defaultchdir="pyexecnetcache"):
|
def __init__(self, config, specs=None, defaultchdir="pyexecnetcache"):
|
||||||
self.config = config
|
self.config = config
|
||||||
self._nodesready = py.std.threading.Event()
|
self._nodesready = threading.Event()
|
||||||
self.trace = self.config.trace.get("nodemanager")
|
self.trace = self.config.trace.get("nodemanager")
|
||||||
self.group = execnet.Group()
|
self.group = execnet.Group()
|
||||||
if specs is None:
|
if specs is None:
|
||||||
@@ -184,7 +185,7 @@ class HostRSync(execnet.RSync):
|
|||||||
|
|
||||||
|
|
||||||
def make_reltoroot(roots, args):
|
def make_reltoroot(roots, args):
|
||||||
# XXX introduce/use public API for splitting py.test args
|
# XXX introduce/use public API for splitting pytest args
|
||||||
splitcode = "::"
|
splitcode = "::"
|
||||||
result = []
|
result = []
|
||||||
for arg in args:
|
for arg in args:
|
||||||
|
|||||||
Reference in New Issue
Block a user