Compare commits

...

63 Commits
3.2.1 ... 3.2.3

Author SHA1 Message Date
Bruno Oliveira
6b91bc88de Preparing release version 3.2.3 2017-10-03 21:42:34 +00:00
Bruno Oliveira
6690b8a444 Merge pull request #2807 from xuanluong/issue-1442-mention-not--k-help
[doc] Add example of -k 'not test' in help text
2017-10-01 14:32:34 -03:00
Xuan Luong
7093d8f65e Add example of -k 'not test' in help text 2017-09-30 18:43:20 -04:00
Bruno Oliveira
966391c77e Merge pull request #2789 from Avira/master
Don't crash if an item has no _fixtureinfo attribute
2017-09-19 17:34:43 -03:00
Bruno Oliveira
9c8847a0cb Merge pull request #2792 from Avira/fix-tox-docs-link
fix tox documentation link
2017-09-19 12:31:21 -03:00
Oliver Bestwalter
58aaabbb10 fix tox documentation link 2017-09-19 16:57:16 +02:00
Oliver Bestwalter
2802135741 fix 'DoctestItem' object has no attribute '_fixtureinfo'
* doxtests don't seem to have this attribute, so nothing will be written in that case.
* tried to be a good boy scout and tidied up surrounding code a bit (comments, shadowed/unused names, removed random new lines, naming things)
2017-09-19 12:41:12 +02:00
Ronny Pfannschmidt
bf77daa2ee Merge pull request #2785 from nicoddemus/py36
Change to py36 as main environment for Python 3 environments in tox
2017-09-17 09:19:06 +02:00
Bruno Oliveira
9933635cf7 Change to py36 as main environment for Python 3 environments in tox
This also has the benefit of working around Travis recent failures
in Python 3.5 environments.
2017-09-16 19:18:07 -03:00
Bruno Oliveira
ac5c5cc1ef Merge pull request #2750 from evanunderscore/fix-filescompleter
Fix crash in FastFilesCompleter with no prefix
2017-09-14 20:11:43 -03:00
Bruno Oliveira
810320f591 Small fixes to development_guide: title and label names
* Fix title to use a proper "title" section marker
* Fix labels by adding a " " after the ":"
* Fix OS labels after obvious mishap
* Sort labels
2017-09-14 19:58:56 -03:00
Bruno Oliveira
25d2acbdb2 Merge pull request #2760 from nicoddemus/labels
Add development guide to docs
2017-09-14 19:20:45 -03:00
Bruno Oliveira
52c134aed3 Add development guide to docs 2017-09-13 19:32:40 -03:00
Ronny Pfannschmidt
70cdfaf661 Merge pull request #2754 from nicoddemus/xfail_strict
Set xfail_strict=True in pytest's own test suite
2017-09-13 09:01:32 +02:00
Bruno Oliveira
abfd9774ef Remove xfail mark from passing test in py26 2017-09-12 17:59:09 -03:00
Bruno Oliveira
e57cc55719 Merge pull request #2766 from xuanluong/issue-1548-docs-multiple-calls-metafunc-parametrize
Update documentation on multiple calls of metafunc.parametrize
2017-09-10 02:07:06 -03:00
Xuan Luong
696c702da7 Update documentation on multiple calls of metafunc.parametrize 2017-09-10 00:23:23 -04:00
Bruno Oliveira
bee2c864d8 Merge pull request #2765 from xuanluong/pass-callable-to-marker-typo
Fix typo in example of passing a callable to markers
2017-09-09 21:03:13 -03:00
Xuan Luong
e27a0d69aa Rename changelog file to PR id number 2017-09-09 18:26:15 -04:00
Xuan Luong
15222ceca2 Fix typo in example of passing a callable to markers 2017-09-09 18:22:23 -04:00
Bruno Oliveira
3c1ca03b9c Merge pull request #2763 from jhamman/docs/skipif_class_warning
add warning to skipping docs re marker inheritance
2017-09-09 15:15:47 -03:00
Ronny Pfannschmidt
25ed4edbc7 Merge pull request #2764 from xuanluong/issue-2758-fix-mark-decorator-equality
[bugfix] Checking MarkDecorator equality returns False for non-MarkDecorator object
2017-09-09 10:03:49 +02:00
Xuan Luong
1e93089165 [bugfix] Checking MarkDecorator equality returns False for non-MarkDecorator object 2017-09-09 01:31:08 -04:00
Joe Hamman
b2a8e06e4f add warning to skipping docs re marker inheritance 2017-09-08 12:01:33 -07:00
Bruno Oliveira
09349c344e Merge pull request #2757 from nicoddemus/release-3.2.2
Preparing release version 3.2.2
2017-09-07 13:54:31 -03:00
Evan
6cf515b164 Fix crash in FastFilesCompleter with no prefix 2017-09-08 00:14:56 +10:00
Bruno Oliveira
c52f87ede3 Preparing release version 3.2.2 2017-09-06 21:37:57 +00:00
Bruno Oliveira
549f5c1a47 Merge pull request #2736 from xuanluong/issue-2604-documents-mark.with_args
[DOC] Add examples for mark.with_args
2017-09-06 16:33:01 -03:00
Xuan Luong
3f8ff7f090 [DOC] Add examples for mark.with_args 2017-09-06 14:26:28 -04:00
Ronny Pfannschmidt
ad36407747 Merge pull request #2700 from nicoddemus/staticmethods-fixtures
Allow tests declared as @staticmethod to use fixtures
2017-09-06 08:24:00 +02:00
Bruno Oliveira
10d43bd3bf Set xfail_strict=True in pytest's own test suite
Fix #2722
2017-09-05 19:57:26 -03:00
Bruno Oliveira
1fc185b640 Add comment about possible future refactoring in the fixture mechanism 2017-09-05 19:28:39 -03:00
Ronny Pfannschmidt
181bd60bf9 Merge pull request #2742 from nicoddemus/resultlog-deprecation
Improve user guidance regarding ``--resultlog`` deprecation
2017-09-01 08:29:41 +02:00
Bruno Oliveira
3288c9a110 Improve user guidance regarding `--resultlog` deprecation
Fix #2739
2017-08-31 19:11:41 -03:00
Ronny Pfannschmidt
5e00549ecc Merge pull request #2735 from fgmacedo/fgm-fix-reprfuncargs-toterminal
2731.bug Fix ReprFuncArgs with mixed unicode and utf-8 args.
2017-08-31 09:36:56 +02:00
Ronny Pfannschmidt
b770a32dc8 Merge pull request #2707 from cybergrind/fix_baseexception
Catch BaseException in safe_getattr
2017-08-31 09:35:07 +02:00
Bruno Oliveira
f9157b1b6b Improve CHANGELOG entry to be more user-friendly 2017-08-30 21:21:44 -03:00
Bruno Oliveira
f4e811afc0 Merge remote-tracking branch 'upstream/master' into cybergrind/fix_baseexception 2017-08-30 21:11:22 -03:00
Fernando Macedo
59cdef92be fixes #2731 ReprFuncArgs with mixed unicode and utf-8 args 2017-08-30 16:06:12 -03:00
Bruno Oliveira
709b8b65a4 Merge pull request #2721 from josepht/patch-1
Fix typo in goodpractices.rst
2017-08-29 22:08:20 -03:00
Bruno Oliveira
0824076e11 Merge pull request #2710 from massich/raises_match_doc
[DOC] update raises documentation regarding regex match
2017-08-29 21:01:27 -03:00
Joe Talbott
67161ee9f8 Add changelog item for PR #2721. 2017-08-25 10:06:45 -04:00
Joe Talbott
1c891d7d97 Fix typo in goodpractices.rst 2017-08-25 10:01:24 -04:00
Kirill Pinchuk
12b1bff6c5 compat.safe_getattr now catches OutcomeExceptions too 2017-08-23 17:17:03 +03:00
Joan Massich
657976e98a update raises documentation regarding regex match 2017-08-22 12:12:48 +02:00
Bruno Oliveira
a993add783 Allow tests declared as @staticmethod to use fixtures
Fix #2699
2017-08-17 20:44:19 -03:00
Ronny Pfannschmidt
539523cfee Merge pull request #2697 from nicoddemus/match-kw-version
Update docs: ``match`` keyword was introduced in 3.1
2017-08-17 14:41:55 +02:00
Bruno Oliveira
f18780ed8a Update docs: `match` keyword was introduced in 3.1
Also update the text to recommend using the context-manager
over the callable/string forms.
2017-08-16 14:28:34 -03:00
Ronny Pfannschmidt
806d47b4d4 Merge pull request #2691 from anhiga/trivial_error
Fixed error in 'Good Practices' code snippet
2017-08-16 09:50:32 +02:00
Bruno Oliveira
bfc9f61482 Update the number of plugins in index.rst 2017-08-15 23:05:23 -03:00
Antonio Hidalgo
2a99d82c3b Fixed error in 'Good Practices' code snippet 2017-08-16 00:26:14 +02:00
Ronny Pfannschmidt
9b2753b302 Merge pull request #2687 from nicoddemus/use-py36-ci
Use 3.6 as preferred Python 3 interpreter for CI
2017-08-15 10:49:39 +02:00
Bruno Oliveira
e9bfccdf2d Merge pull request #2678 from jespino/fix/2676
Add default values documentation for python_files, python_classes and python_functions
2017-08-14 20:29:39 -03:00
Bruno Oliveira
7b5d26c1a8 Use py36 as preferred Python 3 interpreter for CI testing 2017-08-14 20:27:28 -03:00
Bruno Oliveira
362b1b3c4f Use tox release candidates in CI
Fix #2683
2017-08-14 19:19:20 -03:00
Ronny Pfannschmidt
5c0c1977e3 Merge pull request #2682 from pelme/getfuncargvalue-fix
Use the correct stacklevel for getfuncargvalue() deprecation warning.
2017-08-13 18:24:39 +02:00
Andreas Pelme
39331856ed Use the correct stacklevel for getfuncargvalue() deprecation warning.
Fixed #2681.
2017-08-13 14:59:33 +02:00
Jesús Espino
dc9154e8ff Add default values documentation for python_files, python_classes and python_functions 2017-08-12 12:29:13 +02:00
Bruno Oliveira
021fba4e84 Update number of plugins on README and poiint to plugincompat link 2017-08-10 21:15:22 -03:00
Bruno Oliveira
fd84c886ee Merge pull request #2671 from nicoddemus/release-3.2.1
Release 3.2.1
2017-08-09 17:15:21 -03:00
Bruno Oliveira
e6020781f6 Merge pull request #2653 from felipedau/slow-sharing-note
Add note on sharing the `slow` marker in the basic examples
2017-08-09 08:18:26 -03:00
Felipe Dau
acd3c4fbc4 Update changelog for #2653 2017-08-09 02:57:36 +00:00
Felipe Dau
c847b83d56 Use pytest_collection_modifyitems() in the run/skip option example 2017-08-09 02:51:07 +00:00
41 changed files with 540 additions and 104 deletions

