Merge pull request #2790 from nicoddemus/merge-master-into-features
Merge master into features
This commit is contained in:
commit
de0d19ca09
10
.travis.yml
10
.travis.yml
|
@ -20,11 +20,11 @@ env:
|
||||||
- TOXENV=py27-trial
|
- TOXENV=py27-trial
|
||||||
- TOXENV=py27-numpy
|
- TOXENV=py27-numpy
|
||||||
- TOXENV=py27-pluggymaster
|
- TOXENV=py27-pluggymaster
|
||||||
- TOXENV=py35-pexpect
|
- TOXENV=py36-pexpect
|
||||||
- TOXENV=py35-xdist
|
- TOXENV=py36-xdist
|
||||||
- TOXENV=py35-trial
|
- TOXENV=py36-trial
|
||||||
- TOXENV=py35-numpy
|
- TOXENV=py36-numpy
|
||||||
- TOXENV=py35-pluggymaster
|
- TOXENV=py36-pluggymaster
|
||||||
- TOXENV=py27-nobyte
|
- TOXENV=py27-nobyte
|
||||||
- TOXENV=doctesting
|
- TOXENV=doctesting
|
||||||
- TOXENV=docs
|
- TOXENV=docs
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
How to release pytest
|
Release Procedure
|
||||||
--------------------------------------------
|
-----------------
|
||||||
|
|
||||||
|
Our current policy for releasing is to aim for a bugfix every few weeks and a minor release every 2-3 months. The idea
|
||||||
|
is to get fixes and new features out instead of trying to cram a ton of features into a release and by consequence
|
||||||
|
taking a lot of time to make a new one.
|
||||||
|
|
||||||
.. important::
|
.. important::
|
||||||
|
|
||||||
|
@ -21,7 +25,7 @@ How to release pytest
|
||||||
#. Generate docs, changelog, announcements and upload a package to
|
#. Generate docs, changelog, announcements and upload a package to
|
||||||
your ``devpi`` staging server::
|
your ``devpi`` staging server::
|
||||||
|
|
||||||
invoke generate.pre_release <VERSION> <DEVPI USER> --password <DEVPI PASSWORD>
|
invoke generate.pre-release <VERSION> <DEVPI USER> --password <DEVPI PASSWORD>
|
||||||
|
|
||||||
If ``--password`` is not given, it is assumed the user is already logged in ``devpi``.
|
If ``--password`` is not given, it is assumed the user is already logged in ``devpi``.
|
||||||
If you don't have an account, please ask for one.
|
If you don't have an account, please ask for one.
|
||||||
|
@ -49,7 +53,7 @@ How to release pytest
|
||||||
|
|
||||||
#. Publish to PyPI::
|
#. Publish to PyPI::
|
||||||
|
|
||||||
invoke generate.publish_release <VERSION> <DEVPI USER> <PYPI_NAME>
|
invoke generate.publish-release <VERSION> <DEVPI USER> <PYPI_NAME>
|
||||||
|
|
||||||
where PYPI_NAME is the name of pypi.python.org as configured in your ``~/.pypirc``
|
where PYPI_NAME is the name of pypi.python.org as configured in your ``~/.pypirc``
|
||||||
file `for devpi <http://doc.devpi.net/latest/quickstart-releaseprocess.html?highlight=pypirc#devpi-push-releasing-to-an-external-index>`_.
|
file `for devpi <http://doc.devpi.net/latest/quickstart-releaseprocess.html?highlight=pypirc#devpi-push-releasing-to-an-external-index>`_.
|
||||||
|
|
|
@ -78,7 +78,8 @@ class FastFilesCompleter:
|
||||||
completion = []
|
completion = []
|
||||||
globbed = []
|
globbed = []
|
||||||
if '*' not in prefix and '?' not in prefix:
|
if '*' not in prefix and '?' not in prefix:
|
||||||
if prefix[-1] == os.path.sep: # we are on unix, otherwise no bash
|
# we are on unix, otherwise no bash
|
||||||
|
if not prefix or prefix[-1] == os.path.sep:
|
||||||
globbed.extend(glob(prefix + '.*'))
|
globbed.extend(glob(prefix + '.*'))
|
||||||
prefix += '*'
|
prefix += '*'
|
||||||
globbed.extend(glob(prefix))
|
globbed.extend(glob(prefix))
|
||||||
|
@ -98,7 +99,7 @@ if os.environ.get('_ARGCOMPLETE'):
|
||||||
filescompleter = FastFilesCompleter()
|
filescompleter = FastFilesCompleter()
|
||||||
|
|
||||||
def try_argcomplete(parser):
|
def try_argcomplete(parser):
|
||||||
argcomplete.autocomplete(parser)
|
argcomplete.autocomplete(parser, always_complete_options=False)
|
||||||
else:
|
else:
|
||||||
def try_argcomplete(parser):
|
def try_argcomplete(parser):
|
||||||
pass
|
pass
|
||||||
|
|
|
@ -326,7 +326,7 @@ class MarkDecorator:
|
||||||
return self.name # for backward-compat (2.4.1 had this attr)
|
return self.name # for backward-compat (2.4.1 had this attr)
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
return self.mark == other.mark
|
return self.mark == other.mark if isinstance(other, MarkDecorator) else False
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<MarkDecorator %r>" % (self.mark,)
|
return "<MarkDecorator %r>" % (self.mark,)
|
||||||
|
|
10
appveyor.yml
10
appveyor.yml
|
@ -22,11 +22,11 @@ environment:
|
||||||
- TOXENV: "py27-trial"
|
- TOXENV: "py27-trial"
|
||||||
- TOXENV: "py27-numpy"
|
- TOXENV: "py27-numpy"
|
||||||
- TOXENV: "py27-pluggymaster"
|
- TOXENV: "py27-pluggymaster"
|
||||||
- TOXENV: "py35-pexpect"
|
- TOXENV: "py36-pexpect"
|
||||||
- TOXENV: "py35-xdist"
|
- TOXENV: "py36-xdist"
|
||||||
- TOXENV: "py35-trial"
|
- TOXENV: "py36-trial"
|
||||||
- TOXENV: "py35-numpy"
|
- TOXENV: "py36-numpy"
|
||||||
- TOXENV: "py35-pluggymaster"
|
- TOXENV: "py36-pluggymaster"
|
||||||
- TOXENV: "py27-nobyte"
|
- TOXENV: "py27-nobyte"
|
||||||
- TOXENV: "doctesting"
|
- TOXENV: "doctesting"
|
||||||
- TOXENV: "py35-freeze"
|
- TOXENV: "py35-freeze"
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Add note in ``parametrize.rst`` about calling ``metafunc.parametrize`` multiple times.
|
|
@ -0,0 +1 @@
|
||||||
|
Set ``xfail_strict=True`` in pytest's own test suite to catch expected failures as soon as they start to pass.
|
|
@ -0,0 +1 @@
|
||||||
|
Fix crash in tab completion when no prefix is given.
|
|
@ -0,0 +1 @@
|
||||||
|
The equality checking function (``__eq__``) of ``MarkDecorator`` returns ``False`` if one object is not an instance of ``MarkDecorator``.
|
|
@ -0,0 +1 @@
|
||||||
|
Fix typo in example of passing a callable to markers (in example/markers.rst)
|
|
@ -41,6 +41,7 @@ Full pytest documentation
|
||||||
historical-notes
|
historical-notes
|
||||||
license
|
license
|
||||||
contributing
|
contributing
|
||||||
|
development_guide
|
||||||
talks
|
talks
|
||||||
projects
|
projects
|
||||||
faq
|
faq
|
||||||
|
|
|
@ -0,0 +1,108 @@
|
||||||
|
=================
|
||||||
|
Development Guide
|
||||||
|
=================
|
||||||
|
|
||||||
|
Some general guidelines regarding development in pytest for core maintainers and general contributors. Nothing here
|
||||||
|
is set in stone and can't be changed, feel free to suggest improvements or changes in the workflow.
|
||||||
|
|
||||||
|
|
||||||
|
Code Style
|
||||||
|
----------
|
||||||
|
|
||||||
|
* `PEP-8 <https://www.python.org/dev/peps/pep-0008>`_
|
||||||
|
* `flake8 <https://pypi.python.org/pypi/flake8>`_ for quality checks
|
||||||
|
* `invoke <http://www.pyinvoke.org/>`_ to automate development tasks
|
||||||
|
|
||||||
|
|
||||||
|
Branches
|
||||||
|
--------
|
||||||
|
|
||||||
|
We have two long term branches:
|
||||||
|
|
||||||
|
* ``master``: contains the code for the next bugfix release.
|
||||||
|
* ``features``: contains the code with new features for the next minor release.
|
||||||
|
|
||||||
|
The official repository usually does not contain topic branches, developers and contributors should create topic
|
||||||
|
branches in their own forks.
|
||||||
|
|
||||||
|
Exceptions can be made for cases where more than one contributor is working on the same
|
||||||
|
topic or where it makes sense to use some automatic capability of the main repository, such as automatic docs from
|
||||||
|
`readthedocs <readthedocs.org>`_ for a branch dealing with documentation refactoring.
|
||||||
|
|
||||||
|
Issues
|
||||||
|
------
|
||||||
|
|
||||||
|
Any question, feature, bug or proposal is welcome as an issue. Users are encouraged to use them whenever they need.
|
||||||
|
|
||||||
|
GitHub issues should use labels to categorize them. Labels should be created sporadically, to fill a niche; we should
|
||||||
|
avoid creating labels just for the sake of creating them.
|
||||||
|
|
||||||
|
Here is a list of labels and a brief description mentioning their intent.
|
||||||
|
|
||||||
|
|
||||||
|
**Type**
|
||||||
|
|
||||||
|
* ``type: backward compatibility``: issue that will cause problems with old pytest versions.
|
||||||
|
* ``type: bug``: problem that needs to be addressed.
|
||||||
|
* ``type: deprecation``: feature that will be deprecated in the future.
|
||||||
|
* ``type: docs``: documentation missing or needing clarification.
|
||||||
|
* ``type: enhancement``: new feature or API change, should be merged into ``features``.
|
||||||
|
* ``type: feature-branch``: new feature or API change, should be merged into ``features``.
|
||||||
|
* ``type: infrastructure``: improvement to development/releases/CI structure.
|
||||||
|
* ``type: performance``: performance or memory problem/improvement.
|
||||||
|
* ``type: proposal``: proposal for a new feature, often to gather opinions or design the API around the new feature.
|
||||||
|
* ``type: question``: question regarding usage, installation, internals or how to test something.
|
||||||
|
* ``type: refactoring``: internal improvements to the code.
|
||||||
|
* ``type: regression``: indicates a problem that was introduced in a release which was working previously.
|
||||||
|
|
||||||
|
**Status**
|
||||||
|
|
||||||
|
* ``status: critical``: grave problem or usability issue that affects lots of users.
|
||||||
|
* ``status: easy``: easy issue that is friendly to new contributors.
|
||||||
|
* ``status: help wanted``: core developers need help from experts on this topic.
|
||||||
|
* ``status: needs information``: reporter needs to provide more information; can be closed after 2 or more weeks of inactivity.
|
||||||
|
|
||||||
|
**Topic**
|
||||||
|
|
||||||
|
* ``topic: collection``
|
||||||
|
* ``topic: fixtures``
|
||||||
|
* ``topic: parametrize``
|
||||||
|
* ``topic: reporting``
|
||||||
|
* ``topic: selection``
|
||||||
|
* ``topic: tracebacks``
|
||||||
|
|
||||||
|
**Plugin (internal or external)**
|
||||||
|
|
||||||
|
* ``plugin: cache``
|
||||||
|
* ``plugin: capture``
|
||||||
|
* ``plugin: doctests``
|
||||||
|
* ``plugin: junitxml``
|
||||||
|
* ``plugin: monkeypatch``
|
||||||
|
* ``plugin: nose``
|
||||||
|
* ``plugin: pastebin``
|
||||||
|
* ``plugin: pytester``
|
||||||
|
* ``plugin: tmpdir``
|
||||||
|
* ``plugin: unittest``
|
||||||
|
* ``plugin: warnings``
|
||||||
|
* ``plugin: xdist``
|
||||||
|
|
||||||
|
|
||||||
|
**OS**
|
||||||
|
|
||||||
|
Issues specific to a single operating system. Do not use as a means to indicate where an issue originated from, only
|
||||||
|
for problems that happen **only** in that system.
|
||||||
|
|
||||||
|
* ``os: linux``
|
||||||
|
* ``os: mac``
|
||||||
|
* ``os: windows``
|
||||||
|
|
||||||
|
**Temporary**
|
||||||
|
|
||||||
|
Used to classify issues for limited time, to help find issues related in events for example.
|
||||||
|
They should be removed after they are no longer relevant.
|
||||||
|
|
||||||
|
* ``temporary: EP2017 sprint``:
|
||||||
|
* ``temporary: sprint-candidate``:
|
||||||
|
|
||||||
|
|
||||||
|
.. include:: ../../HOWTORELEASE.rst
|
|
@ -435,7 +435,7 @@ The output is as follows::
|
||||||
.
|
.
|
||||||
1 passed in 0.12 seconds
|
1 passed in 0.12 seconds
|
||||||
|
|
||||||
We can see that the custom marker has its argument set extended with the function ``hello_world``. This is the key different between creating a custom marker as a callable, which invokes ``__call__`` behind the scenes, and using ``with_args``.
|
We can see that the custom marker has its argument set extended with the function ``hello_world``. This is the key difference between creating a custom marker as a callable, which invokes ``__call__`` behind the scenes, and using ``with_args``.
|
||||||
|
|
||||||
|
|
||||||
Reading markers which were set from multiple places
|
Reading markers which were set from multiple places
|
||||||
|
|
|
@ -198,6 +198,10 @@ list::
|
||||||
SKIP [1] test_strings.py:2: got empty parameter set ['stringinput'], function test_valid_string at $REGENDOC_TMPDIR/test_strings.py:1
|
SKIP [1] test_strings.py:2: got empty parameter set ['stringinput'], function test_valid_string at $REGENDOC_TMPDIR/test_strings.py:1
|
||||||
1 skipped in 0.12 seconds
|
1 skipped in 0.12 seconds
|
||||||
|
|
||||||
|
|
||||||
|
Note that when calling ``metafunc.parametrize`` multiple times with different parameter sets, all parameter names across
|
||||||
|
those sets cannot be duplicated, otherwise an error will be raised.
|
||||||
|
|
||||||
For further examples, you might want to look at :ref:`more
|
For further examples, you might want to look at :ref:`more
|
||||||
parametrization examples <paramexamples>`.
|
parametrization examples <paramexamples>`.
|
||||||
|
|
||||||
|
|
|
@ -118,6 +118,12 @@ You can use the ``skipif`` marker (as any other marker) on classes::
|
||||||
If the condition is ``True``, this marker will produce a skip result for
|
If the condition is ``True``, this marker will produce a skip result for
|
||||||
each of the test methods of that class.
|
each of the test methods of that class.
|
||||||
|
|
||||||
|
.. warning::
|
||||||
|
|
||||||
|
The use of ``skipif`` on classes that use inheritance is strongly
|
||||||
|
discouraged. `A Known bug <https://github.com/pytest-dev/pytest/issues/568>`_
|
||||||
|
in pytest's markers may cause unexpected behavior in super classes.
|
||||||
|
|
||||||
If you want to skip all test functions of a module, you may use
|
If you want to skip all test functions of a module, you may use
|
||||||
the ``pytestmark`` name on the global level:
|
the ``pytestmark`` name on the global level:
|
||||||
|
|
||||||
|
@ -346,5 +352,3 @@ test instances when using parametrize:
|
||||||
])
|
])
|
||||||
def test_increment(n, expected):
|
def test_increment(n, expected):
|
||||||
assert n + 1 == expected
|
assert n + 1 == expected
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -391,7 +391,6 @@ def test_deindent():
|
||||||
assert lines == ['', 'def f():', ' def g():', ' pass', ' ']
|
assert lines == ['', 'def f():', ' def g():', ' pass', ' ']
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.xfail("sys.version_info[:3] < (2,7,0)")
|
|
||||||
def test_source_of_class_at_eof_without_newline(tmpdir):
|
def test_source_of_class_at_eof_without_newline(tmpdir):
|
||||||
# this test fails because the implicit inspect.getsource(A) below
|
# this test fails because the implicit inspect.getsource(A) below
|
||||||
# does not return the "x = 1" last line.
|
# does not return the "x = 1" last line.
|
||||||
|
|
|
@ -841,7 +841,7 @@ class TestConftestCustomization(object):
|
||||||
def pytest_pycollect_makeitem():
|
def pytest_pycollect_makeitem():
|
||||||
outcome = yield
|
outcome = yield
|
||||||
if outcome.excinfo is None:
|
if outcome.excinfo is None:
|
||||||
result = outcome.result
|
result = outcome.get_result()
|
||||||
if result:
|
if result:
|
||||||
for func in result:
|
for func in result:
|
||||||
func._some123 = "world"
|
func._some123 = "world"
|
||||||
|
|
|
@ -82,7 +82,7 @@ class TestArgComplete(object):
|
||||||
from _pytest._argcomplete import FastFilesCompleter
|
from _pytest._argcomplete import FastFilesCompleter
|
||||||
ffc = FastFilesCompleter()
|
ffc = FastFilesCompleter()
|
||||||
fc = FilesCompleter()
|
fc = FilesCompleter()
|
||||||
for x in '/ /d /data qqq'.split():
|
for x in ['/', '/d', '/data', 'qqq', '']:
|
||||||
assert equal_with_bash(x, ffc, fc, out=py.std.sys.stdout)
|
assert equal_with_bash(x, ffc, fc, out=py.std.sys.stdout)
|
||||||
|
|
||||||
@pytest.mark.skipif("sys.platform in ('win32', 'darwin')")
|
@pytest.mark.skipif("sys.platform in ('win32', 'darwin')")
|
||||||
|
|
|
@ -812,3 +812,15 @@ def test_legacy_transfer():
|
||||||
assert fake_method.fun
|
assert fake_method.fun
|
||||||
# pristine marks dont transfer
|
# pristine marks dont transfer
|
||||||
assert fake_method.pytestmark == [pytest.mark.fun.mark]
|
assert fake_method.pytestmark == [pytest.mark.fun.mark]
|
||||||
|
|
||||||
|
|
||||||
|
class TestMarkDecorator(object):
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('lhs, rhs, expected', [
|
||||||
|
(pytest.mark.foo(), pytest.mark.foo(), True),
|
||||||
|
(pytest.mark.foo(), pytest.mark.bar(), False),
|
||||||
|
(pytest.mark.foo(), 'bar', False),
|
||||||
|
('foo', pytest.mark.bar(), False)
|
||||||
|
])
|
||||||
|
def test__eq__(self, lhs, rhs, expected):
|
||||||
|
assert (lhs == rhs) == expected
|
||||||
|
|
13
tox.ini
13
tox.ini
|
@ -12,7 +12,7 @@ envlist =
|
||||||
py36
|
py36
|
||||||
py37
|
py37
|
||||||
pypy
|
pypy
|
||||||
{py27,py35}-{pexpect,xdist,trial,numpy,pluggymaster}
|
{py27,py36}-{pexpect,xdist,trial,numpy,pluggymaster}
|
||||||
py27-nobyte
|
py27-nobyte
|
||||||
doctesting
|
doctesting
|
||||||
py35-freeze
|
py35-freeze
|
||||||
|
@ -37,7 +37,6 @@ deps =
|
||||||
|
|
||||||
[testenv:py27-subprocess]
|
[testenv:py27-subprocess]
|
||||||
changedir = .
|
changedir = .
|
||||||
basepython = python2.7
|
|
||||||
deps =
|
deps =
|
||||||
pytest-xdist>=1.13
|
pytest-xdist>=1.13
|
||||||
mock
|
mock
|
||||||
|
@ -68,7 +67,7 @@ deps =
|
||||||
commands =
|
commands =
|
||||||
pytest -n1 -ra {posargs:testing}
|
pytest -n1 -ra {posargs:testing}
|
||||||
|
|
||||||
[testenv:py35-xdist]
|
[testenv:py36-xdist]
|
||||||
deps = {[testenv:py27-xdist]deps}
|
deps = {[testenv:py27-xdist]deps}
|
||||||
commands =
|
commands =
|
||||||
pytest -n3 -ra {posargs:testing}
|
pytest -n3 -ra {posargs:testing}
|
||||||
|
@ -80,7 +79,7 @@ deps = pexpect
|
||||||
commands =
|
commands =
|
||||||
pytest -ra test_pdb.py test_terminal.py test_unittest.py
|
pytest -ra test_pdb.py test_terminal.py test_unittest.py
|
||||||
|
|
||||||
[testenv:py35-pexpect]
|
[testenv:py36-pexpect]
|
||||||
changedir = testing
|
changedir = testing
|
||||||
platform = linux|darwin
|
platform = linux|darwin
|
||||||
deps = {[testenv:py27-pexpect]deps}
|
deps = {[testenv:py27-pexpect]deps}
|
||||||
|
@ -102,7 +101,7 @@ deps = twisted
|
||||||
commands =
|
commands =
|
||||||
pytest -ra {posargs:testing/test_unittest.py}
|
pytest -ra {posargs:testing/test_unittest.py}
|
||||||
|
|
||||||
[testenv:py35-trial]
|
[testenv:py36-trial]
|
||||||
deps = {[testenv:py27-trial]deps}
|
deps = {[testenv:py27-trial]deps}
|
||||||
commands =
|
commands =
|
||||||
pytest -ra {posargs:testing/test_unittest.py}
|
pytest -ra {posargs:testing/test_unittest.py}
|
||||||
|
@ -112,7 +111,7 @@ deps=numpy
|
||||||
commands=
|
commands=
|
||||||
pytest -ra {posargs:testing/python/approx.py}
|
pytest -ra {posargs:testing/python/approx.py}
|
||||||
|
|
||||||
[testenv:py35-numpy]
|
[testenv:py36-numpy]
|
||||||
deps=numpy
|
deps=numpy
|
||||||
commands=
|
commands=
|
||||||
pytest -ra {posargs:testing/python/approx.py}
|
pytest -ra {posargs:testing/python/approx.py}
|
||||||
|
@ -198,7 +197,6 @@ commands =
|
||||||
[testenv:coveralls]
|
[testenv:coveralls]
|
||||||
passenv = TRAVIS TRAVIS_JOB_ID TRAVIS_BRANCH COVERALLS_REPO_TOKEN
|
passenv = TRAVIS TRAVIS_JOB_ID TRAVIS_BRANCH COVERALLS_REPO_TOKEN
|
||||||
usedevelop = True
|
usedevelop = True
|
||||||
basepython = python3.5
|
|
||||||
changedir = .
|
changedir = .
|
||||||
deps =
|
deps =
|
||||||
{[testenv]deps}
|
{[testenv]deps}
|
||||||
|
@ -218,6 +216,7 @@ python_files = test_*.py *_test.py testing/*/*.py
|
||||||
python_classes = Test Acceptance
|
python_classes = Test Acceptance
|
||||||
python_functions = test
|
python_functions = test
|
||||||
norecursedirs = .tox ja .hg cx_freeze_source
|
norecursedirs = .tox ja .hg cx_freeze_source
|
||||||
|
xfail_strict=true
|
||||||
filterwarnings =
|
filterwarnings =
|
||||||
error
|
error
|
||||||
# produced by path.local
|
# produced by path.local
|
||||||
|
|
Loading…
Reference in New Issue