Commit 45ca7bbf authored by Daniel Stender's avatar Daniel Stender

New upstream version 1.18.2

parent 16a880f5
Thanks for submitting a PR, your contribution is really appreciated!
Here's a quick checklist that should be present in PRs:
- [ ] Make sure to include reasonable tests for your change if necessary
- [ ] We use [towncrier](https://pypi.python.org/pypi/towncrier) for changelog management, so please add a *news* file into the `changelog` folder following these guidelines:
* Name it `$issue_id.$type` for example `588.bugfix`;
* If you don't have an issue_id change it to the PR id after creating it
* Ensure type is one of `removal`, `feature`, `bugfix`, `vendor`, `doc` or `trivial`
* Make sure to use full sentences with correct case and punctuation, for example:
```
Fix issue with non-ascii contents in doctest text files.
```
sudo: false
language: python
python:
- '2.6'
- '2.7'
- '3.4'
- '3.5'
install: pip install -U tox setuptools_scm
env:
matrix:
- TESTENV=py26-pytest26
- TESTENV=py26-pytest27
- TESTENV=py26-pytest28
- TESTENV=py26-pytest29
- TESTENV=py27-pytest26
- TESTENV=py27-pytest27
- TESTENV=py27-pytest28
- TESTENV=py27-pytest29
- TESTENV=py34-pytest26
- TESTENV=py34-pytest27
- TESTENV=py34-pytest28
- TESTENV=py34-pytest29
- TESTENV=py35-pytest27
- TESTENV=py35-pytest28
- TESTENV=py35-pytest29
- TESTENV=py27-pytest28-pexpect
- TESTENV=py35-pytest28-pexpect
- TESTENV=flakes
- TESTENV=readme
script: tox --recreate -e $TESTENV
- '3.6'
install: pip install tox-travis setuptools_scm
matrix:
include:
# note: please use "tox --listenvs" to populate the build matrix
- python: "3.5"
env: TOXENV=flakes
- python: "3.5"
env: TOXENV=readme
script: tox
notifications:
irc:
channels:
......@@ -37,6 +28,7 @@ notifications:
deploy:
provider: pypi
user: ronny
skip_upload_docs: true
password:
secure: cxmSDho5d+PYKEM4ZCg8ms1P4lzhYkrw6fEOm2HtTcsuCyY6aZMSgImWAnEYbJHSkdzgcxlXK9UKJ9B0YenXmBCkAr7UjdnpNXNmkySr0sYzlH/sfqt/dDATCHFaRKxnkOSOVywaDYhT9n8YudbXI77pXwD12i/CeSSJDbHhsu0JYUfAcb+D6YjRYoA2SEGCnzSzg+gDDfwXZx4ZiODCGLVwieNp1klCg88YROUE1BaYYNuUOONvfXX8+TWowbCF6ChH1WL/bZ49OStEYQNuYxZQZr4yClIqu9VJbchrU8j860K9ott2kkGTgfB/dDrQB/XncBubyIX9ikzCQAmmBXWAI3eyvWLPDk2Jz7kW2l2RT7syct80tCq3JhvQ1qdwr5ap7siocTLgnBW0tF4tkHSTFN3510fkc43npnp6FThebESQpnI24vqpwJ9hI/kW5mYi014Og2E/cpCXnz2XO8iZPDbqAMQpDsqEQoyhfGNgPTGp4K30TxRtwZBI5hHhDKnnR16fXtRgt1gYPvz/peUQvvpOm4JzIzGXPzluuutpnCBy75v5+oiwT3YRrLL/Meims9FtDDXL3qQubAE/ezIOOpm0N5XXV8DxIom8EN71yq5ab1tqhM+tBX7owRjy4FR4If2Q8feBdmTuh26DIQt/y+qSG8VkB9Sw/JCjc7c=
on:
......
pytest-xdist 1.18.2 (2017-07-28)
================================
Bug Fixes
---------
- Removal of unnecessary dependency on incorrect version of py. (`#105
<https://github.com/pytest-dev/pytest-xdist/issues/105>`_)
- Fix bug in internal event-loop error handler in the master node. This bug
would shadow the original errors making extremely hard/impossible for users
to diagnose the problem properly. (`#175 <https://github.com/pytest-
dev/pytest-xdist/issues/175>`_)
pytest-xdist 1.18.1 (2017-07-05)
================================
Bug Fixes
---------
- Fixed serialization of ``longrepr.sections`` during error reporting from
workers. (`#171 <https://github.com/pytest-dev/pytest-xdist/issues/171>`_)
- Fix ``ReprLocal`` not being unserialized breaking --showlocals usages. (`#176
<https://github.com/pytest-dev/pytest-xdist/issues/176>`_)
pytest-xdist 1.18.0 (2017-06-26)
================================
- ``pytest-xdist`` now requires ``pytest>=3.0.0``.
Features
--------
- Add long option `--numprocesses` as alternative for `-n`. (#168)
Bug Fixes
---------
- Fix serialization and deserialization dropping longrepr details. (#133)
pytest-xdist 1.17.1 (2017-06-10)
================================
Bug Fixes
---------
- Hot fix release reverting the change introduced by #124, unfortunately it
broke a number of test suites so we are reversing this change while we
investigate the problem. (#157)
Improved Documentation
----------------------
- Introduced ``towncrier`` for ``CHANGELOG`` management. (#154)
- Added ``HOWTORELEASE`` documentation. (#155)
..
You should *NOT* be adding new change log entries to this file, this
file is managed by towncrier. You *may* edit previous change logs to
fix problems like typo corrections or such.
To add a new change log entry, please see
https://pip.pypa.io/en/latest/development/#adding-a-news-entry
We named the news folder ``changelog``
.. towncrier release notes start
1.17.0
------
- fix #124: xdist would mark test as complete after 'call' step. As a result,
xdist could identify the wrong test as failing when test crashes at teardown.
To address this issue, xdist now marks test as complete at teardown.
1.16.0
------
- ``pytest-xdist`` now requires pytest 2.7 or later.
- Add ``worker_id`` attribute in the TestReport
- new hook: ``pytest_xdist_make_scheduler(config, log)``, can return custom tests items
distribution logic implementation. You can take a look at built-in ``LoadScheduling``
and ``EachScheduling`` implementations. Note that required scheduler class public
API may change in next ``pytest-xdist`` versions.
1.15.0
------
......
======================
Releasing pytest-xdist
======================
This document describes the steps to make a new ``pytest-xdist`` release.
Version
-------
``master`` should always be green and a potential release candidate. ``pytest-xdist`` follows
semantic versioning, so given that the current version is ``X.Y.Z``, to find the next version number
one needs to look at the ``changelog`` folder:
- If there is any file named ``*.feature``, then we must make a new **minor** release: next
release will be ``X.Y+1.0``.
- Otherwise it is just a **bug fix** release: ``X.Y.Z+1``.
Steps
-----
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``.
#. Install ``pytest-xdist`` and dev requirements in a virtualenv::
$ pip install -e . -r dev-requirements.txt
#. Update ``CHANGELOG.rst`` file by running::
$ towncrier --version X.Y.Z
It might ask for confirmation to remove news fragments; answer yes.
#. Commit and push the branch for review.
#. Once PR is **green** and **approved**, create and push a tag::
$ export VERSION=X.Y.Z
$ git tag v$VERSION release-$VERSION
$ git push git@github.com:pytest-dev/pytest-xdist.git v$VERSION
That will build the package and publish it on ``PyPI`` automatically.
include CHANGELOG
include LICENSE
include README.txt
include setup.py
include tox.ini
graft testing
prune .git
......@@ -34,6 +34,8 @@ The execution flow is:
tests and sends them one by one to each **worker** in a round robin
fashion. The rest of the tests will be distributed later as **workers**
finish tests (see below).
1. Note that `pytest_xdist_make_scheduler` hook can be used to implement custom tests distribution logic.
1. **workers** re-implement `pytest_runtestloop`: pytest's default implementation
basically loops over all collected items in the `session` object and executes
......
Metadata-Version: 1.1
Name: pytest-xdist
Version: 1.15.0
Version: 1.18.2
Summary: py.test xdist plugin for distributed testing and loop-on-failing modes
Home-page: https://github.com/pytest-dev/pytest-xdist
Author: holger krekel and contributors
Author-email: pytest-dev@python.org,holger@merlinux.eu
License: MIT
Description:
.. image:: https://travis-ci.org/pytest-dev/pytest-xdist.svg?branch=master
:target: https://travis-ci.org/pytest-dev/pytest-xdist
.. image:: http://img.shields.io/pypi/v/pytest-xdist.svg
:target: https://pypi.python.org/pypi/pytest-xdist
:target: https://pypi.python.org/pypi/pytest-xdist
.. image:: https://anaconda.org/conda-forge/pytest-xdist/badges/version.svg
:target: https://anaconda.org/conda-forge/pytest-xdist
.. image:: https://travis-ci.org/pytest-dev/pytest-xdist.svg?branch=master
:target: https://travis-ci.org/pytest-dev/pytest-xdist
.. image:: https://ci.appveyor.com/api/projects/status/56eq1a1avd4sdd7e/branch/master?svg=true
:target: https://ci.appveyor.com/project/pytestbot/pytest-xdist
......@@ -48,13 +52,9 @@ Description:
Install the plugin with::
easy_install pytest-xdist
# or
pip install pytest-xdist
or use the package in develope/in-place mode with
or use the package in develop/in-place mode with
a checkout of the `pytest-xdist repository`_ ::
python setup.py develop
......@@ -217,6 +217,10 @@ Description:
* ``PYTEST_XDIST_WORKER_COUNT``: the total number of workers in this session,
e.g., ``"4"`` when ``-n 4`` is given in the command-line.
The information about the worker_id in a test is stored in the TestReport as
well, under worker_id attribute.
*New in version 1.15.*
Specifying test exec environments in an ini file
......@@ -263,12 +267,6 @@ Description:
.. _`pytest-xdist repository`: https://github.com/pytest-dev/pytest-xdist
.. _`pytest`: http://pytest.org
Issue and Bug Tracker
------------------------
Please use the `pytest issue tracker <https://github.com/pytest-dev/pytest/issues>`_
for reporting bugs in this plugin.
Platform: linux
Platform: osx
Platform: win32
......
.. image:: https://travis-ci.org/pytest-dev/pytest-xdist.svg?branch=master
:target: https://travis-ci.org/pytest-dev/pytest-xdist
.. image:: http://img.shields.io/pypi/v/pytest-xdist.svg
:target: https://pypi.python.org/pypi/pytest-xdist
:target: https://pypi.python.org/pypi/pytest-xdist
.. image:: https://anaconda.org/conda-forge/pytest-xdist/badges/version.svg
:target: https://anaconda.org/conda-forge/pytest-xdist
.. image:: https://travis-ci.org/pytest-dev/pytest-xdist.svg?branch=master
:target: https://travis-ci.org/pytest-dev/pytest-xdist
.. image:: https://ci.appveyor.com/api/projects/status/56eq1a1avd4sdd7e/branch/master?svg=true
:target: https://ci.appveyor.com/project/pytestbot/pytest-xdist
......@@ -40,13 +44,9 @@ Installation
Install the plugin with::
easy_install pytest-xdist
# or
pip install pytest-xdist
or use the package in develope/in-place mode with
or use the package in develop/in-place mode with
a checkout of the `pytest-xdist repository`_ ::
python setup.py develop
......@@ -209,6 +209,10 @@ defined:
* ``PYTEST_XDIST_WORKER_COUNT``: the total number of workers in this session,
e.g., ``"4"`` when ``-n 4`` is given in the command-line.
The information about the worker_id in a test is stored in the TestReport as
well, under worker_id attribute.
*New in version 1.15.*
Specifying test exec environments in an ini file
......@@ -254,9 +258,3 @@ where the configuration file was found.
.. _`pytest-xdist`: http://pypi.python.org/pypi/pytest-xdist
.. _`pytest-xdist repository`: https://github.com/pytest-dev/pytest-xdist
.. _`pytest`: http://pytest.org
Issue and Bug Tracker
------------------------
Please use the `pytest issue tracker <https://github.com/pytest-dev/pytest/issues>`_
for reporting bugs in this plugin.
environment:
matrix:
# note: please use "tox --listenvs" to populate the build matrix
- TOXENV: "py26-pytest30"
- TOXENV: "py27-pytest30"
- TOXENV: "py34-pytest30"
- TOXENV: "py35-pytest30"
- TOXENV: "py36-pytest30"
- TOXENV: "py27-pytest30-pexpect"
- TOXENV: "py35-pytest30-pexpect"
- TOXENV: "flakes"
- TOXENV: "readme"
install:
- C:\Python35\python -m pip install tox setuptools_scm
......
{% for section in sections %}
{% set underline = "-" %}
{% if section %}
{{section}}
{{ underline * section|length }}{% set underline = "~" %}
{% endif %}
{% if sections[section] %}
{% for category, val in definitions.items() if category in sections[section] %}
{{ definitions[category]['name'] }}
{{ underline * definitions[category]['name']|length }}
{% if definitions[category]['showcontent'] %}
{% for text, values in sections[section][category]|dictsort(by='value') %}
- {{ text }}{% if category != 'vendor' %} (`{{ values[0] }} <https://github.com/pytest-dev/pytest-xdist/issues/{{ values[0][1:] }}>`_){% endif %}
{% endfor %}
{% else %}
- {{ sections[section][category]['']|sort|join(', ') }}
{% endif %}
{% if sections[section][category]|length == 0 %}
No significant changes.
{% else %}
{% endif %}
{% endfor %}
{% else %}
No significant changes.
{% endif %}
{% endfor %}
[tool.towncrier]
package = "xdist"
filename = "CHANGELOG.rst"
directory = "changelog/"
title_format = "pytest-xdist {version} ({project_date})"
template = "changelog/_template.rst"
[[tool.towncrier.type]]
directory = "removal"
name = "Deprecations and Removals"
showcontent = true
[[tool.towncrier.type]]
directory = "feature"
name = "Features"
showcontent = true
[[tool.towncrier.type]]
directory = "bugfix"
name = "Bug Fixes"
showcontent = true
[[tool.towncrier.type]]
directory = "vendor"
name = "Vendored Libraries"
showcontent = true
[[tool.towncrier.type]]
directory = "doc"
name = "Improved Documentation"
showcontent = true
[[tool.towncrier.type]]
directory = "trivial"
name = "Trivial Changes"
showcontent = false
[bdist_wheel]
universal = 1
[metadata]
license_file = LICENSE
[egg_info]
tag_svn_revision = 0
tag_build =
tag_date = 0
tag_build =
tag_svn_revision = 0
......@@ -20,7 +20,7 @@ setup(
],
},
zip_safe=False,
install_requires=['execnet>=1.1', 'pytest>=2.4.2', 'py>=1.4.22'],
install_requires=['execnet>=1.1', 'pytest>=3.0.0'],
setup_requires=['setuptools_scm'],
classifiers=[
'Development Status :: 5 - Production/Stable',
......
......@@ -10,7 +10,9 @@ class TestDistribution:
""")
result = testdir.runpytest(p1, "-n1")
assert result.ret == 0
result.stdout.fnmatch_lines(["*1 passed*", ])
result.stdout.fnmatch_lines([
"*1 passed*",
])
def test_n1_fail(self, testdir):
p1 = testdir.makepyfile("""
......@@ -19,7 +21,9 @@ class TestDistribution:
""")
result = testdir.runpytest(p1, "-n1")
assert result.ret == 1
result.stdout.fnmatch_lines(["*1 failed*", ])
result.stdout.fnmatch_lines([
"*1 failed*",
])
def test_n1_import_error(self, testdir):
p1 = testdir.makepyfile("""
......@@ -30,7 +34,7 @@ class TestDistribution:
result = testdir.runpytest(p1, "-n1")
assert result.ret == 1
result.stdout.fnmatch_lines([
"E ImportError: *__import_of_missing_module*",
"E *Error: No module named *__import_of_missing_module*",
])
def test_n2_import_error(self, testdir):
......@@ -53,7 +57,9 @@ class TestDistribution:
""")
result = testdir.runpytest(p1, "-n1")
assert result.ret == 0
result.stdout.fnmatch_lines(["*1 skipped*", ])
result.stdout.fnmatch_lines([
"*1 skipped*",
])
def test_manytests_to_one_import_error(self, testdir):
p1 = testdir.makepyfile("""
......@@ -62,13 +68,14 @@ class TestDistribution:
pass
""")
result = testdir.runpytest(p1, '--tx=popen', '--tx=popen')
assert result.ret == 1
assert result.ret in (1, 2)
result.stdout.fnmatch_lines([
"E ImportError: *__import_of_missing_module*",
"E *Error: No module named *__import_of_missing_module*",
])
def test_manytests_to_one_popen(self, testdir):
p1 = testdir.makepyfile("""
p1 = testdir.makepyfile(
"""
import py
def test_fail0():
assert 0
......@@ -108,10 +115,13 @@ class TestDistribution:
""" % str(testdir.tmpdir))
result = testdir.runpytest_subprocess(p1, "-n1")
assert result.ret == 0
result.stdout.fnmatch_lines(["*1 passed*", ])
result.stdout.fnmatch_lines([
"*1 passed*",
])
def test_dist_ini_specified(self, testdir):
p1 = testdir.makepyfile("""
p1 = testdir.makepyfile(
"""
import py
def test_fail0():
assert 0
......@@ -207,14 +217,14 @@ class TestDistribution:
""")
p1 = testdir.makepyfile("def test_func(): pass")
result = testdir.runpytest("-v", p1, '-d', '--tx=popen')
result.stdout.fnmatch_lines([
"*0*Python*", "*calculated result is 49*", "*1 passed*"
])
result.stdout.fnmatch_lines(
["*0*Python*", "*calculated result is 49*", "*1 passed*"])
assert result.ret == 0
def test_keyboardinterrupt_hooks_issue79(self, testdir):
testdir.makepyfile(__init__="",
test_one="""
testdir.makepyfile(
__init__="",
test_one="""
def test_hello():
raise KeyboardInterrupt()
""")
......@@ -273,8 +283,9 @@ class TestDistEach:
py.test.skip("%s not found" % name)
interpreters.append(interp)
testdir.makepyfile(__init__="",
test_one="""
testdir.makepyfile(
__init__="",
test_one="""
import sys
def test_hello():
print("%s...%s" % sys.version_info[:2])
......@@ -335,9 +346,8 @@ def test_teardownfails_one_function(testdir):
assert 0
""")
result = testdir.runpytest(p, '-n1', '--tx=popen')
result.stdout.fnmatch_lines([
"*def teardown_function(function):*", "*1 passed*1 error*"
])
result.stdout.fnmatch_lines(
["*def teardown_function(function):*", "*1 passed*1 error*"])
@py.test.mark.xfail
......@@ -350,7 +360,9 @@ def test_terminate_on_hangingnode(testdir):
""")
result = testdir.runpytest(p, '--dist=each', '--tx=popen//id=my')
assert result.duration < 2.0
result.stdout.fnmatch_lines(["*killed*my*", ])
result.stdout.fnmatch_lines([
"*killed*my*",
])
@pytest.mark.xfail(reason="works if run outside test suite", run=False)
......@@ -377,7 +389,10 @@ def test_session_hooks(testdir):
assert hasattr(sys, 'pytestsessionhooks')
""")
result = testdir.runpytest(p, "--dist=each", "--tx=popen")
result.stdout.fnmatch_lines(["*ValueError*", "*1 passed*", ])
result.stdout.fnmatch_lines([
"*ValueError*",
"*1 passed*",
])
assert not result.ret
d = result.parseoutcomes()
assert d['passed'] == 1
......@@ -422,7 +437,10 @@ def test_funcarg_teardown_failure(testdir):
pass
""")
result = testdir.runpytest_subprocess("--debug", p) # , "-n1")
result.stdout.fnmatch_lines(["*ValueError*42*", "*1 passed*1 error*", ])
result.stdout.fnmatch_lines([
"*ValueError*42*",
"*1 passed*1 error*",
])
assert result.ret
......@@ -453,7 +471,8 @@ def test_skipping(testdir):
def test_issue34_pluginloading_in_subprocess(testdir):
testdir.tmpdir.join("plugin123.py").write(py.code.Source("""
testdir.tmpdir.join("plugin123.py").write(
py.code.Source("""
def pytest_namespace():
return {'sample_variable': 'testing'}
"""))
......@@ -464,7 +483,9 @@ def test_issue34_pluginloading_in_subprocess(testdir):
""")
result = testdir.runpytest_subprocess("-n1", "-p", "plugin123")
assert result.ret == 0
result.stdout.fnmatch_lines(["*1 passed*", ])
result.stdout.fnmatch_lines([
"*1 passed*",
])
def test_fixture_scope_caching_issue503(testdir):
......@@ -486,7 +507,9 @@ def test_fixture_scope_caching_issue503(testdir):
""")
result = testdir.runpytest(p1, '-v', '-n1')
assert result.ret == 0
result.stdout.fnmatch_lines(["*2 passed*", ])
result.stdout.fnmatch_lines([
"*2 passed*",
])
def test_issue_594_random_parametrize(testdir):
......
......@@ -49,80 +49,84 @@ def dumpqueue(queue):
class TestEachScheduling:
def test_schedule_load_simple(self):
def test_schedule_load_simple(self, testdir):
node1 = MockNode()
node2 = MockNode()
sched = EachScheduling(2)
sched.addnode(node1)
sched.addnode(node2)
config = testdir.parseconfig("--tx=2*popen")
sched = EachScheduling(config)
sched.add_node(node1)
sched.add_node(node2)
collection = ["a.py::test_1", ]
assert not sched.collection_is_completed
sched.addnode_collection(node1, collection)
sched.add_node_collection(node1, collection)
assert not sched.collection_is_completed
sched.addnode_collection(node2, collection)
sched.add_node_collection(node2, collection)
assert sched.collection_is_completed
assert sched.node2collection[node1] == collection
assert sched.node2collection[node2] == collection
sched.init_distribute()
assert sched.tests_finished()
sched.schedule()
assert sched.tests_finished
assert node1.sent == ['ALL']
assert node2.sent == ['ALL']
sched.remove_item(node1, 0)
assert sched.tests_finished()
sched.remove_item(node2, 0)
assert sched.tests_finished()
sched.mark_test_complete(node1, 0)
assert sched.tests_finished
sched.mark_test_complete(node2, 0)
assert sched.tests_finished
def test_schedule_remove_node(self):
def test_schedule_remove_node(self, testdir):
node1 = MockNode()
sched = EachScheduling(1)
sched.addnode(node1)
config = testdir.parseconfig("--tx=popen")
sched = EachScheduling(config)
sched.add_node(node1)
collection = ["a.py::test_1", ]
assert not sched.collection_is_completed
sched.addnode_collection(node1, collection)
sched.add_node_collection(node1, collection)
assert sched.collection_is_completed
assert sched.node2collection[node1] == collection
sched.init_distribute()
assert sched.tests_finished()
sched.schedule()
assert sched.tests_finished
crashitem = sched.remove_node(node1)
assert crashitem
assert sched.tests_finished()
assert not sched.hasnodes()
assert sched.tests_finished
assert not sched.nodes
class TestLoadScheduling:
def test_schedule_load_simple(self):
sched = LoadScheduling(2)
sched.addnode(MockNode())
sched.addnode(MockNode())
def test_schedule_load_simple(self, testdir):
config = testdir.parseconfig("--tx=2*popen")
sched = LoadScheduling(config)
sched.add_node(MockNode())
sched.add_node(MockNode())
node1, node2 = sched.nodes
collection = ["a.py::test_1", "a.py::test_2"]
assert not sched.collection_is_completed
sched.addnode_collection(node1, collection)
sched.add_node_collection(node1, collection)
assert not sched.collection_is_completed
sched.addnode_collection(node2, collection)
sched.add_node_collection(node2, collection)
assert sched.collection_is_completed
assert sched.node2collection[node1] == collection
assert sched.node2collection[node2] == collection
sched.init_distribute()
sched.schedule()
assert not sched.pending
assert sched.tests_finished()
assert sched.tests_finished
assert len(node1.sent) == 1
assert len(node2.sent) == 1
assert node1.sent == [0]
assert node2.sent == [1]
sched.remove_item(node1, node1.sent[0])
assert sched.tests_finished()
def test_init_distribute_batch_size(self):
sched = LoadScheduling(2)
sched.addnode(MockNode())
sched.addnode(MockNode())
sched.mark_test_complete(node1, node1.sent[0])
assert sched.tests_finished
def test_schedule_batch_size(self, testdir):
config = testdir.parseconfig("--tx=2*popen")
sched = LoadScheduling(config)
sched.add_node(MockNode())
sched.add_node(MockNode())
node1, node2 = sched.nodes