View File

@@ -1,9 +1,10 @@
sudo: false
language: python
python:
- '3.5'
- '3.6'
# command to install dependencies
install: "pip install -U tox"
install:
- pip install --upgrade --pre tox
# # command to run tests
env:
matrix:
@@ -13,18 +14,17 @@ env:
- TOXENV=linting
- TOXENV=py27
- TOXENV=py34
- TOXENV=py35
- TOXENV=py36
- TOXENV=py27-pexpect
- TOXENV=py27-xdist
- TOXENV=py27-trial
- TOXENV=py27-numpy
- TOXENV=py35-pexpect
- TOXENV=py35-xdist
- TOXENV=py35-trial
- TOXENV=py35-numpy
- TOXENV=py36-pexpect
- TOXENV=py36-xdist
- TOXENV=py36-trial
- TOXENV=py36-numpy
- TOXENV=py27-nobyte
- TOXENV=doctesting
- TOXENV=freeze
- TOXENV=docs
matrix:
@@ -35,8 +35,10 @@ matrix:
python: '3.3'
- env: TOXENV=pypy
python: 'pypy-5.4'
- env: TOXENV=py36
python: '3.6'
- env: TOXENV=py35
python: '3.5'
- env: TOXENV=py35-freeze
python: '3.5'
- env: TOXENV=py37
python: 'nightly'
allow_failures:

