Merge remote-tracking branch 'upstream/master' into features
This commit is contained in:
commit
3ebfb881c9
|
@ -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::
|
||||
|
||||
|
@ -21,7 +25,7 @@ How to release pytest
|
|||
#. Generate docs, changelog, announcements and upload a package to
|
||||
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 you don't have an account, please ask for one.
|
||||
|
@ -49,7 +53,7 @@ How to release pytest
|
|||
|
||||
#. 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``
|
||||
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 = []
|
||||
globbed = []
|
||||
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 + '.*'))
|
||||
prefix += '*'
|
||||
globbed.extend(glob(prefix))
|
||||
|
@ -98,7 +99,7 @@ if os.environ.get('_ARGCOMPLETE'):
|
|||
filescompleter = FastFilesCompleter()
|
||||
|
||||
def try_argcomplete(parser):
|
||||
argcomplete.autocomplete(parser)
|
||||
argcomplete.autocomplete(parser, always_complete_options=False)
|
||||
else:
|
||||
def try_argcomplete(parser):
|
||||
pass
|
||||
|
|
|
@ -326,7 +326,7 @@ class MarkDecorator:
|
|||
return self.name # for backward-compat (2.4.1 had this attr)
|
||||
|
||||
def __eq__(self, other):
|
||||
return self.mark == other.mark
|
||||
return self.mark == other.mark if isinstance(other, MarkDecorator) else False
|
||||
|
||||
def __repr__(self):
|
||||
return "<MarkDecorator %r>" % (self.mark,)
|
||||
|
|
|
@ -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
|
||||
license
|
||||
contributing
|
||||
development_guide
|
||||
talks
|
||||
projects
|
||||
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
|
||||
|
||||
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
|
||||
|
|
|
@ -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
|
||||
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
|
||||
parametrization examples <paramexamples>`.
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@ by calling the ``pytest.skip(reason)`` function:
|
|||
if not valid_config():
|
||||
pytest.skip("unsupported configuration")
|
||||
|
||||
The imperative method is useful when it is not possible to evaluate the skip condition
|
||||
The imperative method is useful when it is not possible to evaluate the skip condition
|
||||
during import time.
|
||||
|
||||
``skipif``
|
||||
|
@ -73,7 +73,7 @@ when run on a Python3.3 interpreter::
|
|||
...
|
||||
|
||||
If the condition evaluates to ``True`` during collection, the test function will be skipped,
|
||||
with the specified reason appearing in the summary when using ``-rs``.
|
||||
with the specified reason appearing in the summary when using ``-rs``.
|
||||
|
||||
You can share ``skipif`` markers between modules. Consider this test module::
|
||||
|
||||
|
@ -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
|
||||
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
|
||||
the ``pytestmark`` name on the global level:
|
||||
|
||||
|
@ -305,12 +311,12 @@ Running it with the report-on-xfail option gives this output::
|
|||
platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y
|
||||
rootdir: $REGENDOC_TMPDIR/example, inifile:
|
||||
collected 7 items
|
||||
|
||||
|
||||
xfail_demo.py xxxxxxx
|
||||
======= short test summary info ========
|
||||
XFAIL xfail_demo.py::test_hello
|
||||
XFAIL xfail_demo.py::test_hello2
|
||||
reason: [NOTRUN]
|
||||
reason: [NOTRUN]
|
||||
XFAIL xfail_demo.py::test_hello3
|
||||
condition: hasattr(os, 'sep')
|
||||
XFAIL xfail_demo.py::test_hello4
|
||||
|
@ -320,7 +326,7 @@ Running it with the report-on-xfail option gives this output::
|
|||
XFAIL xfail_demo.py::test_hello6
|
||||
reason: reason
|
||||
XFAIL xfail_demo.py::test_hello7
|
||||
|
||||
|
||||
======= 7 xfailed in 0.12 seconds ========
|
||||
|
||||
.. _`skip/xfail with parametrize`:
|
||||
|
@ -346,5 +352,3 @@ test instances when using parametrize:
|
|||
])
|
||||
def test_increment(n, expected):
|
||||
assert n + 1 == expected
|
||||
|
||||
|
||||
|
|
|
@ -391,7 +391,6 @@ def test_deindent():
|
|||
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):
|
||||
# this test fails because the implicit inspect.getsource(A) below
|
||||
# does not return the "x = 1" last line.
|
||||
|
|
|
@ -82,7 +82,7 @@ class TestArgComplete(object):
|
|||
from _pytest._argcomplete import FastFilesCompleter
|
||||
ffc = FastFilesCompleter()
|
||||
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)
|
||||
|
||||
@pytest.mark.skipif("sys.platform in ('win32', 'darwin')")
|
||||
|
|
|
@ -812,3 +812,15 @@ def test_legacy_transfer():
|
|||
assert fake_method.fun
|
||||
# pristine marks dont transfer
|
||||
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
|
||||
py37
|
||||
pypy
|
||||
{py27,py35}-{pexpect,xdist,trial,numpy,pluggymaster}
|
||||
{py27,py36}-{pexpect,xdist,trial,numpy,pluggymaster}
|
||||
py27-nobyte
|
||||
doctesting
|
||||
py35-freeze
|
||||
|
@ -37,7 +37,6 @@ deps =
|
|||
|
||||
[testenv:py27-subprocess]
|
||||
changedir = .
|
||||
basepython = python2.7
|
||||
deps =
|
||||
pytest-xdist>=1.13
|
||||
mock
|
||||
|
@ -68,7 +67,7 @@ deps =
|
|||
commands =
|
||||
pytest -n1 -ra {posargs:testing}
|
||||
|
||||
[testenv:py35-xdist]
|
||||
[testenv:py36-xdist]
|
||||
deps = {[testenv:py27-xdist]deps}
|
||||
commands =
|
||||
pytest -n3 -ra {posargs:testing}
|
||||
|
@ -80,7 +79,7 @@ deps = pexpect
|
|||
commands =
|
||||
pytest -ra test_pdb.py test_terminal.py test_unittest.py
|
||||
|
||||
[testenv:py35-pexpect]
|
||||
[testenv:py36-pexpect]
|
||||
changedir = testing
|
||||
platform = linux|darwin
|
||||
deps = {[testenv:py27-pexpect]deps}
|
||||
|
@ -102,7 +101,7 @@ deps = twisted
|
|||
commands =
|
||||
pytest -ra {posargs:testing/test_unittest.py}
|
||||
|
||||
[testenv:py35-trial]
|
||||
[testenv:py36-trial]
|
||||
deps = {[testenv:py27-trial]deps}
|
||||
commands =
|
||||
pytest -ra {posargs:testing/test_unittest.py}
|
||||
|
@ -112,7 +111,7 @@ deps=numpy
|
|||
commands=
|
||||
pytest -ra {posargs:testing/python/approx.py}
|
||||
|
||||
[testenv:py35-numpy]
|
||||
[testenv:py36-numpy]
|
||||
deps=numpy
|
||||
commands=
|
||||
pytest -ra {posargs:testing/python/approx.py}
|
||||
|
@ -198,7 +197,6 @@ commands =
|
|||
[testenv:coveralls]
|
||||
passenv = TRAVIS TRAVIS_JOB_ID TRAVIS_BRANCH COVERALLS_REPO_TOKEN
|
||||
usedevelop = True
|
||||
basepython = python3.5
|
||||
changedir = .
|
||||
deps =
|
||||
{[testenv]deps}
|
||||
|
@ -218,6 +216,7 @@ python_files = test_*.py *_test.py testing/*/*.py
|
|||
python_classes = Test Acceptance
|
||||
python_functions = test
|
||||
norecursedirs = .tox ja .hg cx_freeze_source
|
||||
xfail_strict=true
|
||||
filterwarnings =
|
||||
error
|
||||
# produced by path.local
|
||||
|
|
Loading…
Reference in New Issue