View File

@@ -173,5 +173,6 @@ Vidar T. Fauske
Vitaly Lashmanov
Vlad Dragos
Wouter van Ackooy
Xuan Luong
Xuecong Liao
Zoltán Máté

View File

@@ -8,6 +8,93 @@
.. towncrier release notes start
Pytest 3.2.3 (2017-10-03)
=========================
Bug Fixes
---------
- Fix crash in tab completion when no prefix is given. (`#2748
<https://github.com/pytest-dev/pytest/issues/2748>`_)
- The equality checking function (``__eq__``) of ``MarkDecorator`` returns
``False`` if one object is not an instance of ``MarkDecorator``. (`#2758
<https://github.com/pytest-dev/pytest/issues/2758>`_)
- When running ``pytest --fixtures-per-test``: don't crash if an item has no
_fixtureinfo attribute (e.g. doctests) (`#2788
<https://github.com/pytest-dev/pytest/issues/2788>`_)
Improved Documentation
----------------------
- In help text of ``-k`` option, add example of using ``not`` to not select
certain tests whose names match the provided expression. (`#1442
<https://github.com/pytest-dev/pytest/issues/1442>`_)
- Add note in ``parametrize.rst`` about calling ``metafunc.parametrize``
multiple times. (`#1548 <https://github.com/pytest-dev/pytest/issues/1548>`_)
Trivial/Internal Changes
------------------------
- Set ``xfail_strict=True`` in pytest's own test suite to catch expected
failures as soon as they start to pass. (`#2722
<https://github.com/pytest-dev/pytest/issues/2722>`_)
- Fix typo in example of passing a callable to markers (in example/markers.rst)
(`#2765 <https://github.com/pytest-dev/pytest/issues/2765>`_)
Pytest 3.2.2 (2017-09-06)
=========================
Bug Fixes
---------
- Calling the deprecated `request.getfuncargvalue()` now shows the source of
the call. (`#2681 <https://github.com/pytest-dev/pytest/issues/2681>`_)
- Allow tests declared as ``@staticmethod`` to use fixtures. (`#2699
<https://github.com/pytest-dev/pytest/issues/2699>`_)
- Fixed edge-case during collection: attributes which raised ``pytest.fail``
when accessed would abort the entire collection. (`#2707
<https://github.com/pytest-dev/pytest/issues/2707>`_)
- Fix ``ReprFuncArgs`` with mixed unicode and UTF-8 args. (`#2731
<https://github.com/pytest-dev/pytest/issues/2731>`_)
Improved Documentation
----------------------
- In examples on working with custom markers, add examples demonstrating the
usage of ``pytest.mark.MARKER_NAME.with_args`` in comparison with
``pytest.mark.MARKER_NAME.__call__`` (`#2604
<https://github.com/pytest-dev/pytest/issues/2604>`_)
- In one of the simple examples, use `pytest_collection_modifyitems()` to skip
tests based on a command-line option, allowing its sharing while preventing a
user error when acessing `pytest.config` before the argument parsing. (`#2653
<https://github.com/pytest-dev/pytest/issues/2653>`_)
Trivial/Internal Changes
------------------------
- Fixed minor error in 'Good Practices/Manual Integration' code snippet.
(`#2691 <https://github.com/pytest-dev/pytest/issues/2691>`_)
- Fixed typo in goodpractices.rst. (`#2721
<https://github.com/pytest-dev/pytest/issues/2721>`_)
- Improve user guidance regarding ``--resultlog`` deprecation. (`#2739
<https://github.com/pytest-dev/pytest/issues/2739>`_)
Pytest 3.2.1 (2017-08-08)
=========================

View File

@@ -120,7 +120,7 @@ the following:
- PyPI presence with a ``setup.py`` that contains a license, ``pytest-``
prefixed name, version number, authors, short and long description.
- a ``tox.ini`` for running tests using `tox <http://tox.testrun.org>`_.
- a ``tox.ini`` for running tests using `tox <https://tox.readthedocs.io>`_.
- a ``README.txt`` describing how to use the plugin and on which
platforms it runs.

View File

@@ -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>`_.

View File

@@ -78,7 +78,7 @@ Features
- Python2.6+, Python3.3+, PyPy-2.3, Jython-2.5 (untested);
- Rich plugin architecture, with over 150+ `external plugins <http://docs.pytest.org/en/latest/plugins.html#installing-external-plugins-searching>`_ and thriving community;
- Rich plugin architecture, with over 315+ `external plugins <http://plugincompat.herokuapp.com>`_ and thriving community;
Documentation

View File

@@ -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

View File

@@ -863,7 +863,7 @@ class ReprFuncArgs(TerminalRepr):
if self.args:
linesofar = ""
for name, value in self.args:
ns = "%s = %s" % (name, value)
ns = "%s = %s" % (safe_str(name), safe_str(value))
if len(ns) + len(linesofar) + 2 > tw.fullwidth:
if linesofar:
tw.line(linesofar)

View File

@@ -11,6 +11,7 @@ import functools
import py
import _pytest
from _pytest.outcomes import TEST_OUTCOME
try:
@@ -82,7 +83,15 @@ def num_mock_patch_args(function):
return len(patchings)
def getfuncargnames(function, startindex=None):
def getfuncargnames(function, startindex=None, cls=None):
"""
@RonnyPfannschmidt: This function should be refactored when we revisit fixtures. The
fixture mechanism should ask the node for the fixture names, and not try to obtain
directly from the function object well after collection has occurred.
"""
if startindex is None and cls is not None:
is_staticmethod = isinstance(cls.__dict__.get(function.__name__, None), staticmethod)
startindex = 0 if is_staticmethod else 1
# XXX merge with main.py's varnames
# assert not isclass(function)
realfunction = function
@@ -221,14 +230,16 @@ def getimfunc(func):
def safe_getattr(object, name, default):
""" Like getattr but return default upon any Exception.
""" Like getattr but return default upon any Exception or any OutcomeException.
Attribute access can potentially fail for 'evil' Python objects.
See issue #214.
It catches OutcomeException because of #2490 (issue #580), new outcomes are derived from BaseException
instead of Exception (for more details check #2707)
"""
try:
return getattr(object, name, default)
except Exception:
except TEST_OUTCOME:
return default

View File

@@ -26,7 +26,10 @@ SETUP_CFG_PYTEST = '[pytest] section in setup.cfg files is deprecated, use [tool
GETFUNCARGVALUE = "use of getfuncargvalue is deprecated, use getfixturevalue"
RESULT_LOG = '--result-log is deprecated and scheduled for removal in pytest 4.0'
RESULT_LOG = (
'--result-log is deprecated and scheduled for removal in pytest 4.0.\n'
'See https://docs.pytest.org/en/latest/usage.html#creating-resultlog-format-files for more information.'
)
MARK_INFO_ATTRIBUTE = RemovedInPytest4Warning(
"MarkInfo objects are deprecated as they contain the merged marks"

View File

@@ -432,7 +432,8 @@ class FixtureRequest(FuncargnamesCompatAttr):
from _pytest import deprecated
warnings.warn(
deprecated.GETFUNCARGVALUE,
DeprecationWarning)
DeprecationWarning,
stacklevel=2)
return self.getfixturevalue(argname)
def _get_active_fixturedef(self, argname):
@@ -956,11 +957,7 @@ class FixtureManager:
def getfixtureinfo(self, node, func, cls, funcargs=True):
if funcargs and not hasattr(node, "nofuncargs"):
if cls is not None:
startindex = 1
else:
startindex = None
argnames = getfuncargnames(func, startindex)
argnames = getfuncargnames(func, cls=cls)
else:
argnames = ()
usefixtures = getattr(func, "usefixtures", None)

View File

@@ -91,7 +91,8 @@ def pytest_addoption(parser):
"where all names are substring-matched against test names "
"and their parent classes. Example: -k 'test_method or test_"
"other' matches all test functions and classes whose name "
"contains 'test_method' or 'test_other'. "
"contains 'test_method' or 'test_other', while -k 'not test_method' "
"matches those that don't contain 'test_method' in their names. "
"Additionally keywords are matched to classes and functions "
"containing extra names in their 'extra_keyword_matches' set, "
"as well as functions which have names assigned directly to them."
@@ -330,7 +331,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,)

View File

@@ -979,50 +979,48 @@ def _show_fixtures_per_test(config, session):
tw = _pytest.config.create_terminal_writer(config)
verbose = config.getvalue("verbose")
def get_best_rel(func):
def get_best_relpath(func):
loc = getlocation(func, curdir)
return curdir.bestrelpath(loc)
def write_fixture(fixture_def):
argname = fixture_def.argname
if verbose <= 0 and argname.startswith("_"):
return
if verbose > 0:
bestrel = get_best_rel(fixture_def.func)
bestrel = get_best_relpath(fixture_def.func)
funcargspec = "{0} -- {1}".format(argname, bestrel)
else:
funcargspec = argname
tw.line(funcargspec, green=True)
fixture_doc = fixture_def.func.__doc__
if fixture_doc:
write_docstring(tw, fixture_doc)
else:
tw.line(' no docstring available', red=True)
def write_item(item):
name2fixturedefs = item._fixtureinfo.name2fixturedefs
if not name2fixturedefs:
# The given test item does not use any fixtures
try:
info = item._fixtureinfo
except AttributeError:
# doctests items have no _fixtureinfo attribute
return
if not info.name2fixturedefs:
# this test item does not use any fixtures
return
bestrel = get_best_rel(item.function)
tw.line()
tw.sep('-', 'fixtures used by {0}'.format(item.name))
tw.sep('-', '({0})'.format(bestrel))
for argname, fixture_defs in sorted(name2fixturedefs.items()):
assert fixture_defs is not None
if not fixture_defs:
tw.sep('-', '({0})'.format(get_best_relpath(item.function)))
# dict key not used in loop but needed for sorting
for _, fixturedefs in sorted(info.name2fixturedefs.items()):
assert fixturedefs is not None
if not fixturedefs:
continue
# The last fixture def item in the list is expected
# to be the one used by the test item
write_fixture(fixture_defs[-1])
# last item is expected to be the one used by the test item
write_fixture(fixturedefs[-1])
for item in session.items:
write_item(item)
for session_item in session.items:
write_item(session_item)
def showfixtures(config):

View File

@@ -493,7 +493,8 @@ def raises(expected_exception, *args, **kwargs):
...
>>> assert exc_info.type == ValueError
Or you can use the keyword argument ``match`` to assert that the
Since version ``3.1`` you can use the keyword argument ``match`` to assert that the
exception matches a text or regex::
>>> with raises(ValueError, match='must be 0 or None'):
@@ -502,7 +503,12 @@ def raises(expected_exception, *args, **kwargs):
>>> with raises(ValueError, match=r'must be \d+$'):
... raise ValueError("value must be 42")
Or you can specify a callable by passing a to-be-called lambda::
**Legacy forms**
The forms below are fully supported but are discouraged for new code because the
context manager form is regarded as more readable and less error-prone.
It is possible to specify a callable by passing a to-be-called lambda::
>>> raises(ZeroDivisionError, lambda: 1/0)
<ExceptionInfo ...>
@@ -516,11 +522,14 @@ def raises(expected_exception, *args, **kwargs):
>>> raises(ZeroDivisionError, f, x=0)
<ExceptionInfo ...>
A third possibility is to use a string to be executed::
It is also possible to pass a string to be evaluated at runtime::
>>> raises(ZeroDivisionError, "f(0)")
<ExceptionInfo ...>
The string will be evaluated using the same ``locals()`` and ``globals()``
at the moment of the ``raises`` call.
.. autoclass:: _pytest._code.ExceptionInfo
:members:

View File

@@ -21,13 +21,13 @@ environment:
- TOXENV: "py27-xdist"
- TOXENV: "py27-trial"
- TOXENV: "py27-numpy"
- TOXENV: "py35-pexpect"
- TOXENV: "py35-xdist"
- TOXENV: "py35-trial"
- TOXENV: "py35-numpy"
- TOXENV: "py36-pexpect"
- TOXENV: "py36-xdist"
- TOXENV: "py36-trial"
- TOXENV: "py36-numpy"
- TOXENV: "py27-nobyte"
- TOXENV: "doctesting"
- TOXENV: "freeze"
- TOXENV: "py35-freeze"
- TOXENV: "docs"
install:
@@ -36,7 +36,7 @@ install:
- if "%TOXENV%" == "pypy" call scripts\install-pypy.bat
- C:\Python35\python -m pip install tox
- C:\Python36\python -m pip install --upgrade --pre tox
build: false # Not a C# project, build stuff at the test step instead.

View File

@@ -6,6 +6,8 @@ Release announcements
:maxdepth: 2
release-3.2.3
release-3.2.2
release-3.2.1
release-3.2.0
release-3.1.3

View File

@@ -0,0 +1,28 @@
pytest-3.2.2
=======================================
pytest 3.2.2 has just been released to PyPI.
This is a bug-fix release, being a drop-in replacement. To upgrade::
pip install --upgrade pytest
The full changelog is available at http://doc.pytest.org/en/latest/changelog.html.
Thanks to all who contributed to this release, among them:
* Andreas Pelme
* Antonio Hidalgo
* Bruno Oliveira
* Felipe Dau
* Fernando Macedo
* Jesús Espino
* Joan Massich
* Joe Talbott
* Kirill Pinchuk
* Ronny Pfannschmidt
* Xuan Luong
Happy testing,
The pytest Development Team

View File

@@ -0,0 +1,23 @@
pytest-3.2.3
=======================================
pytest 3.2.3 has just been released to PyPI.
This is a bug-fix release, being a drop-in replacement. To upgrade::
pip install --upgrade pytest
The full changelog is available at http://doc.pytest.org/en/latest/changelog.html.
Thanks to all who contributed to this release, among them:
* Bruno Oliveira
* Evan
* Joe Hamman
* Oliver Bestwalter
* Ronny Pfannschmidt
* Xuan Luong
Happy testing,
The pytest Development Team

View File

@@ -119,9 +119,9 @@ exceptions your own code is deliberately raising, whereas using
like documenting unfixed bugs (where the test describes what "should" happen)
or bugs in dependencies.
If you want to test that a regular expression matches on the string
representation of an exception (like the ``TestCase.assertRaisesRegexp`` method
from ``unittest``) you can use the ``ExceptionInfo.match`` method::
Also, the context manager form accepts a ``match`` keyword parameter to test
that a regular expression matches on the string representation of an exception
(like the ``TestCase.assertRaisesRegexp`` method from ``unittest``)::
import pytest
@@ -129,12 +129,11 @@ from ``unittest``) you can use the ``ExceptionInfo.match`` method::
raise ValueError("Exception 123 raised")
def test_match():
with pytest.raises(ValueError) as excinfo:
with pytest.raises(ValueError, match=r'.* 123 .*'):
myfunc()
excinfo.match(r'.* 123 .*')
The regexp parameter of the ``match`` method is matched with the ``re.search``
function. So in the above example ``excinfo.match('123')`` would have worked as
function. So in the above example ``match='123'`` would have worked as
well.

View File

@@ -41,6 +41,7 @@ Full pytest documentation
historical-notes
license
contributing
development_guide
talks
projects
faq

View File

@@ -230,13 +230,16 @@ Builtin configuration file options
.. confval:: python_files
One or more Glob-style file patterns determining which python files
are considered as test modules.
are considered as test modules. By default, pytest will consider
any file matching with ``test_*.py`` and ``*_test.py`` globs as a test
module.
.. confval:: python_classes
One or more name prefixes or glob-style patterns determining which classes
are considered for test collection. Here is an example of how to collect
tests from classes that end in ``Suite``:
are considered for test collection. By default, pytest will consider any
class prefixed with ``Test`` as a test collection. Here is an example of how
to collect tests from classes that end in ``Suite``:
.. code-block:: ini
@@ -251,7 +254,8 @@ Builtin configuration file options
.. confval:: python_functions
One or more name prefixes or glob-patterns determining which test functions
and methods are considered tests. Here is an example of how
and methods are considered tests. By default, pytest will consider any
function prefixed with ``test`` as a test. Here is an example of how
to collect test functions and methods that end in ``_test``:
.. code-block:: ini

View File

@@ -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

View File

@@ -395,6 +395,49 @@ The ``--markers`` option always gives you a list of available markers::
@pytest.mark.trylast: mark a hook implementation function such that the plugin machinery will try to call it last/as late as possible.
.. _`passing callables to custom markers`:
Passing a callable to custom markers
--------------------------------------------
.. regendoc:wipe
Below is the config file that will be used in the next examples::
# content of conftest.py
import sys
def pytest_runtest_setup(item):
marker = item.get_marker('my_marker')
if marker is not None:
for info in marker:
print('Marker info name={} args={} kwars={}'.format(info.name, info.args, info.kwargs))
sys.stdout.flush()
A custom marker can have its argument set, i.e. ``args`` and ``kwargs`` properties, defined by either invoking it as a callable or using ``pytest.mark.MARKER_NAME.with_args``. These two methods achieve the same effect most of the time.
However, if there is a callable as the single positional argument with no keyword arguments, using the ``pytest.mark.MARKER_NAME(c)`` will not pass ``c`` as a positional argument but decorate ``c`` with the custom marker (see :ref:`MarkDecorator <mark>`). Fortunately, ``pytest.mark.MARKER_NAME.with_args`` comes to the rescue::
# content of test_custom_marker.py
import pytest
def hello_world(*args, **kwargs):
return 'Hello World'
@pytest.mark.my_marker.with_args(hello_world)
def test_with_args():
pass
The output is as follows::
$ pytest -q -s
Marker info name=my_marker args=(<function hello_world at 0xdeadbeef>,) kwars={}
.
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 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
----------------------------------------------------

View File

@@ -358,7 +358,7 @@ get on the terminal - we are working on that)::
> int(s)
E ValueError: invalid literal for int() with base 10: 'qwe'
<0-codegen $PYTHON_PREFIX/lib/python3.5/site-packages/_pytest/python_api.py:570>:1: ValueError
<0-codegen $PYTHON_PREFIX/lib/python3.5/site-packages/_pytest/python_api.py:579>:1: ValueError
_______ TestRaises.test_raises_doesnt ________
self = <failure_demo.TestRaises object at 0xdeadbeef>

View File

@@ -127,7 +127,7 @@ Control skipping of tests according to command line option
.. regendoc:wipe
Here is a ``conftest.py`` file adding a ``--runslow`` command
line option to control skipping of ``slow`` marked tests:
line option to control skipping of ``pytest.mark.slow`` marked tests:
.. code-block:: python
@@ -136,7 +136,16 @@ line option to control skipping of ``slow`` marked tests:
import pytest
def pytest_addoption(parser):
parser.addoption("--runslow", action="store_true",
help="run slow tests")
default=False, help="run slow tests")
def pytest_collection_modifyitems(config, items):
if config.getoption("--runslow"):
# --runslow given in cli: do not skip slow tests
return
skip_slow = pytest.mark.skip(reason="need --runslow option to run")
for item in items:
if "slow" in item.keywords:
item.add_marker(skip_slow)
We can now write a test module like this:
@@ -146,17 +155,11 @@ We can now write a test module like this:
import pytest
slow = pytest.mark.skipif(
not pytest.config.getoption("--runslow"),
reason="need --runslow option to run"
)
def test_func_fast():
pass
@slow
@pytest.mark.slow
def test_func_slow():
pass
@@ -170,7 +173,7 @@ and when running it will see a skipped "slow" test::
test_module.py .s
======= short test summary info ========
SKIP [1] test_module.py:14: need --runslow option to run
SKIP [1] test_module.py:8: need --runslow option to run
======= 1 passed, 1 skipped in 0.12 seconds ========

View File

@@ -122,7 +122,7 @@ want to distribute them along with your application::
test_view.py
...
In this scheme, it is easy to your run tests using the ``--pyargs`` option::
In this scheme, it is easy to run your tests using the ``--pyargs`` option::
pytest --pyargs mypkg
@@ -267,7 +267,7 @@ your own setuptools Test command for invoking pytest.
def initialize_options(self):
TestCommand.initialize_options(self)
self.pytest_args = []
self.pytest_args = ''
def run_tests(self):
import shlex

View File

@@ -59,7 +59,7 @@ Features
- Python2.6+, Python3.3+, PyPy-2.3, Jython-2.5 (untested);
- Rich plugin architecture, with over 150+ :ref:`external plugins <extplugins>` and thriving community;
- Rich plugin architecture, with over 315+ `external plugins <http://plugincompat.herokuapp.com>`_ and thriving community;
Documentation

View File

@@ -198,6 +198,9 @@ 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>`.

View File

@@ -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:
@@ -346,5 +352,3 @@ test instances when using parametrize:
])
def test_increment(n, expected):
assert n + 1 == expected

View File

@@ -311,6 +311,13 @@ Creating resultlog format files
This option is rarely used and is scheduled for removal in 4.0.
An alternative for users which still need similar functionality is to use the
`pytest-tap <https://pypi.python.org/pypi/pytest-tap>`_ plugin which provides
a stream of test data.
If you have any concerns, please don't hesitate to
`open an issue <https://github.com/pytest-dev/pytest/issues>`_.
To create plain-text machine-readable result files you can issue::
pytest --resultlog=path

View File

@@ -5,4 +5,4 @@ if "%TOXENV%" == "coveralls" (
exit /b 0
)
)
C:\Python35\python -m tox
C:\Python36\python -m tox

View File

@@ -1,9 +1,11 @@
# coding: utf-8
from __future__ import absolute_import, division, print_function
import sys
import _pytest._code
import py
import pytest
from test_excinfo import TWMock
def test_ne():
@@ -172,3 +174,23 @@ class TestTracebackEntry(object):
source = entry.getsource()
assert len(source) == 6
assert 'assert False' in source[5]
class TestReprFuncArgs(object):
def test_not_raise_exception_with_mixed_encoding(self):
from _pytest._code.code import ReprFuncArgs
tw = TWMock()
args = [
('unicode_string', u"São Paulo"),
('utf8_string', 'S\xc3\xa3o Paulo'),
]
r = ReprFuncArgs(args)
r.toterminal(tw)
if sys.version_info[0] >= 3:
assert tw.lines[0] == 'unicode_string = São Paulo, utf8_string = São Paulo'
else:
assert tw.lines[0] == 'unicode_string = São Paulo, utf8_string = São Paulo'

View File

@@ -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.

View File

@@ -78,4 +78,7 @@ def test_resultlog_is_deprecated(testdir):
pass
''')
result = testdir.runpytest('--result-log=%s' % testdir.tmpdir.join('result.log'))
result.stdout.fnmatch_lines(['*--result-log is deprecated and scheduled for removal in pytest 4.0*'])
result.stdout.fnmatch_lines([
'*--result-log is deprecated and scheduled for removal in pytest 4.0*',
'*See https://docs.pytest.org/*/usage.html#creating-resultlog-format-files for more information*',
])

View File

@@ -147,11 +147,21 @@ class TestClass(object):
])
def test_static_method(self, testdir):
"""Support for collecting staticmethod tests (#2528, #2699)"""
testdir.getmodulecol("""
import pytest
class Test(object):
@staticmethod
def test_something():
pass
@pytest.fixture
def fix(self):
return 1
@staticmethod
def test_fix(fix):
assert fix == 1
""")
result = testdir.runpytest()
if sys.version_info < (2, 7):
@@ -162,8 +172,8 @@ class TestClass(object):
])
else:
result.stdout.fnmatch_lines([
"*collected 1 item*",
"*1 passed in*",
"*collected 2 items*",
"*2 passed in*",
])
def test_setup_teardown_class_as_classmethod(self, testdir):

View File

@@ -29,10 +29,16 @@ def test_getfuncargnames():
def f(self, arg1, arg2="hello"):
pass
@staticmethod
def static(arg1, arg2):
pass
assert fixtures.getfuncargnames(A().f) == ('arg1',)
if sys.version_info < (3, 0):
assert fixtures.getfuncargnames(A.f) == ('arg1',)
assert fixtures.getfuncargnames(A.static, cls=A) == ('arg1', 'arg2')
class TestFillFixtures(object):
def test_fillfuncargs_exposed(self):

View File

@@ -135,3 +135,24 @@ def test_verbose_include_private_fixtures_and_loc(testdir):
'arg3 -- test_verbose_include_private_fixtures_and_loc.py:3',
' arg3 from testmodule',
])
def test_doctest_items(testdir):
testdir.makepyfile('''
def foo():
"""
>>> 1 + 1
2
"""
''')
testdir.maketxtfile('''
>>> 1 + 1
2
''')
result = testdir.runpytest("--fixtures-per-test", "--doctest-modules",
"--doctest-glob=*.txt", "-v")
assert result.ret == 0
result.stdout.fnmatch_lines([
'*collected 2 items*',
])

View File

@@ -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')")

View File

@@ -2,7 +2,8 @@ from __future__ import absolute_import, division, print_function
import sys
import pytest
from _pytest.compat import is_generator, get_real_func
from _pytest.compat import is_generator, get_real_func, safe_getattr
from _pytest.outcomes import OutcomeException
def test_is_generator():
@@ -74,3 +75,27 @@ def test_is_generator_async_syntax(testdir):
""")
result = testdir.runpytest()
result.stdout.fnmatch_lines(['*1 passed*'])
class ErrorsHelper(object):
@property
def raise_exception(self):
raise Exception('exception should be catched')
@property
def raise_fail(self):
pytest.fail('fail should be catched')
def test_helper_failures():
helper = ErrorsHelper()
with pytest.raises(Exception):
helper.raise_exception
with pytest.raises(OutcomeException):
helper.raise_fail
def test_safe_getattr():
helper = ErrorsHelper()
assert safe_getattr(helper, 'raise_exception', 'default') == 'default'
assert safe_getattr(helper, 'raise_fail', 'default') == 'default'

View File

@@ -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

17
tox.ini
View File

@@ -12,10 +12,10 @@ envlist =
py36
py37
pypy
{py27,py35}-{pexpect,xdist,trial,numpy}
{py27,py36}-{pexpect,xdist,trial,numpy}
py27-nobyte
doctesting
freeze
py35-freeze
docs
[testenv]
@@ -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 -rfsxX {posargs:testing}
[testenv:py35-xdist]
[testenv:py36-xdist]
deps = {[testenv:py27-xdist]deps}
commands =
pytest -n3 -rfsxX {posargs:testing}
@@ -80,7 +79,7 @@ deps = pexpect
commands =
pytest -rfsxX 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 -rfsxX {posargs:testing/python/approx.py}
[testenv:py35-numpy]
[testenv:py36-numpy]
deps=numpy
commands=
pytest -rfsxX {posargs:testing/python/approx.py}
@@ -169,7 +168,7 @@ changedir = testing
commands =
{envpython} {envbindir}/py.test-jython -rfsxX {posargs}
[testenv:freeze]
[testenv:py35-freeze]
changedir = testing/freeze
deps = pyinstaller
commands =
@@ -180,7 +179,6 @@ commands =
[testenv:coveralls]
passenv = TRAVIS TRAVIS_JOB_ID TRAVIS_BRANCH COVERALLS_REPO_TOKEN
usedevelop = True
basepython = python3.5
changedir = .
deps =
{[testenv]deps}
@@ -200,6 +198,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