Merge branch 'master' into fix-missing-nodeid-with-pyargs
This commit is contained in:
commit
f0f2d2b861
|
@ -12,4 +12,4 @@ Here's a quick checklist that should be present in PRs:
|
||||||
|
|
||||||
Unless your change is a trivial or a documentation fix (e.g., a typo or reword of a small section) please:
|
Unless your change is a trivial or a documentation fix (e.g., a typo or reword of a small section) please:
|
||||||
|
|
||||||
- [ ] Add yourself to `AUTHORS`;
|
- [ ] Add yourself to `AUTHORS`, in alphabetical order;
|
||||||
|
|
2
AUTHORS
2
AUTHORS
|
@ -46,6 +46,7 @@ Dave Hunt
|
||||||
David Díaz-Barquero
|
David Díaz-Barquero
|
||||||
David Mohr
|
David Mohr
|
||||||
David Vierra
|
David Vierra
|
||||||
|
Daw-Ran Liou
|
||||||
Denis Kirisov
|
Denis Kirisov
|
||||||
Diego Russo
|
Diego Russo
|
||||||
Dmitry Dygalo
|
Dmitry Dygalo
|
||||||
|
@ -164,6 +165,7 @@ Stephan Obermann
|
||||||
Tareq Alayan
|
Tareq Alayan
|
||||||
Ted Xiao
|
Ted Xiao
|
||||||
Thomas Grainger
|
Thomas Grainger
|
||||||
|
Tom Dalton
|
||||||
Tom Viner
|
Tom Viner
|
||||||
Trevor Bekolay
|
Trevor Bekolay
|
||||||
Tyler Goodlet
|
Tyler Goodlet
|
||||||
|
|
|
@ -8,6 +8,46 @@
|
||||||
|
|
||||||
.. towncrier release notes start
|
.. 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)
|
Pytest 3.2.2 (2017-09-06)
|
||||||
=========================
|
=========================
|
||||||
|
|
||||||
|
|
|
@ -120,7 +120,7 @@ the following:
|
||||||
- PyPI presence with a ``setup.py`` that contains a license, ``pytest-``
|
- PyPI presence with a ``setup.py`` that contains a license, ``pytest-``
|
||||||
prefixed name, version number, authors, short and long description.
|
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
|
- a ``README.txt`` describing how to use the plugin and on which
|
||||||
platforms it runs.
|
platforms it runs.
|
||||||
|
@ -177,7 +177,8 @@ Short version
|
||||||
#. Write a ``changelog`` entry: ``changelog/2574.bugfix``, use issue id number
|
#. Write a ``changelog`` entry: ``changelog/2574.bugfix``, use issue id number
|
||||||
and one of ``bugfix``, ``removal``, ``feature``, ``vendor``, ``doc`` or
|
and one of ``bugfix``, ``removal``, ``feature``, ``vendor``, ``doc`` or
|
||||||
``trivial`` for the issue type.
|
``trivial`` for the issue type.
|
||||||
#. Add yourself to ``AUTHORS`` file if not there yet, in alphabetical order.
|
#. Unless your change is a trivial or a documentation fix (e.g., a typo or reword of a small section) please
|
||||||
|
add yourself to the ``AUTHORS`` file, in alphabetical order;
|
||||||
|
|
||||||
|
|
||||||
Long version
|
Long version
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -250,7 +250,7 @@ class TracebackEntry(object):
|
||||||
line = str(self.statement).lstrip()
|
line = str(self.statement).lstrip()
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
raise
|
raise
|
||||||
except:
|
except: # noqa
|
||||||
line = "???"
|
line = "???"
|
||||||
return " File %r:%d in %s\n %s\n" % (fn, self.lineno + 1, name, line)
|
return " File %r:%d in %s\n %s\n" % (fn, self.lineno + 1, name, line)
|
||||||
|
|
||||||
|
@ -338,16 +338,16 @@ class Traceback(list):
|
||||||
# XXX needs a test
|
# XXX needs a test
|
||||||
key = entry.frame.code.path, id(entry.frame.code.raw), entry.lineno
|
key = entry.frame.code.path, id(entry.frame.code.raw), entry.lineno
|
||||||
# print "checking for recursion at", key
|
# print "checking for recursion at", key
|
||||||
l = cache.setdefault(key, [])
|
values = cache.setdefault(key, [])
|
||||||
if l:
|
if values:
|
||||||
f = entry.frame
|
f = entry.frame
|
||||||
loc = f.f_locals
|
loc = f.f_locals
|
||||||
for otherloc in l:
|
for otherloc in values:
|
||||||
if f.is_true(f.eval(co_equal,
|
if f.is_true(f.eval(co_equal,
|
||||||
__recursioncache_locals_1=loc,
|
__recursioncache_locals_1=loc,
|
||||||
__recursioncache_locals_2=otherloc)):
|
__recursioncache_locals_2=otherloc)):
|
||||||
return i
|
return i
|
||||||
l.append(entry.frame.f_locals)
|
values.append(entry.frame.f_locals)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
@ -478,12 +478,12 @@ class FormattedExcinfo(object):
|
||||||
s = str(source.getstatement(len(source) - 1))
|
s = str(source.getstatement(len(source) - 1))
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
raise
|
raise
|
||||||
except:
|
except: # noqa
|
||||||
try:
|
try:
|
||||||
s = str(source[-1])
|
s = str(source[-1])
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
raise
|
raise
|
||||||
except:
|
except: # noqa
|
||||||
return 0
|
return 0
|
||||||
return 4 + (len(s) - len(s.lstrip()))
|
return 4 + (len(s) - len(s.lstrip()))
|
||||||
|
|
||||||
|
|
|
@ -254,7 +254,7 @@ def findsource(obj):
|
||||||
sourcelines, lineno = py.std.inspect.findsource(obj)
|
sourcelines, lineno = py.std.inspect.findsource(obj)
|
||||||
except py.builtin._sysex:
|
except py.builtin._sysex:
|
||||||
raise
|
raise
|
||||||
except:
|
except: # noqa
|
||||||
return None, -1
|
return None, -1
|
||||||
source = Source()
|
source = Source()
|
||||||
source.lines = [line.rstrip() for line in sourcelines]
|
source.lines = [line.rstrip() for line in sourcelines]
|
||||||
|
@ -319,22 +319,22 @@ def get_statement_startend2(lineno, node):
|
||||||
import ast
|
import ast
|
||||||
# flatten all statements and except handlers into one lineno-list
|
# flatten all statements and except handlers into one lineno-list
|
||||||
# AST's line numbers start indexing at 1
|
# AST's line numbers start indexing at 1
|
||||||
l = []
|
values = []
|
||||||
for x in ast.walk(node):
|
for x in ast.walk(node):
|
||||||
if isinstance(x, _ast.stmt) or isinstance(x, _ast.ExceptHandler):
|
if isinstance(x, _ast.stmt) or isinstance(x, _ast.ExceptHandler):
|
||||||
l.append(x.lineno - 1)
|
values.append(x.lineno - 1)
|
||||||
for name in "finalbody", "orelse":
|
for name in "finalbody", "orelse":
|
||||||
val = getattr(x, name, None)
|
val = getattr(x, name, None)
|
||||||
if val:
|
if val:
|
||||||
# treat the finally/orelse part as its own statement
|
# treat the finally/orelse part as its own statement
|
||||||
l.append(val[0].lineno - 1 - 1)
|
values.append(val[0].lineno - 1 - 1)
|
||||||
l.sort()
|
values.sort()
|
||||||
insert_index = bisect_right(l, lineno)
|
insert_index = bisect_right(values, lineno)
|
||||||
start = l[insert_index - 1]
|
start = values[insert_index - 1]
|
||||||
if insert_index >= len(l):
|
if insert_index >= len(values):
|
||||||
end = None
|
end = None
|
||||||
else:
|
else:
|
||||||
end = l[insert_index]
|
end = values[insert_index]
|
||||||
return start, end
|
return start, end
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -210,7 +210,7 @@ class AssertionRewritingHook(object):
|
||||||
mod.__cached__ = pyc
|
mod.__cached__ = pyc
|
||||||
mod.__loader__ = self
|
mod.__loader__ = self
|
||||||
py.builtin.exec_(co, mod.__dict__)
|
py.builtin.exec_(co, mod.__dict__)
|
||||||
except:
|
except: # noqa
|
||||||
if name in sys.modules:
|
if name in sys.modules:
|
||||||
del sys.modules[name]
|
del sys.modules[name]
|
||||||
raise
|
raise
|
||||||
|
@ -595,23 +595,26 @@ class AssertionRewriter(ast.NodeVisitor):
|
||||||
# docstrings and __future__ imports.
|
# docstrings and __future__ imports.
|
||||||
aliases = [ast.alias(py.builtin.builtins.__name__, "@py_builtins"),
|
aliases = [ast.alias(py.builtin.builtins.__name__, "@py_builtins"),
|
||||||
ast.alias("_pytest.assertion.rewrite", "@pytest_ar")]
|
ast.alias("_pytest.assertion.rewrite", "@pytest_ar")]
|
||||||
expect_docstring = True
|
doc = getattr(mod, "docstring", None)
|
||||||
|
expect_docstring = doc is None
|
||||||
|
if doc is not None and self.is_rewrite_disabled(doc):
|
||||||
|
return
|
||||||
pos = 0
|
pos = 0
|
||||||
lineno = 0
|
lineno = 1
|
||||||
for item in mod.body:
|
for item in mod.body:
|
||||||
if (expect_docstring and isinstance(item, ast.Expr) and
|
if (expect_docstring and isinstance(item, ast.Expr) and
|
||||||
isinstance(item.value, ast.Str)):
|
isinstance(item.value, ast.Str)):
|
||||||
doc = item.value.s
|
doc = item.value.s
|
||||||
if "PYTEST_DONT_REWRITE" in doc:
|
if self.is_rewrite_disabled(doc):
|
||||||
# The module has disabled assertion rewriting.
|
|
||||||
return
|
return
|
||||||
lineno += len(doc) - 1
|
|
||||||
expect_docstring = False
|
expect_docstring = False
|
||||||
elif (not isinstance(item, ast.ImportFrom) or item.level > 0 or
|
elif (not isinstance(item, ast.ImportFrom) or item.level > 0 or
|
||||||
item.module != "__future__"):
|
item.module != "__future__"):
|
||||||
lineno = item.lineno
|
lineno = item.lineno
|
||||||
break
|
break
|
||||||
pos += 1
|
pos += 1
|
||||||
|
else:
|
||||||
|
lineno = item.lineno
|
||||||
imports = [ast.Import([alias], lineno=lineno, col_offset=0)
|
imports = [ast.Import([alias], lineno=lineno, col_offset=0)
|
||||||
for alias in aliases]
|
for alias in aliases]
|
||||||
mod.body[pos:pos] = imports
|
mod.body[pos:pos] = imports
|
||||||
|
@ -637,6 +640,9 @@ class AssertionRewriter(ast.NodeVisitor):
|
||||||
not isinstance(field, ast.expr)):
|
not isinstance(field, ast.expr)):
|
||||||
nodes.append(field)
|
nodes.append(field)
|
||||||
|
|
||||||
|
def is_rewrite_disabled(self, docstring):
|
||||||
|
return "PYTEST_DONT_REWRITE" in docstring
|
||||||
|
|
||||||
def variable(self):
|
def variable(self):
|
||||||
"""Get a new variable."""
|
"""Get a new variable."""
|
||||||
# Use a character invalid in python identifiers to avoid clashing.
|
# Use a character invalid in python identifiers to avoid clashing.
|
||||||
|
|
|
@ -53,11 +53,11 @@ def _split_explanation(explanation):
|
||||||
"""
|
"""
|
||||||
raw_lines = (explanation or u('')).split('\n')
|
raw_lines = (explanation or u('')).split('\n')
|
||||||
lines = [raw_lines[0]]
|
lines = [raw_lines[0]]
|
||||||
for l in raw_lines[1:]:
|
for values in raw_lines[1:]:
|
||||||
if l and l[0] in ['{', '}', '~', '>']:
|
if values and values[0] in ['{', '}', '~', '>']:
|
||||||
lines.append(l)
|
lines.append(values)
|
||||||
else:
|
else:
|
||||||
lines[-1] += '\\n' + l
|
lines[-1] += '\\n' + values
|
||||||
return lines
|
return lines
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1170,10 +1170,10 @@ class Config(object):
|
||||||
return []
|
return []
|
||||||
if type == "pathlist":
|
if type == "pathlist":
|
||||||
dp = py.path.local(self.inicfg.config.path).dirpath()
|
dp = py.path.local(self.inicfg.config.path).dirpath()
|
||||||
l = []
|
values = []
|
||||||
for relpath in shlex.split(value):
|
for relpath in shlex.split(value):
|
||||||
l.append(dp.join(relpath, abs=True))
|
values.append(dp.join(relpath, abs=True))
|
||||||
return l
|
return values
|
||||||
elif type == "args":
|
elif type == "args":
|
||||||
return shlex.split(value)
|
return shlex.split(value)
|
||||||
elif type == "linelist":
|
elif type == "linelist":
|
||||||
|
@ -1190,13 +1190,13 @@ class Config(object):
|
||||||
except KeyError:
|
except KeyError:
|
||||||
return None
|
return None
|
||||||
modpath = py.path.local(mod.__file__).dirpath()
|
modpath = py.path.local(mod.__file__).dirpath()
|
||||||
l = []
|
values = []
|
||||||
for relroot in relroots:
|
for relroot in relroots:
|
||||||
if not isinstance(relroot, py.path.local):
|
if not isinstance(relroot, py.path.local):
|
||||||
relroot = relroot.replace("/", py.path.local.sep)
|
relroot = relroot.replace("/", py.path.local.sep)
|
||||||
relroot = modpath.join(relroot, abs=True)
|
relroot = modpath.join(relroot, abs=True)
|
||||||
l.append(relroot)
|
values.append(relroot)
|
||||||
return l
|
return values
|
||||||
|
|
||||||
def _get_override_ini_value(self, name):
|
def _get_override_ini_value(self, name):
|
||||||
value = None
|
value = None
|
||||||
|
|
|
@ -120,7 +120,7 @@ class DoctestItem(pytest.Item):
|
||||||
lines = ["%03d %s" % (i + test.lineno + 1, x)
|
lines = ["%03d %s" % (i + test.lineno + 1, x)
|
||||||
for (i, x) in enumerate(lines)]
|
for (i, x) in enumerate(lines)]
|
||||||
# trim docstring error lines to 10
|
# trim docstring error lines to 10
|
||||||
lines = lines[example.lineno - 9:example.lineno + 1]
|
lines = lines[max(example.lineno - 9, 0):example.lineno + 1]
|
||||||
else:
|
else:
|
||||||
lines = ['EXAMPLE LOCATION UNKNOWN, not showing all tests of that example']
|
lines = ['EXAMPLE LOCATION UNKNOWN, not showing all tests of that example']
|
||||||
indent = '>>>'
|
indent = '>>>'
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
from __future__ import absolute_import, division, print_function
|
from __future__ import absolute_import, division, print_function
|
||||||
import sys
|
|
||||||
|
|
||||||
from py._code.code import FormattedExcinfo
|
|
||||||
|
|
||||||
import py
|
|
||||||
import warnings
|
|
||||||
|
|
||||||
import inspect
|
import inspect
|
||||||
|
import sys
|
||||||
|
import warnings
|
||||||
|
|
||||||
|
import py
|
||||||
|
from py._code.code import FormattedExcinfo
|
||||||
|
|
||||||
import _pytest
|
import _pytest
|
||||||
|
from _pytest import nodes
|
||||||
from _pytest._code.code import TerminalRepr
|
from _pytest._code.code import TerminalRepr
|
||||||
from _pytest.compat import (
|
from _pytest.compat import (
|
||||||
NOTSET, exc_clear, _format_args,
|
NOTSET, exc_clear, _format_args,
|
||||||
|
@ -15,9 +16,10 @@ from _pytest.compat import (
|
||||||
is_generator, isclass, getimfunc,
|
is_generator, isclass, getimfunc,
|
||||||
getlocation, getfuncargnames,
|
getlocation, getfuncargnames,
|
||||||
safe_getattr,
|
safe_getattr,
|
||||||
|
FuncargnamesCompatAttr,
|
||||||
)
|
)
|
||||||
from _pytest.outcomes import fail, TEST_OUTCOME
|
from _pytest.outcomes import fail, TEST_OUTCOME
|
||||||
from _pytest.compat import FuncargnamesCompatAttr
|
|
||||||
|
|
||||||
if sys.version_info[:2] == (2, 6):
|
if sys.version_info[:2] == (2, 6):
|
||||||
from ordereddict import OrderedDict
|
from ordereddict import OrderedDict
|
||||||
|
@ -458,13 +460,13 @@ class FixtureRequest(FuncargnamesCompatAttr):
|
||||||
|
|
||||||
def _get_fixturestack(self):
|
def _get_fixturestack(self):
|
||||||
current = self
|
current = self
|
||||||
l = []
|
values = []
|
||||||
while 1:
|
while 1:
|
||||||
fixturedef = getattr(current, "_fixturedef", None)
|
fixturedef = getattr(current, "_fixturedef", None)
|
||||||
if fixturedef is None:
|
if fixturedef is None:
|
||||||
l.reverse()
|
values.reverse()
|
||||||
return l
|
return values
|
||||||
l.append(fixturedef)
|
values.append(fixturedef)
|
||||||
current = current._parent_request
|
current = current._parent_request
|
||||||
|
|
||||||
def _getfixturevalue(self, fixturedef):
|
def _getfixturevalue(self, fixturedef):
|
||||||
|
@ -573,7 +575,6 @@ class SubRequest(FixtureRequest):
|
||||||
self.param_index = param_index
|
self.param_index = param_index
|
||||||
self.scope = scope
|
self.scope = scope
|
||||||
self._fixturedef = fixturedef
|
self._fixturedef = fixturedef
|
||||||
self.addfinalizer = fixturedef.addfinalizer
|
|
||||||
self._pyfuncitem = request._pyfuncitem
|
self._pyfuncitem = request._pyfuncitem
|
||||||
self._fixture_values = request._fixture_values
|
self._fixture_values = request._fixture_values
|
||||||
self._fixture_defs = request._fixture_defs
|
self._fixture_defs = request._fixture_defs
|
||||||
|
@ -584,6 +585,9 @@ class SubRequest(FixtureRequest):
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<SubRequest %r for %r>" % (self.fixturename, self._pyfuncitem)
|
return "<SubRequest %r for %r>" % (self.fixturename, self._pyfuncitem)
|
||||||
|
|
||||||
|
def addfinalizer(self, finalizer):
|
||||||
|
self._fixturedef.addfinalizer(finalizer)
|
||||||
|
|
||||||
|
|
||||||
class ScopeMismatchError(Exception):
|
class ScopeMismatchError(Exception):
|
||||||
""" A fixture function tries to use a different fixture function which
|
""" A fixture function tries to use a different fixture function which
|
||||||
|
@ -747,7 +751,7 @@ class FixtureDef:
|
||||||
try:
|
try:
|
||||||
func = self._finalizer.pop()
|
func = self._finalizer.pop()
|
||||||
func()
|
func()
|
||||||
except:
|
except: # noqa
|
||||||
exceptions.append(sys.exc_info())
|
exceptions.append(sys.exc_info())
|
||||||
if exceptions:
|
if exceptions:
|
||||||
e = exceptions[0]
|
e = exceptions[0]
|
||||||
|
@ -981,8 +985,8 @@ class FixtureManager:
|
||||||
# by their test id)
|
# by their test id)
|
||||||
if p.basename.startswith("conftest.py"):
|
if p.basename.startswith("conftest.py"):
|
||||||
nodeid = p.dirpath().relto(self.config.rootdir)
|
nodeid = p.dirpath().relto(self.config.rootdir)
|
||||||
if p.sep != "/":
|
if p.sep != nodes.SEP:
|
||||||
nodeid = nodeid.replace(p.sep, "/")
|
nodeid = nodeid.replace(p.sep, nodes.SEP)
|
||||||
self.parsefactories(plugin, nodeid)
|
self.parsefactories(plugin, nodeid)
|
||||||
|
|
||||||
def _getautousenames(self, nodeid):
|
def _getautousenames(self, nodeid):
|
||||||
|
@ -1037,8 +1041,13 @@ class FixtureManager:
|
||||||
if faclist:
|
if faclist:
|
||||||
fixturedef = faclist[-1]
|
fixturedef = faclist[-1]
|
||||||
if fixturedef.params is not None:
|
if fixturedef.params is not None:
|
||||||
func_params = getattr(getattr(metafunc.function, 'parametrize', None), 'args', [[None]])
|
parametrize_func = getattr(metafunc.function, 'parametrize', None)
|
||||||
|
func_params = getattr(parametrize_func, 'args', [[None]])
|
||||||
|
func_kwargs = getattr(parametrize_func, 'kwargs', {})
|
||||||
# skip directly parametrized arguments
|
# skip directly parametrized arguments
|
||||||
|
if "argnames" in func_kwargs:
|
||||||
|
argnames = parametrize_func.kwargs["argnames"]
|
||||||
|
else:
|
||||||
argnames = func_params[0]
|
argnames = func_params[0]
|
||||||
if not isinstance(argnames, (tuple, list)):
|
if not isinstance(argnames, (tuple, list)):
|
||||||
argnames = [x.strip() for x in argnames.split(",") if x.strip()]
|
argnames = [x.strip() for x in argnames.split(",") if x.strip()]
|
||||||
|
@ -1127,5 +1136,5 @@ class FixtureManager:
|
||||||
|
|
||||||
def _matchfactories(self, fixturedefs, nodeid):
|
def _matchfactories(self, fixturedefs, nodeid):
|
||||||
for fixturedef in fixturedefs:
|
for fixturedef in fixturedefs:
|
||||||
if nodeid.startswith(fixturedef.baseid):
|
if nodes.ischildnode(fixturedef.baseid, nodeid):
|
||||||
yield fixturedef
|
yield fixturedef
|
||||||
|
|
|
@ -17,6 +17,7 @@ import re
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
import pytest
|
import pytest
|
||||||
|
from _pytest import nodes
|
||||||
from _pytest.config import filename_arg
|
from _pytest.config import filename_arg
|
||||||
|
|
||||||
# Python 2.X and 3.X compatibility
|
# Python 2.X and 3.X compatibility
|
||||||
|
@ -252,7 +253,7 @@ def mangle_test_address(address):
|
||||||
except ValueError:
|
except ValueError:
|
||||||
pass
|
pass
|
||||||
# convert file path to dotted path
|
# convert file path to dotted path
|
||||||
names[0] = names[0].replace("/", '.')
|
names[0] = names[0].replace(nodes.SEP, '.')
|
||||||
names[0] = _py_ext_re.sub("", names[0])
|
names[0] = _py_ext_re.sub("", names[0])
|
||||||
# put any params back
|
# put any params back
|
||||||
names[-1] += possible_open_bracket + params
|
names[-1] += possible_open_bracket + params
|
||||||
|
|
|
@ -6,6 +6,7 @@ import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
import _pytest
|
import _pytest
|
||||||
|
from _pytest import nodes
|
||||||
import _pytest._code
|
import _pytest._code
|
||||||
import py
|
import py
|
||||||
try:
|
try:
|
||||||
|
@ -14,8 +15,8 @@ except ImportError:
|
||||||
from UserDict import DictMixin as MappingMixin
|
from UserDict import DictMixin as MappingMixin
|
||||||
|
|
||||||
from _pytest.config import directory_arg, UsageError, hookimpl
|
from _pytest.config import directory_arg, UsageError, hookimpl
|
||||||
from _pytest.runner import collect_one_node
|
|
||||||
from _pytest.outcomes import exit
|
from _pytest.outcomes import exit
|
||||||
|
from _pytest.runner import collect_one_node
|
||||||
|
|
||||||
tracebackcutdir = py.path.local(_pytest.__file__).dirpath()
|
tracebackcutdir = py.path.local(_pytest.__file__).dirpath()
|
||||||
|
|
||||||
|
@ -117,7 +118,7 @@ def wrap_session(config, doit):
|
||||||
excinfo.typename, excinfo.value.msg))
|
excinfo.typename, excinfo.value.msg))
|
||||||
config.hook.pytest_keyboard_interrupt(excinfo=excinfo)
|
config.hook.pytest_keyboard_interrupt(excinfo=excinfo)
|
||||||
session.exitstatus = EXIT_INTERRUPTED
|
session.exitstatus = EXIT_INTERRUPTED
|
||||||
except:
|
except: # noqa
|
||||||
excinfo = _pytest._code.ExceptionInfo()
|
excinfo = _pytest._code.ExceptionInfo()
|
||||||
config.notify_exception(excinfo, config.option)
|
config.notify_exception(excinfo, config.option)
|
||||||
session.exitstatus = EXIT_INTERNALERROR
|
session.exitstatus = EXIT_INTERNALERROR
|
||||||
|
@ -374,7 +375,7 @@ class Node(object):
|
||||||
res = function()
|
res = function()
|
||||||
except py.builtin._sysex:
|
except py.builtin._sysex:
|
||||||
raise
|
raise
|
||||||
except:
|
except: # noqa
|
||||||
failure = sys.exc_info()
|
failure = sys.exc_info()
|
||||||
setattr(self, exattrname, failure)
|
setattr(self, exattrname, failure)
|
||||||
raise
|
raise
|
||||||
|
@ -516,7 +517,7 @@ class FSCollector(Collector):
|
||||||
rel = fspath.relto(parent.fspath)
|
rel = fspath.relto(parent.fspath)
|
||||||
if rel:
|
if rel:
|
||||||
name = rel
|
name = rel
|
||||||
name = name.replace(os.sep, "/")
|
name = name.replace(os.sep, nodes.SEP)
|
||||||
super(FSCollector, self).__init__(name, parent, config, session)
|
super(FSCollector, self).__init__(name, parent, config, session)
|
||||||
self.fspath = fspath
|
self.fspath = fspath
|
||||||
|
|
||||||
|
@ -527,10 +528,11 @@ class FSCollector(Collector):
|
||||||
|
|
||||||
def _makeid(self):
|
def _makeid(self):
|
||||||
relpath = self.fspath.relto(self.config.rootdir)
|
relpath = self.fspath.relto(self.config.rootdir)
|
||||||
|
|
||||||
if not relpath:
|
if not relpath:
|
||||||
relpath = self._check_initialpaths_for_relpath()
|
relpath = self._check_initialpaths_for_relpath()
|
||||||
if os.sep != "/":
|
if os.sep != nodes.SEP:
|
||||||
relpath = relpath.replace(os.sep, "/")
|
relpath = relpath.replace(os.sep, nodes.SEP)
|
||||||
return relpath
|
return relpath
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -91,7 +91,8 @@ def pytest_addoption(parser):
|
||||||
"where all names are substring-matched against test names "
|
"where all names are substring-matched against test names "
|
||||||
"and their parent classes. Example: -k 'test_method or test_"
|
"and their parent classes. Example: -k 'test_method or test_"
|
||||||
"other' matches all test functions and classes whose name "
|
"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 "
|
"Additionally keywords are matched to classes and functions "
|
||||||
"containing extra names in their 'extra_keyword_matches' set, "
|
"containing extra names in their 'extra_keyword_matches' set, "
|
||||||
"as well as functions which have names assigned directly to them."
|
"as well as functions which have names assigned directly to them."
|
||||||
|
@ -269,11 +270,12 @@ class MarkGenerator:
|
||||||
return
|
return
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
pass
|
pass
|
||||||
self._markers = l = set()
|
self._markers = values = set()
|
||||||
for line in self._config.getini("markers"):
|
for line in self._config.getini("markers"):
|
||||||
beginning = line.split(":", 1)
|
marker, _ = line.split(":", 1)
|
||||||
x = beginning[0].split("(", 1)[0]
|
marker = marker.rstrip()
|
||||||
l.add(x)
|
x = marker.split("(", 1)[0]
|
||||||
|
values.add(x)
|
||||||
if name not in self._markers:
|
if name not in self._markers:
|
||||||
raise AttributeError("%r not a registered marker" % (name,))
|
raise AttributeError("%r not a registered marker" % (name,))
|
||||||
|
|
||||||
|
@ -382,7 +384,7 @@ def store_mark(obj, mark):
|
||||||
"""
|
"""
|
||||||
assert isinstance(mark, Mark), mark
|
assert isinstance(mark, Mark), mark
|
||||||
# always reassign name to avoid updating pytestmark
|
# always reassign name to avoid updating pytestmark
|
||||||
# in a referene that was only borrowed
|
# in a reference that was only borrowed
|
||||||
obj.pytestmark = get_unpacked_marks(obj) + [mark]
|
obj.pytestmark = get_unpacked_marks(obj) + [mark]
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
SEP = "/"
|
||||||
|
|
||||||
|
|
||||||
|
def _splitnode(nodeid):
|
||||||
|
"""Split a nodeid into constituent 'parts'.
|
||||||
|
|
||||||
|
Node IDs are strings, and can be things like:
|
||||||
|
''
|
||||||
|
'testing/code'
|
||||||
|
'testing/code/test_excinfo.py'
|
||||||
|
'testing/code/test_excinfo.py::TestFormattedExcinfo::()'
|
||||||
|
|
||||||
|
Return values are lists e.g.
|
||||||
|
[]
|
||||||
|
['testing', 'code']
|
||||||
|
['testing', 'code', 'test_excinfo.py']
|
||||||
|
['testing', 'code', 'test_excinfo.py', 'TestFormattedExcinfo', '()']
|
||||||
|
"""
|
||||||
|
if nodeid == '':
|
||||||
|
# If there is no root node at all, return an empty list so the caller's logic can remain sane
|
||||||
|
return []
|
||||||
|
parts = nodeid.split(SEP)
|
||||||
|
# Replace single last element 'test_foo.py::Bar::()' with multiple elements 'test_foo.py', 'Bar', '()'
|
||||||
|
parts[-1:] = parts[-1].split("::")
|
||||||
|
return parts
|
||||||
|
|
||||||
|
|
||||||
|
def ischildnode(baseid, nodeid):
|
||||||
|
"""Return True if the nodeid is a child node of the baseid.
|
||||||
|
|
||||||
|
E.g. 'foo/bar::Baz::()' is a child of 'foo', 'foo/bar' and 'foo/bar::Baz', but not of 'foo/blorp'
|
||||||
|
"""
|
||||||
|
base_parts = _splitnode(baseid)
|
||||||
|
node_parts = _splitnode(nodeid)
|
||||||
|
if len(node_parts) < len(base_parts):
|
||||||
|
return False
|
||||||
|
return node_parts[:len(base_parts)] == base_parts
|
|
@ -182,9 +182,9 @@ class PytestArg:
|
||||||
return hookrecorder
|
return hookrecorder
|
||||||
|
|
||||||
|
|
||||||
def get_public_names(l):
|
def get_public_names(values):
|
||||||
"""Only return names from iterator l without a leading underscore."""
|
"""Only return names from iterator values without a leading underscore."""
|
||||||
return [x for x in l if x[0] != "_"]
|
return [x for x in values if x[0] != "_"]
|
||||||
|
|
||||||
|
|
||||||
class ParsedCall:
|
class ParsedCall:
|
||||||
|
@ -258,9 +258,9 @@ class HookRecorder:
|
||||||
pytest.fail("\n".join(lines))
|
pytest.fail("\n".join(lines))
|
||||||
|
|
||||||
def getcall(self, name):
|
def getcall(self, name):
|
||||||
l = self.getcalls(name)
|
values = self.getcalls(name)
|
||||||
assert len(l) == 1, (name, l)
|
assert len(values) == 1, (name, values)
|
||||||
return l[0]
|
return values[0]
|
||||||
|
|
||||||
# functionality for test reports
|
# functionality for test reports
|
||||||
|
|
||||||
|
@ -271,7 +271,7 @@ class HookRecorder:
|
||||||
def matchreport(self, inamepart="",
|
def matchreport(self, inamepart="",
|
||||||
names="pytest_runtest_logreport pytest_collectreport", when=None):
|
names="pytest_runtest_logreport pytest_collectreport", when=None):
|
||||||
""" return a testreport whose dotted import path matches """
|
""" return a testreport whose dotted import path matches """
|
||||||
l = []
|
values = []
|
||||||
for rep in self.getreports(names=names):
|
for rep in self.getreports(names=names):
|
||||||
try:
|
try:
|
||||||
if not when and rep.when != "call" and rep.passed:
|
if not when and rep.when != "call" and rep.passed:
|
||||||
|
@ -282,14 +282,14 @@ class HookRecorder:
|
||||||
if when and getattr(rep, 'when', None) != when:
|
if when and getattr(rep, 'when', None) != when:
|
||||||
continue
|
continue
|
||||||
if not inamepart or inamepart in rep.nodeid.split("::"):
|
if not inamepart or inamepart in rep.nodeid.split("::"):
|
||||||
l.append(rep)
|
values.append(rep)
|
||||||
if not l:
|
if not values:
|
||||||
raise ValueError("could not find test report matching %r: "
|
raise ValueError("could not find test report matching %r: "
|
||||||
"no test reports at all!" % (inamepart,))
|
"no test reports at all!" % (inamepart,))
|
||||||
if len(l) > 1:
|
if len(values) > 1:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
"found 2 or more testreports matching %r: %s" % (inamepart, l))
|
"found 2 or more testreports matching %r: %s" % (inamepart, values))
|
||||||
return l[0]
|
return values[0]
|
||||||
|
|
||||||
def getfailures(self,
|
def getfailures(self,
|
||||||
names='pytest_runtest_logreport pytest_collectreport'):
|
names='pytest_runtest_logreport pytest_collectreport'):
|
||||||
|
@ -673,8 +673,8 @@ class Testdir:
|
||||||
|
|
||||||
"""
|
"""
|
||||||
p = self.makepyfile(source)
|
p = self.makepyfile(source)
|
||||||
l = list(cmdlineargs) + [p]
|
values = list(cmdlineargs) + [p]
|
||||||
return self.inline_run(*l)
|
return self.inline_run(*values)
|
||||||
|
|
||||||
def inline_genitems(self, *args):
|
def inline_genitems(self, *args):
|
||||||
"""Run ``pytest.main(['--collectonly'])`` in-process.
|
"""Run ``pytest.main(['--collectonly'])`` in-process.
|
||||||
|
|
|
@ -321,7 +321,7 @@ class PyCollector(PyobjMixin, main.Collector):
|
||||||
for basecls in inspect.getmro(self.obj.__class__):
|
for basecls in inspect.getmro(self.obj.__class__):
|
||||||
dicts.append(basecls.__dict__)
|
dicts.append(basecls.__dict__)
|
||||||
seen = {}
|
seen = {}
|
||||||
l = []
|
values = []
|
||||||
for dic in dicts:
|
for dic in dicts:
|
||||||
for name, obj in list(dic.items()):
|
for name, obj in list(dic.items()):
|
||||||
if name in seen:
|
if name in seen:
|
||||||
|
@ -332,9 +332,9 @@ class PyCollector(PyobjMixin, main.Collector):
|
||||||
continue
|
continue
|
||||||
if not isinstance(res, list):
|
if not isinstance(res, list):
|
||||||
res = [res]
|
res = [res]
|
||||||
l.extend(res)
|
values.extend(res)
|
||||||
l.sort(key=lambda item: item.reportinfo()[:2])
|
values.sort(key=lambda item: item.reportinfo()[:2])
|
||||||
return l
|
return values
|
||||||
|
|
||||||
def makeitem(self, name, obj):
|
def makeitem(self, name, obj):
|
||||||
# assert self.ihook.fspath == self.fspath, self
|
# assert self.ihook.fspath == self.fspath, self
|
||||||
|
@ -592,7 +592,7 @@ class Generator(FunctionMixin, PyCollector):
|
||||||
self.session._setupstate.prepare(self)
|
self.session._setupstate.prepare(self)
|
||||||
# see FunctionMixin.setup and test_setupstate_is_preserved_134
|
# see FunctionMixin.setup and test_setupstate_is_preserved_134
|
||||||
self._preservedparent = self.parent.obj
|
self._preservedparent = self.parent.obj
|
||||||
l = []
|
values = []
|
||||||
seen = {}
|
seen = {}
|
||||||
for i, x in enumerate(self.obj()):
|
for i, x in enumerate(self.obj()):
|
||||||
name, call, args = self.getcallargs(x)
|
name, call, args = self.getcallargs(x)
|
||||||
|
@ -605,9 +605,9 @@ class Generator(FunctionMixin, PyCollector):
|
||||||
if name in seen:
|
if name in seen:
|
||||||
raise ValueError("%r generated tests with non-unique name %r" % (self, name))
|
raise ValueError("%r generated tests with non-unique name %r" % (self, name))
|
||||||
seen[name] = True
|
seen[name] = True
|
||||||
l.append(self.Function(name, self, args=args, callobj=call))
|
values.append(self.Function(name, self, args=args, callobj=call))
|
||||||
self.warn('C1', deprecated.YIELD_TESTS)
|
self.warn('C1', deprecated.YIELD_TESTS)
|
||||||
return l
|
return values
|
||||||
|
|
||||||
def getcallargs(self, obj):
|
def getcallargs(self, obj):
|
||||||
if not isinstance(obj, (tuple, list)):
|
if not isinstance(obj, (tuple, list)):
|
||||||
|
@ -979,50 +979,48 @@ def _show_fixtures_per_test(config, session):
|
||||||
tw = _pytest.config.create_terminal_writer(config)
|
tw = _pytest.config.create_terminal_writer(config)
|
||||||
verbose = config.getvalue("verbose")
|
verbose = config.getvalue("verbose")
|
||||||
|
|
||||||
def get_best_rel(func):
|
def get_best_relpath(func):
|
||||||
loc = getlocation(func, curdir)
|
loc = getlocation(func, curdir)
|
||||||
return curdir.bestrelpath(loc)
|
return curdir.bestrelpath(loc)
|
||||||
|
|
||||||
def write_fixture(fixture_def):
|
def write_fixture(fixture_def):
|
||||||
argname = fixture_def.argname
|
argname = fixture_def.argname
|
||||||
|
|
||||||
if verbose <= 0 and argname.startswith("_"):
|
if verbose <= 0 and argname.startswith("_"):
|
||||||
return
|
return
|
||||||
if verbose > 0:
|
if verbose > 0:
|
||||||
bestrel = get_best_rel(fixture_def.func)
|
bestrel = get_best_relpath(fixture_def.func)
|
||||||
funcargspec = "{0} -- {1}".format(argname, bestrel)
|
funcargspec = "{0} -- {1}".format(argname, bestrel)
|
||||||
else:
|
else:
|
||||||
funcargspec = argname
|
funcargspec = argname
|
||||||
tw.line(funcargspec, green=True)
|
tw.line(funcargspec, green=True)
|
||||||
|
|
||||||
fixture_doc = fixture_def.func.__doc__
|
fixture_doc = fixture_def.func.__doc__
|
||||||
|
|
||||||
if fixture_doc:
|
if fixture_doc:
|
||||||
write_docstring(tw, fixture_doc)
|
write_docstring(tw, fixture_doc)
|
||||||
else:
|
else:
|
||||||
tw.line(' no docstring available', red=True)
|
tw.line(' no docstring available', red=True)
|
||||||
|
|
||||||
def write_item(item):
|
def write_item(item):
|
||||||
name2fixturedefs = item._fixtureinfo.name2fixturedefs
|
try:
|
||||||
|
info = item._fixtureinfo
|
||||||
if not name2fixturedefs:
|
except AttributeError:
|
||||||
# The given test item does not use any fixtures
|
# doctests items have no _fixtureinfo attribute
|
||||||
|
return
|
||||||
|
if not info.name2fixturedefs:
|
||||||
|
# this test item does not use any fixtures
|
||||||
return
|
return
|
||||||
bestrel = get_best_rel(item.function)
|
|
||||||
|
|
||||||
tw.line()
|
tw.line()
|
||||||
tw.sep('-', 'fixtures used by {0}'.format(item.name))
|
tw.sep('-', 'fixtures used by {0}'.format(item.name))
|
||||||
tw.sep('-', '({0})'.format(bestrel))
|
tw.sep('-', '({0})'.format(get_best_relpath(item.function)))
|
||||||
for argname, fixture_defs in sorted(name2fixturedefs.items()):
|
# dict key not used in loop but needed for sorting
|
||||||
assert fixture_defs is not None
|
for _, fixturedefs in sorted(info.name2fixturedefs.items()):
|
||||||
if not fixture_defs:
|
assert fixturedefs is not None
|
||||||
|
if not fixturedefs:
|
||||||
continue
|
continue
|
||||||
# The last fixture def item in the list is expected
|
# last item is expected to be the one used by the test item
|
||||||
# to be the one used by the test item
|
write_fixture(fixturedefs[-1])
|
||||||
write_fixture(fixture_defs[-1])
|
|
||||||
|
|
||||||
for item in session.items:
|
for session_item in session.items:
|
||||||
write_item(item)
|
write_item(session_item)
|
||||||
|
|
||||||
|
|
||||||
def showfixtures(config):
|
def showfixtures(config):
|
||||||
|
|
|
@ -84,7 +84,7 @@ class ApproxNumpy(ApproxBase):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
actual = np.asarray(actual)
|
actual = np.asarray(actual)
|
||||||
except:
|
except: # noqa
|
||||||
raise TypeError("cannot compare '{0}' to numpy.ndarray".format(actual))
|
raise TypeError("cannot compare '{0}' to numpy.ndarray".format(actual))
|
||||||
|
|
||||||
if actual.shape != self.expected.shape:
|
if actual.shape != self.expected.shape:
|
||||||
|
@ -217,7 +217,8 @@ class ApproxScalar(ApproxBase):
|
||||||
absolute tolerance or a relative tolerance, depending on what the user
|
absolute tolerance or a relative tolerance, depending on what the user
|
||||||
specified or which would be larger.
|
specified or which would be larger.
|
||||||
"""
|
"""
|
||||||
def set_default(x, default): return x if x is not None else default
|
def set_default(x, default):
|
||||||
|
return x if x is not None else default
|
||||||
|
|
||||||
# Figure out what the absolute tolerance should be. ``self.abs`` is
|
# Figure out what the absolute tolerance should be. ``self.abs`` is
|
||||||
# either None or a value specified by the user.
|
# either None or a value specified by the user.
|
||||||
|
|
|
@ -56,11 +56,6 @@ def pytest_sessionfinish(session):
|
||||||
session._setupstate.teardown_all()
|
session._setupstate.teardown_all()
|
||||||
|
|
||||||
|
|
||||||
class NodeInfo:
|
|
||||||
def __init__(self, location):
|
|
||||||
self.location = location
|
|
||||||
|
|
||||||
|
|
||||||
def pytest_runtest_protocol(item, nextitem):
|
def pytest_runtest_protocol(item, nextitem):
|
||||||
item.ihook.pytest_runtest_logstart(
|
item.ihook.pytest_runtest_logstart(
|
||||||
nodeid=item.nodeid, location=item.location,
|
nodeid=item.nodeid, location=item.location,
|
||||||
|
@ -197,7 +192,7 @@ class CallInfo:
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
self.stop = time()
|
self.stop = time()
|
||||||
raise
|
raise
|
||||||
except:
|
except: # noqa
|
||||||
self.excinfo = ExceptionInfo()
|
self.excinfo = ExceptionInfo()
|
||||||
self.stop = time()
|
self.stop = time()
|
||||||
|
|
||||||
|
|
|
@ -346,10 +346,10 @@ def folded_skips(skipped):
|
||||||
key = event.longrepr
|
key = event.longrepr
|
||||||
assert len(key) == 3, (event, key)
|
assert len(key) == 3, (event, key)
|
||||||
d.setdefault(key, []).append(event)
|
d.setdefault(key, []).append(event)
|
||||||
l = []
|
values = []
|
||||||
for key, events in d.items():
|
for key, events in d.items():
|
||||||
l.append((len(events),) + key)
|
values.append((len(events),) + key)
|
||||||
return l
|
return values
|
||||||
|
|
||||||
|
|
||||||
def show_skipped(terminalreporter, lines):
|
def show_skipped(terminalreporter, lines):
|
||||||
|
|
|
@ -13,6 +13,7 @@ import sys
|
||||||
import time
|
import time
|
||||||
import platform
|
import platform
|
||||||
|
|
||||||
|
from _pytest import nodes
|
||||||
import _pytest._pluggy as pluggy
|
import _pytest._pluggy as pluggy
|
||||||
|
|
||||||
|
|
||||||
|
@ -444,15 +445,15 @@ class TerminalReporter:
|
||||||
line = self.config.cwd_relative_nodeid(nodeid)
|
line = self.config.cwd_relative_nodeid(nodeid)
|
||||||
if domain and line.endswith(domain):
|
if domain and line.endswith(domain):
|
||||||
line = line[:-len(domain)]
|
line = line[:-len(domain)]
|
||||||
l = domain.split("[")
|
values = domain.split("[")
|
||||||
l[0] = l[0].replace('.', '::') # don't replace '.' in params
|
values[0] = values[0].replace('.', '::') # don't replace '.' in params
|
||||||
line += "[".join(l)
|
line += "[".join(values)
|
||||||
return line
|
return line
|
||||||
# collect_fspath comes from testid which has a "/"-normalized path
|
# collect_fspath comes from testid which has a "/"-normalized path
|
||||||
|
|
||||||
if fspath:
|
if fspath:
|
||||||
res = mkrel(nodeid).replace("::()", "") # parens-normalization
|
res = mkrel(nodeid).replace("::()", "") # parens-normalization
|
||||||
if nodeid.split("::")[0] != fspath.replace("\\", "/"):
|
if nodeid.split("::")[0] != fspath.replace("\\", nodes.SEP):
|
||||||
res += " <- " + self.startdir.bestrelpath(fspath)
|
res += " <- " + self.startdir.bestrelpath(fspath)
|
||||||
else:
|
else:
|
||||||
res = "[location]"
|
res = "[location]"
|
||||||
|
@ -478,11 +479,11 @@ class TerminalReporter:
|
||||||
# summaries for sessionfinish
|
# summaries for sessionfinish
|
||||||
#
|
#
|
||||||
def getreports(self, name):
|
def getreports(self, name):
|
||||||
l = []
|
values = []
|
||||||
for x in self.stats.get(name, []):
|
for x in self.stats.get(name, []):
|
||||||
if not hasattr(x, '_pdbshown'):
|
if not hasattr(x, '_pdbshown'):
|
||||||
l.append(x)
|
values.append(x)
|
||||||
return l
|
return values
|
||||||
|
|
||||||
def summary_warnings(self):
|
def summary_warnings(self):
|
||||||
if self.hasopt("w"):
|
if self.hasopt("w"):
|
||||||
|
@ -593,8 +594,8 @@ def repr_pythonversion(v=None):
|
||||||
return str(v)
|
return str(v)
|
||||||
|
|
||||||
|
|
||||||
def flatten(l):
|
def flatten(values):
|
||||||
for x in l:
|
for x in values:
|
||||||
if isinstance(x, (list, tuple)):
|
if isinstance(x, (list, tuple)):
|
||||||
for y in flatten(x):
|
for y in flatten(x):
|
||||||
yield y
|
yield y
|
||||||
|
@ -635,7 +636,7 @@ def build_summary_stats_line(stats):
|
||||||
|
|
||||||
|
|
||||||
def _plugin_nameversions(plugininfo):
|
def _plugin_nameversions(plugininfo):
|
||||||
l = []
|
values = []
|
||||||
for plugin, dist in plugininfo:
|
for plugin, dist in plugininfo:
|
||||||
# gets us name and version!
|
# gets us name and version!
|
||||||
name = '{dist.project_name}-{dist.version}'.format(dist=dist)
|
name = '{dist.project_name}-{dist.version}'.format(dist=dist)
|
||||||
|
@ -644,6 +645,6 @@ def _plugin_nameversions(plugininfo):
|
||||||
name = name[7:]
|
name = name[7:]
|
||||||
# we decided to print python package names
|
# we decided to print python package names
|
||||||
# they can have more than one plugin
|
# they can have more than one plugin
|
||||||
if name not in l:
|
if name not in values:
|
||||||
l.append(name)
|
values.append(name)
|
||||||
return l
|
return values
|
||||||
|
|
|
@ -109,13 +109,13 @@ class TestCaseFunction(Function):
|
||||||
except TypeError:
|
except TypeError:
|
||||||
try:
|
try:
|
||||||
try:
|
try:
|
||||||
l = traceback.format_exception(*rawexcinfo)
|
values = traceback.format_exception(*rawexcinfo)
|
||||||
l.insert(0, "NOTE: Incompatible Exception Representation, "
|
values.insert(0, "NOTE: Incompatible Exception Representation, "
|
||||||
"displaying natively:\n\n")
|
"displaying natively:\n\n")
|
||||||
fail("".join(l), pytrace=False)
|
fail("".join(values), pytrace=False)
|
||||||
except (fail.Exception, KeyboardInterrupt):
|
except (fail.Exception, KeyboardInterrupt):
|
||||||
raise
|
raise
|
||||||
except:
|
except: # noqa
|
||||||
fail("ERROR: Unknown Incompatible Exception "
|
fail("ERROR: Unknown Incompatible Exception "
|
||||||
"representation:\n%r" % (rawexcinfo,), pytrace=False)
|
"representation:\n%r" % (rawexcinfo,), pytrace=False)
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Introduce a dedicated section about conftest.py.
|
|
@ -1 +0,0 @@
|
||||||
Add note in ``parametrize.rst`` about calling ``metafunc.parametrize`` multiple times.
|
|
|
@ -0,0 +1 @@
|
||||||
|
Explicitly mention ``xpass`` in the documentation of ``xfail``.
|
|
@ -0,0 +1 @@
|
||||||
|
Append example for pytest.param in the example/parametrize document.
|
|
@ -1 +0,0 @@
|
||||||
Set ``xfail_strict=True`` in pytest's own test suite to catch expected failures as soon as they start to pass.
|
|
|
@ -1 +0,0 @@
|
||||||
The equality checking function (``__eq__``) of ``MarkDecorator`` returns ``False`` if one object is not an instance of ``MarkDecorator``.
|
|
|
@ -1 +0,0 @@
|
||||||
Fix typo in example of passing a callable to markers (in example/markers.rst)
|
|
|
@ -0,0 +1 @@
|
||||||
|
Fix issue with @pytest.parametrize if argnames was specified as kwarg.
|
|
@ -0,0 +1 @@
|
||||||
|
Match fixture paths against actual path segments in order to avoid matching folders which share a prefix.
|
|
@ -0,0 +1 @@
|
||||||
|
Strip whitespace from marker names when reading them from INI config.
|
|
@ -0,0 +1 @@
|
||||||
|
Show full context of doctest source in the pytest output, if the lineno of failed example in the docstring is < 9.
|
|
@ -0,0 +1 @@
|
||||||
|
Clarify language of proposal for fixtures parameters
|
|
@ -0,0 +1 @@
|
||||||
|
List python 3.6 in the documented supported versions in the getting started document.
|
|
@ -0,0 +1 @@
|
||||||
|
Clarify the documentation of available fixture scopes.
|
|
@ -0,0 +1 @@
|
||||||
|
Add documentation about the ``python -m pytest`` invocation adding the current directory to sys.path.
|
|
@ -6,6 +6,7 @@ Release announcements
|
||||||
:maxdepth: 2
|
:maxdepth: 2
|
||||||
|
|
||||||
|
|
||||||
|
release-3.2.3
|
||||||
release-3.2.2
|
release-3.2.2
|
||||||
release-3.2.1
|
release-3.2.1
|
||||||
release-3.2.0
|
release-3.2.0
|
||||||
|
|
|
@ -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
|
|
@ -209,8 +209,8 @@ the ``pytest_assertrepr_compare`` hook.
|
||||||
.. autofunction:: _pytest.hookspec.pytest_assertrepr_compare
|
.. autofunction:: _pytest.hookspec.pytest_assertrepr_compare
|
||||||
:noindex:
|
:noindex:
|
||||||
|
|
||||||
As an example consider adding the following hook in a conftest.py which
|
As an example consider adding the following hook in a :ref:`conftest.py <conftest.py>`
|
||||||
provides an alternative explanation for ``Foo`` objects::
|
file which provides an alternative explanation for ``Foo`` objects::
|
||||||
|
|
||||||
# content of conftest.py
|
# content of conftest.py
|
||||||
from test_foocompare import Foo
|
from test_foocompare import Foo
|
||||||
|
|
|
@ -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
|
|
@ -350,7 +350,7 @@ Parametrizing test methods through per-class configuration
|
||||||
.. _`unittest parametrizer`: https://github.com/testing-cabal/unittest-ext/blob/master/params.py
|
.. _`unittest parametrizer`: https://github.com/testing-cabal/unittest-ext/blob/master/params.py
|
||||||
|
|
||||||
|
|
||||||
Here is an example ``pytest_generate_function`` function implementing a
|
Here is an example ``pytest_generate_tests`` function implementing a
|
||||||
parametrization scheme similar to Michael Foord's `unittest
|
parametrization scheme similar to Michael Foord's `unittest
|
||||||
parametrizer`_ but in a lot less code::
|
parametrizer`_ but in a lot less code::
|
||||||
|
|
||||||
|
@ -485,4 +485,54 @@ of our ``test_func1`` was skipped. A few notes:
|
||||||
values as well.
|
values as well.
|
||||||
|
|
||||||
|
|
||||||
|
Set marks or test ID for individual parametrized test
|
||||||
|
--------------------------------------------------------------------
|
||||||
|
|
||||||
|
Use ``pytest.param`` to apply marks or set test ID to individual parametrized test.
|
||||||
|
For example::
|
||||||
|
|
||||||
|
# content of test_pytest_param_example.py
|
||||||
|
import pytest
|
||||||
|
@pytest.mark.parametrize('test_input,expected', [
|
||||||
|
('3+5', 8),
|
||||||
|
pytest.param('1+7', 8,
|
||||||
|
marks=pytest.mark.basic),
|
||||||
|
pytest.param('2+4', 6,
|
||||||
|
marks=pytest.mark.basic,
|
||||||
|
id='basic_2+4'),
|
||||||
|
pytest.param('6*9', 42,
|
||||||
|
marks=[pytest.mark.basic, pytest.mark.xfail],
|
||||||
|
id='basic_6*9'),
|
||||||
|
])
|
||||||
|
def test_eval(test_input, expected):
|
||||||
|
assert eval(test_input) == expected
|
||||||
|
|
||||||
|
In this example, we have 4 parametrized tests. Except for the first test,
|
||||||
|
we mark the rest three parametrized tests with the custom marker ``basic``,
|
||||||
|
and for the fourth test we also use the built-in mark ``xfail`` to indicate this
|
||||||
|
test is expected to fail. For explicitness, we set test ids for some tests.
|
||||||
|
|
||||||
|
Then run ``pytest`` with verbose mode and with only the ``basic`` marker::
|
||||||
|
|
||||||
|
pytest -v -m basic
|
||||||
|
============================================ test session starts =============================================
|
||||||
|
platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y
|
||||||
|
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||||
|
collected 4 items
|
||||||
|
|
||||||
|
test_pytest_param_example.py::test_eval[1+7-8] PASSED
|
||||||
|
test_pytest_param_example.py::test_eval[basic_2+4] PASSED
|
||||||
|
test_pytest_param_example.py::test_eval[basic_6*9] xfail
|
||||||
|
========================================== short test summary info ===========================================
|
||||||
|
XFAIL test_pytest_param_example.py::test_eval[basic_6*9]
|
||||||
|
|
||||||
|
============================================= 1 tests deselected =============================================
|
||||||
|
|
||||||
|
As the result:
|
||||||
|
|
||||||
|
- Four tests were collected
|
||||||
|
- One test was deselected because it doesn't have the ``basic`` mark.
|
||||||
|
- Three tests with the ``basic`` mark was selected.
|
||||||
|
- The test ``test_eval[1+7-8]`` passed, but the name is autogenerated and confusing.
|
||||||
|
- The test ``test_eval[basic_2+4]`` passed.
|
||||||
|
- The test ``test_eval[basic_6*9]`` was expected to fail and did fail.
|
||||||
|
|
|
@ -175,21 +175,23 @@ You can always peek at the collection tree without running tests like this::
|
||||||
|
|
||||||
======= no tests ran in 0.12 seconds ========
|
======= no tests ran in 0.12 seconds ========
|
||||||
|
|
||||||
customizing test collection to find all .py files
|
.. _customizing-test-collection:
|
||||||
---------------------------------------------------------
|
|
||||||
|
Customizing test collection
|
||||||
|
---------------------------
|
||||||
|
|
||||||
.. regendoc:wipe
|
.. regendoc:wipe
|
||||||
|
|
||||||
You can easily instruct ``pytest`` to discover tests from every python file::
|
You can easily instruct ``pytest`` to discover tests from every Python file::
|
||||||
|
|
||||||
|
|
||||||
# content of pytest.ini
|
# content of pytest.ini
|
||||||
[pytest]
|
[pytest]
|
||||||
python_files = *.py
|
python_files = *.py
|
||||||
|
|
||||||
However, many projects will have a ``setup.py`` which they don't want to be imported. Moreover, there may files only importable by a specific python version.
|
However, many projects will have a ``setup.py`` which they don't want to be
|
||||||
For such cases you can dynamically define files to be ignored by listing
|
imported. Moreover, there may files only importable by a specific python
|
||||||
them in a ``conftest.py`` file::
|
version. For such cases you can dynamically define files to be ignored by
|
||||||
|
listing them in a ``conftest.py`` file::
|
||||||
|
|
||||||
# content of conftest.py
|
# content of conftest.py
|
||||||
import sys
|
import sys
|
||||||
|
@ -198,7 +200,7 @@ them in a ``conftest.py`` file::
|
||||||
if sys.version_info[0] > 2:
|
if sys.version_info[0] > 2:
|
||||||
collect_ignore.append("pkg/module_py2.py")
|
collect_ignore.append("pkg/module_py2.py")
|
||||||
|
|
||||||
And then if you have a module file like this::
|
and then if you have a module file like this::
|
||||||
|
|
||||||
# content of pkg/module_py2.py
|
# content of pkg/module_py2.py
|
||||||
def test_only_on_python2():
|
def test_only_on_python2():
|
||||||
|
@ -207,13 +209,13 @@ And then if you have a module file like this::
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
and a setup.py dummy file like this::
|
and a ``setup.py`` dummy file like this::
|
||||||
|
|
||||||
# content of setup.py
|
# content of setup.py
|
||||||
0/0 # will raise exception if imported
|
0/0 # will raise exception if imported
|
||||||
|
|
||||||
then a pytest run on Python2 will find the one test and will leave out the
|
If you run with a Python 2 interpreter then you will find the one test and will
|
||||||
setup.py file::
|
leave out the ``setup.py`` file::
|
||||||
|
|
||||||
#$ pytest --collect-only
|
#$ pytest --collect-only
|
||||||
====== test session starts ======
|
====== test session starts ======
|
||||||
|
@ -225,8 +227,8 @@ setup.py file::
|
||||||
|
|
||||||
====== no tests ran in 0.04 seconds ======
|
====== no tests ran in 0.04 seconds ======
|
||||||
|
|
||||||
If you run with a Python3 interpreter both the one test and the setup.py file
|
If you run with a Python 3 interpreter both the one test and the ``setup.py``
|
||||||
will be left out::
|
file will be left out::
|
||||||
|
|
||||||
$ pytest --collect-only
|
$ pytest --collect-only
|
||||||
======= test session starts ========
|
======= test session starts ========
|
||||||
|
|
|
@ -27,7 +27,7 @@ functions:
|
||||||
* fixture management scales from simple unit to complex
|
* fixture management scales from simple unit to complex
|
||||||
functional testing, allowing to parametrize fixtures and tests according
|
functional testing, allowing to parametrize fixtures and tests according
|
||||||
to configuration and component options, or to re-use fixtures
|
to configuration and component options, or to re-use fixtures
|
||||||
across class, module or whole test session scopes.
|
across function, class, module or whole test session scopes.
|
||||||
|
|
||||||
In addition, pytest continues to support :ref:`xunitsetup`. You can mix
|
In addition, pytest continues to support :ref:`xunitsetup`. You can mix
|
||||||
both styles, moving incrementally from classic to new style, as you
|
both styles, moving incrementally from classic to new style, as you
|
||||||
|
@ -127,10 +127,39 @@ It's a prime example of `dependency injection`_ where fixture
|
||||||
functions take the role of the *injector* and test functions are the
|
functions take the role of the *injector* and test functions are the
|
||||||
*consumers* of fixture objects.
|
*consumers* of fixture objects.
|
||||||
|
|
||||||
|
.. _`conftest.py`:
|
||||||
|
.. _`conftest`:
|
||||||
|
|
||||||
|
``conftest.py``: sharing fixture functions
|
||||||
|
------------------------------------------
|
||||||
|
|
||||||
|
If during implementing your tests you realize that you
|
||||||
|
want to use a fixture function from multiple test files you can move it
|
||||||
|
to a ``conftest.py`` file.
|
||||||
|
You don't need to import the fixture you want to use in a test, it
|
||||||
|
automatically gets discovered by pytest. The discovery of
|
||||||
|
fixture functions starts at test classes, then test modules, then
|
||||||
|
``conftest.py`` files and finally builtin and third party plugins.
|
||||||
|
|
||||||
|
You can also use the ``conftest.py`` file to implement
|
||||||
|
:ref:`local per-directory plugins <conftest.py plugins>`.
|
||||||
|
|
||||||
|
Sharing test data
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
If you want to make test data from files available to your tests, a good way
|
||||||
|
to do this is by loading these data in a fixture for use by your tests.
|
||||||
|
This makes use of the automatic caching mechanisms of pytest.
|
||||||
|
|
||||||
|
Another good approach is by adding the data files in the ``tests`` folder.
|
||||||
|
There are also community plugins available to help managing this aspect of
|
||||||
|
testing, e.g. `pytest-datadir <https://github.com/gabrielcnr/pytest-datadir>`__
|
||||||
|
and `pytest-datafiles <https://pypi.python.org/pypi/pytest-datafiles>`__.
|
||||||
|
|
||||||
.. _smtpshared:
|
.. _smtpshared:
|
||||||
|
|
||||||
Sharing a fixture across tests in a module (or class/session)
|
Scope: sharing a fixture instance across tests in a class, module or session
|
||||||
-----------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
|
|
||||||
.. regendoc:wipe
|
.. regendoc:wipe
|
||||||
|
|
||||||
|
@ -139,10 +168,12 @@ usually time-expensive to create. Extending the previous example, we
|
||||||
can add a ``scope='module'`` parameter to the
|
can add a ``scope='module'`` parameter to the
|
||||||
:py:func:`@pytest.fixture <_pytest.python.fixture>` invocation
|
:py:func:`@pytest.fixture <_pytest.python.fixture>` invocation
|
||||||
to cause the decorated ``smtp`` fixture function to only be invoked once
|
to cause the decorated ``smtp`` fixture function to only be invoked once
|
||||||
per test module. Multiple test functions in a test module will thus
|
per test *module* (the default is to invoke once per test *function*).
|
||||||
each receive the same ``smtp`` fixture instance. The next example puts
|
Multiple test functions in a test module will thus
|
||||||
the fixture function into a separate ``conftest.py`` file so
|
each receive the same ``smtp`` fixture instance, thus saving time.
|
||||||
that tests from multiple test modules in the directory can
|
|
||||||
|
The next example puts the fixture function into a separate ``conftest.py`` file
|
||||||
|
so that tests from multiple test modules in the directory can
|
||||||
access the fixture function::
|
access the fixture function::
|
||||||
|
|
||||||
# content of conftest.py
|
# content of conftest.py
|
||||||
|
@ -223,6 +254,8 @@ instance, you can simply declare it:
|
||||||
# the returned fixture value will be shared for
|
# the returned fixture value will be shared for
|
||||||
# all tests needing it
|
# all tests needing it
|
||||||
|
|
||||||
|
Finally, the ``class`` scope will invoke the fixture once per test *class*.
|
||||||
|
|
||||||
.. _`finalization`:
|
.. _`finalization`:
|
||||||
|
|
||||||
Fixture finalization / executing teardown code
|
Fixture finalization / executing teardown code
|
||||||
|
@ -858,7 +891,7 @@ into a conftest.py file **without** using ``autouse``::
|
||||||
|
|
||||||
# content of conftest.py
|
# content of conftest.py
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def transact(self, request, db):
|
def transact(request, db):
|
||||||
db.begin()
|
db.begin()
|
||||||
yield
|
yield
|
||||||
db.rollback()
|
db.rollback()
|
||||||
|
@ -874,17 +907,6 @@ All test methods in this TestClass will use the transaction fixture while
|
||||||
other test classes or functions in the module will not use it unless
|
other test classes or functions in the module will not use it unless
|
||||||
they also add a ``transact`` reference.
|
they also add a ``transact`` reference.
|
||||||
|
|
||||||
|
|
||||||
Shifting (visibility of) fixture functions
|
|
||||||
----------------------------------------------------
|
|
||||||
|
|
||||||
If during implementing your tests you realize that you
|
|
||||||
want to use a fixture function from multiple test files you can move it
|
|
||||||
to a :ref:`conftest.py <conftest.py>` file or even separately installable
|
|
||||||
:ref:`plugins <plugins>` without changing test code. The discovery of
|
|
||||||
fixtures functions starts at test classes, then test modules, then
|
|
||||||
``conftest.py`` files and finally builtin and third party plugins.
|
|
||||||
|
|
||||||
Overriding fixtures on various levels
|
Overriding fixtures on various levels
|
||||||
-------------------------------------
|
-------------------------------------
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
Installation and Getting Started
|
Installation and Getting Started
|
||||||
===================================
|
===================================
|
||||||
|
|
||||||
**Pythons**: Python 2.6,2.7,3.3,3.4,3.5, Jython, PyPy-2.3
|
**Pythons**: Python 2.6,2.7,3.3,3.4,3.5,3.6 Jython, PyPy-2.3
|
||||||
|
|
||||||
**Platforms**: Unix/Posix and Windows
|
**Platforms**: Unix/Posix and Windows
|
||||||
|
|
||||||
|
|
|
@ -198,10 +198,12 @@ 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
|
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.
|
those sets cannot be duplicated, otherwise an error will be raised.
|
||||||
|
|
||||||
|
More examples
|
||||||
|
-------------
|
||||||
|
|
||||||
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>`.
|
||||||
|
|
||||||
|
|
|
@ -94,7 +94,7 @@ environment you can type::
|
||||||
|
|
||||||
and will get an extended test header which shows activated plugins
|
and will get an extended test header which shows activated plugins
|
||||||
and their names. It will also print local plugins aka
|
and their names. It will also print local plugins aka
|
||||||
:ref:`conftest.py <conftest>` files when they are loaded.
|
:ref:`conftest.py <conftest.py plugins>` files when they are loaded.
|
||||||
|
|
||||||
.. _`cmdunregister`:
|
.. _`cmdunregister`:
|
||||||
|
|
||||||
|
@ -155,4 +155,3 @@ in the `pytest repository <https://github.com/pytest-dev/pytest>`_.
|
||||||
_pytest.terminal
|
_pytest.terminal
|
||||||
_pytest.tmpdir
|
_pytest.tmpdir
|
||||||
_pytest.unittest
|
_pytest.unittest
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,13 @@
|
||||||
:orphan:
|
:orphan:
|
||||||
|
|
||||||
=========================
|
===================================
|
||||||
Parametrize with fixtures
|
PROPOSAL: Parametrize with fixtures
|
||||||
=========================
|
===================================
|
||||||
|
|
||||||
|
.. warning::
|
||||||
|
|
||||||
|
This document outlines a proposal around using fixtures as input
|
||||||
|
of parametrized tests or fixtures.
|
||||||
|
|
||||||
Problem
|
Problem
|
||||||
-------
|
-------
|
||||||
|
@ -108,8 +113,13 @@ the following values.
|
||||||
Alternative approach
|
Alternative approach
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
A new helper function named ``fixture_request`` tells pytest to yield all
|
A new helper function named ``fixture_request`` would tell pytest to yield
|
||||||
parameters of a fixture.
|
all parameters marked as a fixture.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
The `pytest-lazy-fixture <https://pypi.python.org/pypi/pytest-lazy-fixture>`_ plugin implements a very
|
||||||
|
similar solution to the proposal below, make sure to check it out.
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
|
|
|
@ -68,4 +68,9 @@ imported in the global import namespace.
|
||||||
|
|
||||||
This is also discussed in details in :ref:`test discovery`.
|
This is also discussed in details in :ref:`test discovery`.
|
||||||
|
|
||||||
|
Invoking ``pytest`` versus ``python -m pytest``
|
||||||
|
-----------------------------------------------
|
||||||
|
|
||||||
|
Running pytest with ``python -m pytest [...]`` instead of ``pytest [...]`` yields nearly
|
||||||
|
equivalent behaviour, except that the former call will add the current directory to ``sys.path``.
|
||||||
|
See also :ref:`cmdline`.
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
.. _skipping:
|
.. _skipping:
|
||||||
|
|
||||||
Skip and xfail: dealing with tests that cannot succeed
|
Skip and xfail: dealing with tests that cannot succeed
|
||||||
=====================================================================
|
======================================================
|
||||||
|
|
||||||
You can mark test functions that cannot be run on certain platforms
|
You can mark test functions that cannot be run on certain platforms
|
||||||
or that you expect to fail so pytest can deal with them accordingly and
|
or that you expect to fail so pytest can deal with them accordingly and
|
||||||
|
@ -16,13 +16,17 @@ resource which is not available at the moment (for example a database).
|
||||||
|
|
||||||
A **xfail** means that you expect a test to fail for some reason.
|
A **xfail** means that you expect a test to fail for some reason.
|
||||||
A common example is a test for a feature not yet implemented, or a bug not yet fixed.
|
A common example is a test for a feature not yet implemented, or a bug not yet fixed.
|
||||||
|
When a test passes despite being expected to fail (marked with ``pytest.mark.xfail``),
|
||||||
|
it's an **xpass** and will be reported in the test summary.
|
||||||
|
|
||||||
``pytest`` counts and lists *skip* and *xfail* tests separately. Detailed
|
``pytest`` counts and lists *skip* and *xfail* tests separately. Detailed
|
||||||
information about skipped/xfailed tests is not shown by default to avoid
|
information about skipped/xfailed tests is not shown by default to avoid
|
||||||
cluttering the output. You can use the ``-r`` option to see details
|
cluttering the output. You can use the ``-r`` option to see details
|
||||||
corresponding to the "short" letters shown in the test progress::
|
corresponding to the "short" letters shown in the test progress::
|
||||||
|
|
||||||
pytest -rxs # show extra info on skips and xfails
|
pytest -rxXs # show extra info on xfailed, xpassed, and skipped tests
|
||||||
|
|
||||||
|
More details on the ``-r`` option can be found by running ``pytest -h``.
|
||||||
|
|
||||||
(See :ref:`how to change command line options defaults`)
|
(See :ref:`how to change command line options defaults`)
|
||||||
|
|
||||||
|
@ -138,6 +142,16 @@ will be skipped if any of the skip conditions is true.
|
||||||
.. _`whole class- or module level`: mark.html#scoped-marking
|
.. _`whole class- or module level`: mark.html#scoped-marking
|
||||||
|
|
||||||
|
|
||||||
|
Skipping files or directories
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Sometimes you may need to skip an entire file or directory, for example if the
|
||||||
|
tests rely on Python version-specific features or contain code that you do not
|
||||||
|
wish pytest to run. In this case, you must exclude the files and directories
|
||||||
|
from collection. Refer to :ref:`customizing-test-collection` for more
|
||||||
|
information.
|
||||||
|
|
||||||
|
|
||||||
Skipping on a missing import dependency
|
Skipping on a missing import dependency
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
|
|
@ -233,3 +233,13 @@ was executed ahead of the ``test_method``.
|
||||||
overwrite ``unittest.TestCase`` ``__call__`` or ``run``, they need to
|
overwrite ``unittest.TestCase`` ``__call__`` or ``run``, they need to
|
||||||
to overwrite ``debug`` in the same way (this is also true for standard
|
to overwrite ``debug`` in the same way (this is also true for standard
|
||||||
unittest).
|
unittest).
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
Due to architectural differences between the two frameworks, setup and
|
||||||
|
teardown for ``unittest``-based tests is performed during the ``call`` phase
|
||||||
|
of testing instead of in ``pytest``'s standard ``setup`` and ``teardown``
|
||||||
|
stages. This can be important to understand in some situations, particularly
|
||||||
|
when reasoning about errors. For example, if a ``unittest``-based suite
|
||||||
|
exhibits errors during setup, ``pytest`` will report no errors during its
|
||||||
|
``setup`` phase and will instead raise the error during ``call``.
|
||||||
|
|
|
@ -17,7 +17,7 @@ You can invoke testing through the Python interpreter from the command line::
|
||||||
python -m pytest [...]
|
python -m pytest [...]
|
||||||
|
|
||||||
This is almost equivalent to invoking the command line script ``pytest [...]``
|
This is almost equivalent to invoking the command line script ``pytest [...]``
|
||||||
directly, except that Python will also add the current directory to ``sys.path``.
|
directly, except that calling via ``python`` will also add the current directory to ``sys.path``.
|
||||||
|
|
||||||
Possible exit codes
|
Possible exit codes
|
||||||
--------------------------------------------------------------
|
--------------------------------------------------------------
|
||||||
|
|
|
@ -109,7 +109,7 @@ decorator or to all tests in a module by setting the ``pytestmark`` variable:
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
# turns all warnings into errors for this module
|
# turns all warnings into errors for this module
|
||||||
pytestmark = @pytest.mark.filterwarnings('error')
|
pytestmark = pytest.mark.filterwarnings('error')
|
||||||
|
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
|
@ -57,9 +57,7 @@ Plugin discovery order at tool startup
|
||||||
|
|
||||||
.. _`pytest/plugin`: http://bitbucket.org/pytest-dev/pytest/src/tip/pytest/plugin/
|
.. _`pytest/plugin`: http://bitbucket.org/pytest-dev/pytest/src/tip/pytest/plugin/
|
||||||
.. _`conftest.py plugins`:
|
.. _`conftest.py plugins`:
|
||||||
.. _`conftest.py`:
|
|
||||||
.. _`localplugin`:
|
.. _`localplugin`:
|
||||||
.. _`conftest`:
|
|
||||||
.. _`local conftest plugins`:
|
.. _`local conftest plugins`:
|
||||||
|
|
||||||
conftest.py: local per-directory plugins
|
conftest.py: local per-directory plugins
|
||||||
|
|
|
@ -77,8 +77,8 @@ def test_excinfo_getstatement():
|
||||||
linenumbers = [_pytest._code.getrawcode(f).co_firstlineno - 1 + 4,
|
linenumbers = [_pytest._code.getrawcode(f).co_firstlineno - 1 + 4,
|
||||||
_pytest._code.getrawcode(f).co_firstlineno - 1 + 1,
|
_pytest._code.getrawcode(f).co_firstlineno - 1 + 1,
|
||||||
_pytest._code.getrawcode(g).co_firstlineno - 1 + 1, ]
|
_pytest._code.getrawcode(g).co_firstlineno - 1 + 1, ]
|
||||||
l = list(excinfo.traceback)
|
values = list(excinfo.traceback)
|
||||||
foundlinenumbers = [x.lineno for x in l]
|
foundlinenumbers = [x.lineno for x in values]
|
||||||
assert foundlinenumbers == linenumbers
|
assert foundlinenumbers == linenumbers
|
||||||
# for x in info:
|
# for x in info:
|
||||||
# print "%s:%d %s" %(x.path.relto(root), x.lineno, x.statement)
|
# print "%s:%d %s" %(x.path.relto(root), x.lineno, x.statement)
|
||||||
|
@ -244,7 +244,7 @@ class TestTraceback_f_g_h(object):
|
||||||
def f(n):
|
def f(n):
|
||||||
try:
|
try:
|
||||||
do_stuff()
|
do_stuff()
|
||||||
except:
|
except: # noqa
|
||||||
reraise_me()
|
reraise_me()
|
||||||
|
|
||||||
excinfo = pytest.raises(RuntimeError, f, 8)
|
excinfo = pytest.raises(RuntimeError, f, 8)
|
||||||
|
@ -434,7 +434,7 @@ class TestFormattedExcinfo(object):
|
||||||
exec(source.compile())
|
exec(source.compile())
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
raise
|
raise
|
||||||
except:
|
except: # noqa
|
||||||
return _pytest._code.ExceptionInfo()
|
return _pytest._code.ExceptionInfo()
|
||||||
assert 0, "did not raise"
|
assert 0, "did not raise"
|
||||||
|
|
||||||
|
@ -1217,7 +1217,7 @@ def test_exception_repr_extraction_error_on_recursion():
|
||||||
|
|
||||||
try:
|
try:
|
||||||
a(numpy_like())
|
a(numpy_like())
|
||||||
except:
|
except: # noqa
|
||||||
from _pytest._code.code import ExceptionInfo
|
from _pytest._code.code import ExceptionInfo
|
||||||
from _pytest.pytester import LineMatcher
|
from _pytest.pytester import LineMatcher
|
||||||
exc_info = ExceptionInfo()
|
exc_info = ExceptionInfo()
|
||||||
|
@ -1241,7 +1241,7 @@ def test_no_recursion_index_on_recursion_error():
|
||||||
return getattr(self, '_' + attr)
|
return getattr(self, '_' + attr)
|
||||||
|
|
||||||
RecursionDepthError().trigger
|
RecursionDepthError().trigger
|
||||||
except:
|
except: # noqa
|
||||||
from _pytest._code.code import ExceptionInfo
|
from _pytest._code.code import ExceptionInfo
|
||||||
exc_info = ExceptionInfo()
|
exc_info = ExceptionInfo()
|
||||||
if sys.version_info[:2] == (2, 6):
|
if sys.version_info[:2] == (2, 6):
|
||||||
|
|
|
@ -155,8 +155,8 @@ class TestAccesses(object):
|
||||||
assert len(self.source) == 4
|
assert len(self.source) == 4
|
||||||
|
|
||||||
def test_iter(self):
|
def test_iter(self):
|
||||||
l = [x for x in self.source]
|
values = [x for x in self.source]
|
||||||
assert len(l) == 4
|
assert len(values) == 4
|
||||||
|
|
||||||
|
|
||||||
class TestSourceParsingAndCompiling(object):
|
class TestSourceParsingAndCompiling(object):
|
||||||
|
@ -331,8 +331,8 @@ def test_getstartingblock_singleline():
|
||||||
|
|
||||||
x = A('x', 'y')
|
x = A('x', 'y')
|
||||||
|
|
||||||
l = [i for i in x.source.lines if i.strip()]
|
values = [i for i in x.source.lines if i.strip()]
|
||||||
assert len(l) == 1
|
assert len(values) == 1
|
||||||
|
|
||||||
|
|
||||||
def test_getline_finally():
|
def test_getline_finally():
|
||||||
|
|
|
@ -22,5 +22,5 @@ def test_getstartingblock_multiline():
|
||||||
,
|
,
|
||||||
'z')
|
'z')
|
||||||
|
|
||||||
l = [i for i in x.source.lines if i.strip()]
|
values = [i for i in x.source.lines if i.strip()]
|
||||||
assert len(l) == 4
|
assert len(values) == 4
|
||||||
|
|
|
@ -873,11 +873,11 @@ class TestConftestCustomization(object):
|
||||||
|
|
||||||
def test_makeitem_non_underscore(self, testdir, monkeypatch):
|
def test_makeitem_non_underscore(self, testdir, monkeypatch):
|
||||||
modcol = testdir.getmodulecol("def _hello(): pass")
|
modcol = testdir.getmodulecol("def _hello(): pass")
|
||||||
l = []
|
values = []
|
||||||
monkeypatch.setattr(pytest.Module, 'makeitem',
|
monkeypatch.setattr(pytest.Module, 'makeitem',
|
||||||
lambda self, name, obj: l.append(name))
|
lambda self, name, obj: values.append(name))
|
||||||
l = modcol.collect()
|
values = modcol.collect()
|
||||||
assert '_hello' not in l
|
assert '_hello' not in values
|
||||||
|
|
||||||
def test_issue2369_collect_module_fileext(self, testdir):
|
def test_issue2369_collect_module_fileext(self, testdir):
|
||||||
"""Ensure we can collect files with weird file extensions as Python
|
"""Ensure we can collect files with weird file extensions as Python
|
||||||
|
|
|
@ -548,12 +548,12 @@ class TestRequestBasic(object):
|
||||||
def test_getfixturevalue(self, testdir, getfixmethod):
|
def test_getfixturevalue(self, testdir, getfixmethod):
|
||||||
item = testdir.getitem("""
|
item = testdir.getitem("""
|
||||||
import pytest
|
import pytest
|
||||||
l = [2]
|
values = [2]
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def something(request): return 1
|
def something(request): return 1
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def other(request):
|
def other(request):
|
||||||
return l.pop()
|
return values.pop()
|
||||||
def test_func(something): pass
|
def test_func(something): pass
|
||||||
""")
|
""")
|
||||||
import contextlib
|
import contextlib
|
||||||
|
@ -622,15 +622,15 @@ class TestRequestBasic(object):
|
||||||
def test_request_addfinalizer_failing_setup(self, testdir):
|
def test_request_addfinalizer_failing_setup(self, testdir):
|
||||||
testdir.makepyfile("""
|
testdir.makepyfile("""
|
||||||
import pytest
|
import pytest
|
||||||
l = [1]
|
values = [1]
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def myfix(request):
|
def myfix(request):
|
||||||
request.addfinalizer(l.pop)
|
request.addfinalizer(values.pop)
|
||||||
assert 0
|
assert 0
|
||||||
def test_fix(myfix):
|
def test_fix(myfix):
|
||||||
pass
|
pass
|
||||||
def test_finalizer_ran():
|
def test_finalizer_ran():
|
||||||
assert not l
|
assert not values
|
||||||
""")
|
""")
|
||||||
reprec = testdir.inline_run("-s")
|
reprec = testdir.inline_run("-s")
|
||||||
reprec.assertoutcome(failed=1, passed=1)
|
reprec.assertoutcome(failed=1, passed=1)
|
||||||
|
@ -638,30 +638,30 @@ class TestRequestBasic(object):
|
||||||
def test_request_addfinalizer_failing_setup_module(self, testdir):
|
def test_request_addfinalizer_failing_setup_module(self, testdir):
|
||||||
testdir.makepyfile("""
|
testdir.makepyfile("""
|
||||||
import pytest
|
import pytest
|
||||||
l = [1, 2]
|
values = [1, 2]
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def myfix(request):
|
def myfix(request):
|
||||||
request.addfinalizer(l.pop)
|
request.addfinalizer(values.pop)
|
||||||
request.addfinalizer(l.pop)
|
request.addfinalizer(values.pop)
|
||||||
assert 0
|
assert 0
|
||||||
def test_fix(myfix):
|
def test_fix(myfix):
|
||||||
pass
|
pass
|
||||||
""")
|
""")
|
||||||
reprec = testdir.inline_run("-s")
|
reprec = testdir.inline_run("-s")
|
||||||
mod = reprec.getcalls("pytest_runtest_setup")[0].item.module
|
mod = reprec.getcalls("pytest_runtest_setup")[0].item.module
|
||||||
assert not mod.l
|
assert not mod.values
|
||||||
|
|
||||||
def test_request_addfinalizer_partial_setup_failure(self, testdir):
|
def test_request_addfinalizer_partial_setup_failure(self, testdir):
|
||||||
p = testdir.makepyfile("""
|
p = testdir.makepyfile("""
|
||||||
import pytest
|
import pytest
|
||||||
l = []
|
values = []
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def something(request):
|
def something(request):
|
||||||
request.addfinalizer(lambda: l.append(None))
|
request.addfinalizer(lambda: values.append(None))
|
||||||
def test_func(something, missingarg):
|
def test_func(something, missingarg):
|
||||||
pass
|
pass
|
||||||
def test_second():
|
def test_second():
|
||||||
assert len(l) == 1
|
assert len(values) == 1
|
||||||
""")
|
""")
|
||||||
result = testdir.runpytest(p)
|
result = testdir.runpytest(p)
|
||||||
result.stdout.fnmatch_lines([
|
result.stdout.fnmatch_lines([
|
||||||
|
@ -675,7 +675,7 @@ class TestRequestBasic(object):
|
||||||
"""
|
"""
|
||||||
testdir.makepyfile("""
|
testdir.makepyfile("""
|
||||||
import pytest
|
import pytest
|
||||||
l = []
|
values = []
|
||||||
def _excepts(where):
|
def _excepts(where):
|
||||||
raise Exception('Error in %s fixture' % where)
|
raise Exception('Error in %s fixture' % where)
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
@ -683,17 +683,17 @@ class TestRequestBasic(object):
|
||||||
return request
|
return request
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def something(subrequest):
|
def something(subrequest):
|
||||||
subrequest.addfinalizer(lambda: l.append(1))
|
subrequest.addfinalizer(lambda: values.append(1))
|
||||||
subrequest.addfinalizer(lambda: l.append(2))
|
subrequest.addfinalizer(lambda: values.append(2))
|
||||||
subrequest.addfinalizer(lambda: _excepts('something'))
|
subrequest.addfinalizer(lambda: _excepts('something'))
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def excepts(subrequest):
|
def excepts(subrequest):
|
||||||
subrequest.addfinalizer(lambda: _excepts('excepts'))
|
subrequest.addfinalizer(lambda: _excepts('excepts'))
|
||||||
subrequest.addfinalizer(lambda: l.append(3))
|
subrequest.addfinalizer(lambda: values.append(3))
|
||||||
def test_first(something, excepts):
|
def test_first(something, excepts):
|
||||||
pass
|
pass
|
||||||
def test_second():
|
def test_second():
|
||||||
assert l == [3, 2, 1]
|
assert values == [3, 2, 1]
|
||||||
""")
|
""")
|
||||||
result = testdir.runpytest()
|
result = testdir.runpytest()
|
||||||
result.stdout.fnmatch_lines([
|
result.stdout.fnmatch_lines([
|
||||||
|
@ -748,13 +748,13 @@ class TestRequestBasic(object):
|
||||||
def test_setupdecorator_and_xunit(self, testdir):
|
def test_setupdecorator_and_xunit(self, testdir):
|
||||||
testdir.makepyfile("""
|
testdir.makepyfile("""
|
||||||
import pytest
|
import pytest
|
||||||
l = []
|
values = []
|
||||||
@pytest.fixture(scope='module', autouse=True)
|
@pytest.fixture(scope='module', autouse=True)
|
||||||
def setup_module():
|
def setup_module():
|
||||||
l.append("module")
|
values.append("module")
|
||||||
@pytest.fixture(autouse=True)
|
@pytest.fixture(autouse=True)
|
||||||
def setup_function():
|
def setup_function():
|
||||||
l.append("function")
|
values.append("function")
|
||||||
|
|
||||||
def test_func():
|
def test_func():
|
||||||
pass
|
pass
|
||||||
|
@ -762,14 +762,14 @@ class TestRequestBasic(object):
|
||||||
class TestClass(object):
|
class TestClass(object):
|
||||||
@pytest.fixture(scope="class", autouse=True)
|
@pytest.fixture(scope="class", autouse=True)
|
||||||
def setup_class(self):
|
def setup_class(self):
|
||||||
l.append("class")
|
values.append("class")
|
||||||
@pytest.fixture(autouse=True)
|
@pytest.fixture(autouse=True)
|
||||||
def setup_method(self):
|
def setup_method(self):
|
||||||
l.append("method")
|
values.append("method")
|
||||||
def test_method(self):
|
def test_method(self):
|
||||||
pass
|
pass
|
||||||
def test_all():
|
def test_all():
|
||||||
assert l == ["module", "function", "class",
|
assert values == ["module", "function", "class",
|
||||||
"function", "method", "function"]
|
"function", "method", "function"]
|
||||||
""")
|
""")
|
||||||
reprec = testdir.inline_run("-v")
|
reprec = testdir.inline_run("-v")
|
||||||
|
@ -930,10 +930,10 @@ class TestRequestCachedSetup(object):
|
||||||
def test_request_cachedsetup_extrakey(self, testdir):
|
def test_request_cachedsetup_extrakey(self, testdir):
|
||||||
item1 = testdir.getitem("def test_func(): pass")
|
item1 = testdir.getitem("def test_func(): pass")
|
||||||
req1 = fixtures.FixtureRequest(item1)
|
req1 = fixtures.FixtureRequest(item1)
|
||||||
l = ["hello", "world"]
|
values = ["hello", "world"]
|
||||||
|
|
||||||
def setup():
|
def setup():
|
||||||
return l.pop()
|
return values.pop()
|
||||||
|
|
||||||
ret1 = req1.cached_setup(setup, extrakey=1)
|
ret1 = req1.cached_setup(setup, extrakey=1)
|
||||||
ret2 = req1.cached_setup(setup, extrakey=2)
|
ret2 = req1.cached_setup(setup, extrakey=2)
|
||||||
|
@ -947,24 +947,24 @@ class TestRequestCachedSetup(object):
|
||||||
def test_request_cachedsetup_cache_deletion(self, testdir):
|
def test_request_cachedsetup_cache_deletion(self, testdir):
|
||||||
item1 = testdir.getitem("def test_func(): pass")
|
item1 = testdir.getitem("def test_func(): pass")
|
||||||
req1 = fixtures.FixtureRequest(item1)
|
req1 = fixtures.FixtureRequest(item1)
|
||||||
l = []
|
values = []
|
||||||
|
|
||||||
def setup():
|
def setup():
|
||||||
l.append("setup")
|
values.append("setup")
|
||||||
|
|
||||||
def teardown(val):
|
def teardown(val):
|
||||||
l.append("teardown")
|
values.append("teardown")
|
||||||
|
|
||||||
req1.cached_setup(setup, teardown, scope="function")
|
req1.cached_setup(setup, teardown, scope="function")
|
||||||
assert l == ['setup']
|
assert values == ['setup']
|
||||||
# artificial call of finalizer
|
# artificial call of finalizer
|
||||||
setupstate = req1._pyfuncitem.session._setupstate
|
setupstate = req1._pyfuncitem.session._setupstate
|
||||||
setupstate._callfinalizers(item1)
|
setupstate._callfinalizers(item1)
|
||||||
assert l == ["setup", "teardown"]
|
assert values == ["setup", "teardown"]
|
||||||
req1.cached_setup(setup, teardown, scope="function")
|
req1.cached_setup(setup, teardown, scope="function")
|
||||||
assert l == ["setup", "teardown", "setup"]
|
assert values == ["setup", "teardown", "setup"]
|
||||||
setupstate._callfinalizers(item1)
|
setupstate._callfinalizers(item1)
|
||||||
assert l == ["setup", "teardown", "setup", "teardown"]
|
assert values == ["setup", "teardown", "setup", "teardown"]
|
||||||
|
|
||||||
def test_request_cached_setup_two_args(self, testdir):
|
def test_request_cached_setup_two_args(self, testdir):
|
||||||
testdir.makepyfile("""
|
testdir.makepyfile("""
|
||||||
|
@ -1006,17 +1006,17 @@ class TestRequestCachedSetup(object):
|
||||||
def test_request_cached_setup_functional(self, testdir):
|
def test_request_cached_setup_functional(self, testdir):
|
||||||
testdir.makepyfile(test_0="""
|
testdir.makepyfile(test_0="""
|
||||||
import pytest
|
import pytest
|
||||||
l = []
|
values = []
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def something(request):
|
def something(request):
|
||||||
val = request.cached_setup(fsetup, fteardown)
|
val = request.cached_setup(fsetup, fteardown)
|
||||||
return val
|
return val
|
||||||
def fsetup(mycache=[1]):
|
def fsetup(mycache=[1]):
|
||||||
l.append(mycache.pop())
|
values.append(mycache.pop())
|
||||||
return l
|
return values
|
||||||
def fteardown(something):
|
def fteardown(something):
|
||||||
l.remove(something[0])
|
values.remove(something[0])
|
||||||
l.append(2)
|
values.append(2)
|
||||||
def test_list_once(something):
|
def test_list_once(something):
|
||||||
assert something == [1]
|
assert something == [1]
|
||||||
def test_list_twice(something):
|
def test_list_twice(something):
|
||||||
|
@ -1025,7 +1025,7 @@ class TestRequestCachedSetup(object):
|
||||||
testdir.makepyfile(test_1="""
|
testdir.makepyfile(test_1="""
|
||||||
import test_0 # should have run already
|
import test_0 # should have run already
|
||||||
def test_check_test0_has_teardown_correct():
|
def test_check_test0_has_teardown_correct():
|
||||||
assert test_0.l == [2]
|
assert test_0.values == [2]
|
||||||
""")
|
""")
|
||||||
result = testdir.runpytest("-v")
|
result = testdir.runpytest("-v")
|
||||||
result.stdout.fnmatch_lines([
|
result.stdout.fnmatch_lines([
|
||||||
|
@ -1150,10 +1150,10 @@ class TestFixtureUsages(object):
|
||||||
def test_funcarg_parametrized_and_used_twice(self, testdir):
|
def test_funcarg_parametrized_and_used_twice(self, testdir):
|
||||||
testdir.makepyfile("""
|
testdir.makepyfile("""
|
||||||
import pytest
|
import pytest
|
||||||
l = []
|
values = []
|
||||||
@pytest.fixture(params=[1,2])
|
@pytest.fixture(params=[1,2])
|
||||||
def arg1(request):
|
def arg1(request):
|
||||||
l.append(1)
|
values.append(1)
|
||||||
return request.param
|
return request.param
|
||||||
|
|
||||||
@pytest.fixture()
|
@pytest.fixture()
|
||||||
|
@ -1162,7 +1162,7 @@ class TestFixtureUsages(object):
|
||||||
|
|
||||||
def test_add(arg1, arg2):
|
def test_add(arg1, arg2):
|
||||||
assert arg2 == arg1 + 1
|
assert arg2 == arg1 + 1
|
||||||
assert len(l) == arg1
|
assert len(values) == arg1
|
||||||
""")
|
""")
|
||||||
result = testdir.runpytest()
|
result = testdir.runpytest()
|
||||||
result.stdout.fnmatch_lines([
|
result.stdout.fnmatch_lines([
|
||||||
|
@ -1203,8 +1203,8 @@ class TestFixtureUsages(object):
|
||||||
|
|
||||||
""")
|
""")
|
||||||
reprec = testdir.inline_run()
|
reprec = testdir.inline_run()
|
||||||
l = reprec.getfailedcollections()
|
values = reprec.getfailedcollections()
|
||||||
assert len(l) == 1
|
assert len(values) == 1
|
||||||
|
|
||||||
def test_request_can_be_overridden(self, testdir):
|
def test_request_can_be_overridden(self, testdir):
|
||||||
testdir.makepyfile("""
|
testdir.makepyfile("""
|
||||||
|
@ -1223,20 +1223,20 @@ class TestFixtureUsages(object):
|
||||||
testdir.makepyfile("""
|
testdir.makepyfile("""
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
l = []
|
values = []
|
||||||
|
|
||||||
@pytest.fixture(scope="class")
|
@pytest.fixture(scope="class")
|
||||||
def myfix(request):
|
def myfix(request):
|
||||||
request.cls.hello = "world"
|
request.cls.hello = "world"
|
||||||
l.append(1)
|
values.append(1)
|
||||||
|
|
||||||
class TestClass(object):
|
class TestClass(object):
|
||||||
def test_one(self):
|
def test_one(self):
|
||||||
assert self.hello == "world"
|
assert self.hello == "world"
|
||||||
assert len(l) == 1
|
assert len(values) == 1
|
||||||
def test_two(self):
|
def test_two(self):
|
||||||
assert self.hello == "world"
|
assert self.hello == "world"
|
||||||
assert len(l) == 1
|
assert len(values) == 1
|
||||||
pytest.mark.usefixtures("myfix")(TestClass)
|
pytest.mark.usefixtures("myfix")(TestClass)
|
||||||
""")
|
""")
|
||||||
reprec = testdir.inline_run()
|
reprec = testdir.inline_run()
|
||||||
|
@ -1290,7 +1290,7 @@ class TestFixtureUsages(object):
|
||||||
testdir.makepyfile("""
|
testdir.makepyfile("""
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
l = []
|
values = []
|
||||||
def f():
|
def f():
|
||||||
yield 1
|
yield 1
|
||||||
yield 2
|
yield 2
|
||||||
|
@ -1304,14 +1304,14 @@ class TestFixtureUsages(object):
|
||||||
return request.param
|
return request.param
|
||||||
|
|
||||||
def test_1(arg):
|
def test_1(arg):
|
||||||
l.append(arg)
|
values.append(arg)
|
||||||
def test_2(arg2):
|
def test_2(arg2):
|
||||||
l.append(arg2*10)
|
values.append(arg2*10)
|
||||||
""")
|
""")
|
||||||
reprec = testdir.inline_run("-v")
|
reprec = testdir.inline_run("-v")
|
||||||
reprec.assertoutcome(passed=4)
|
reprec.assertoutcome(passed=4)
|
||||||
l = reprec.getcalls("pytest_runtest_call")[0].item.module.l
|
values = reprec.getcalls("pytest_runtest_call")[0].item.module.values
|
||||||
assert l == [1, 2, 10, 20]
|
assert values == [1, 2, 10, 20]
|
||||||
|
|
||||||
|
|
||||||
class TestFixtureManagerParseFactories(object):
|
class TestFixtureManagerParseFactories(object):
|
||||||
|
@ -1461,19 +1461,19 @@ class TestAutouseDiscovery(object):
|
||||||
testdir.makepyfile("""
|
testdir.makepyfile("""
|
||||||
import pytest
|
import pytest
|
||||||
class TestA(object):
|
class TestA(object):
|
||||||
l = []
|
values = []
|
||||||
@pytest.fixture(autouse=True)
|
@pytest.fixture(autouse=True)
|
||||||
def setup1(self):
|
def setup1(self):
|
||||||
self.l.append(1)
|
self.values.append(1)
|
||||||
def test_setup1(self):
|
def test_setup1(self):
|
||||||
assert self.l == [1]
|
assert self.values == [1]
|
||||||
class TestB(object):
|
class TestB(object):
|
||||||
l = []
|
values = []
|
||||||
@pytest.fixture(autouse=True)
|
@pytest.fixture(autouse=True)
|
||||||
def setup2(self):
|
def setup2(self):
|
||||||
self.l.append(1)
|
self.values.append(1)
|
||||||
def test_setup2(self):
|
def test_setup2(self):
|
||||||
assert self.l == [1]
|
assert self.values == [1]
|
||||||
""")
|
""")
|
||||||
reprec = testdir.inline_run()
|
reprec = testdir.inline_run()
|
||||||
reprec.assertoutcome(passed=2)
|
reprec.assertoutcome(passed=2)
|
||||||
|
@ -1556,22 +1556,22 @@ class TestAutouseDiscovery(object):
|
||||||
def test_autouse_in_module_and_two_classes(self, testdir):
|
def test_autouse_in_module_and_two_classes(self, testdir):
|
||||||
testdir.makepyfile("""
|
testdir.makepyfile("""
|
||||||
import pytest
|
import pytest
|
||||||
l = []
|
values = []
|
||||||
@pytest.fixture(autouse=True)
|
@pytest.fixture(autouse=True)
|
||||||
def append1():
|
def append1():
|
||||||
l.append("module")
|
values.append("module")
|
||||||
def test_x():
|
def test_x():
|
||||||
assert l == ["module"]
|
assert values == ["module"]
|
||||||
|
|
||||||
class TestA(object):
|
class TestA(object):
|
||||||
@pytest.fixture(autouse=True)
|
@pytest.fixture(autouse=True)
|
||||||
def append2(self):
|
def append2(self):
|
||||||
l.append("A")
|
values.append("A")
|
||||||
def test_hello(self):
|
def test_hello(self):
|
||||||
assert l == ["module", "module", "A"], l
|
assert values == ["module", "module", "A"], values
|
||||||
class TestA2(object):
|
class TestA2(object):
|
||||||
def test_world(self):
|
def test_world(self):
|
||||||
assert l == ["module", "module", "A", "module"], l
|
assert values == ["module", "module", "A", "module"], values
|
||||||
""")
|
""")
|
||||||
reprec = testdir.inline_run()
|
reprec = testdir.inline_run()
|
||||||
reprec.assertoutcome(passed=3)
|
reprec.assertoutcome(passed=3)
|
||||||
|
@ -1615,23 +1615,23 @@ class TestAutouseManagement(object):
|
||||||
def test_funcarg_and_setup(self, testdir):
|
def test_funcarg_and_setup(self, testdir):
|
||||||
testdir.makepyfile("""
|
testdir.makepyfile("""
|
||||||
import pytest
|
import pytest
|
||||||
l = []
|
values = []
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def arg():
|
def arg():
|
||||||
l.append(1)
|
values.append(1)
|
||||||
return 0
|
return 0
|
||||||
@pytest.fixture(scope="module", autouse=True)
|
@pytest.fixture(scope="module", autouse=True)
|
||||||
def something(arg):
|
def something(arg):
|
||||||
l.append(2)
|
values.append(2)
|
||||||
|
|
||||||
def test_hello(arg):
|
def test_hello(arg):
|
||||||
assert len(l) == 2
|
assert len(values) == 2
|
||||||
assert l == [1,2]
|
assert values == [1,2]
|
||||||
assert arg == 0
|
assert arg == 0
|
||||||
|
|
||||||
def test_hello2(arg):
|
def test_hello2(arg):
|
||||||
assert len(l) == 2
|
assert len(values) == 2
|
||||||
assert l == [1,2]
|
assert values == [1,2]
|
||||||
assert arg == 0
|
assert arg == 0
|
||||||
""")
|
""")
|
||||||
reprec = testdir.inline_run()
|
reprec = testdir.inline_run()
|
||||||
|
@ -1640,20 +1640,20 @@ class TestAutouseManagement(object):
|
||||||
def test_uses_parametrized_resource(self, testdir):
|
def test_uses_parametrized_resource(self, testdir):
|
||||||
testdir.makepyfile("""
|
testdir.makepyfile("""
|
||||||
import pytest
|
import pytest
|
||||||
l = []
|
values = []
|
||||||
@pytest.fixture(params=[1,2])
|
@pytest.fixture(params=[1,2])
|
||||||
def arg(request):
|
def arg(request):
|
||||||
return request.param
|
return request.param
|
||||||
|
|
||||||
@pytest.fixture(autouse=True)
|
@pytest.fixture(autouse=True)
|
||||||
def something(arg):
|
def something(arg):
|
||||||
l.append(arg)
|
values.append(arg)
|
||||||
|
|
||||||
def test_hello():
|
def test_hello():
|
||||||
if len(l) == 1:
|
if len(values) == 1:
|
||||||
assert l == [1]
|
assert values == [1]
|
||||||
elif len(l) == 2:
|
elif len(values) == 2:
|
||||||
assert l == [1, 2]
|
assert values == [1, 2]
|
||||||
else:
|
else:
|
||||||
0/0
|
0/0
|
||||||
|
|
||||||
|
@ -1665,7 +1665,7 @@ class TestAutouseManagement(object):
|
||||||
testdir.makepyfile("""
|
testdir.makepyfile("""
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
l = []
|
values = []
|
||||||
|
|
||||||
@pytest.fixture(scope="session", params=[1,2])
|
@pytest.fixture(scope="session", params=[1,2])
|
||||||
def arg(request):
|
def arg(request):
|
||||||
|
@ -1674,14 +1674,14 @@ class TestAutouseManagement(object):
|
||||||
@pytest.fixture(scope="function", autouse=True)
|
@pytest.fixture(scope="function", autouse=True)
|
||||||
def append(request, arg):
|
def append(request, arg):
|
||||||
if request.function.__name__ == "test_some":
|
if request.function.__name__ == "test_some":
|
||||||
l.append(arg)
|
values.append(arg)
|
||||||
|
|
||||||
def test_some():
|
def test_some():
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def test_result(arg):
|
def test_result(arg):
|
||||||
assert len(l) == arg
|
assert len(values) == arg
|
||||||
assert l[:arg] == [1,2][:arg]
|
assert values[:arg] == [1,2][:arg]
|
||||||
""")
|
""")
|
||||||
reprec = testdir.inline_run("-v", "-s")
|
reprec = testdir.inline_run("-v", "-s")
|
||||||
reprec.assertoutcome(passed=4)
|
reprec.assertoutcome(passed=4)
|
||||||
|
@ -1691,7 +1691,7 @@ class TestAutouseManagement(object):
|
||||||
import pytest
|
import pytest
|
||||||
import pprint
|
import pprint
|
||||||
|
|
||||||
l = []
|
values = []
|
||||||
|
|
||||||
@pytest.fixture(scope="function", params=[1,2])
|
@pytest.fixture(scope="function", params=[1,2])
|
||||||
def farg(request):
|
def farg(request):
|
||||||
|
@ -1704,7 +1704,7 @@ class TestAutouseManagement(object):
|
||||||
@pytest.fixture(scope="function", autouse=True)
|
@pytest.fixture(scope="function", autouse=True)
|
||||||
def append(request, farg, carg):
|
def append(request, farg, carg):
|
||||||
def fin():
|
def fin():
|
||||||
l.append("fin_%s%s" % (carg, farg))
|
values.append("fin_%s%s" % (carg, farg))
|
||||||
request.addfinalizer(fin)
|
request.addfinalizer(fin)
|
||||||
""")
|
""")
|
||||||
testdir.makepyfile("""
|
testdir.makepyfile("""
|
||||||
|
@ -1721,26 +1721,26 @@ class TestAutouseManagement(object):
|
||||||
reprec = testdir.inline_run("-v", "-s", confcut)
|
reprec = testdir.inline_run("-v", "-s", confcut)
|
||||||
reprec.assertoutcome(passed=8)
|
reprec.assertoutcome(passed=8)
|
||||||
config = reprec.getcalls("pytest_unconfigure")[0].config
|
config = reprec.getcalls("pytest_unconfigure")[0].config
|
||||||
l = config.pluginmanager._getconftestmodules(p)[0].l
|
values = config.pluginmanager._getconftestmodules(p)[0].values
|
||||||
assert l == ["fin_a1", "fin_a2", "fin_b1", "fin_b2"] * 2
|
assert values == ["fin_a1", "fin_a2", "fin_b1", "fin_b2"] * 2
|
||||||
|
|
||||||
def test_scope_ordering(self, testdir):
|
def test_scope_ordering(self, testdir):
|
||||||
testdir.makepyfile("""
|
testdir.makepyfile("""
|
||||||
import pytest
|
import pytest
|
||||||
l = []
|
values = []
|
||||||
@pytest.fixture(scope="function", autouse=True)
|
@pytest.fixture(scope="function", autouse=True)
|
||||||
def fappend2():
|
def fappend2():
|
||||||
l.append(2)
|
values.append(2)
|
||||||
@pytest.fixture(scope="class", autouse=True)
|
@pytest.fixture(scope="class", autouse=True)
|
||||||
def classappend3():
|
def classappend3():
|
||||||
l.append(3)
|
values.append(3)
|
||||||
@pytest.fixture(scope="module", autouse=True)
|
@pytest.fixture(scope="module", autouse=True)
|
||||||
def mappend():
|
def mappend():
|
||||||
l.append(1)
|
values.append(1)
|
||||||
|
|
||||||
class TestHallo(object):
|
class TestHallo(object):
|
||||||
def test_method(self):
|
def test_method(self):
|
||||||
assert l == [1,3,2]
|
assert values == [1,3,2]
|
||||||
""")
|
""")
|
||||||
reprec = testdir.inline_run()
|
reprec = testdir.inline_run()
|
||||||
reprec.assertoutcome(passed=1)
|
reprec.assertoutcome(passed=1)
|
||||||
|
@ -1748,23 +1748,23 @@ class TestAutouseManagement(object):
|
||||||
def test_parametrization_setup_teardown_ordering(self, testdir):
|
def test_parametrization_setup_teardown_ordering(self, testdir):
|
||||||
testdir.makepyfile("""
|
testdir.makepyfile("""
|
||||||
import pytest
|
import pytest
|
||||||
l = []
|
values = []
|
||||||
def pytest_generate_tests(metafunc):
|
def pytest_generate_tests(metafunc):
|
||||||
if metafunc.cls is not None:
|
if metafunc.cls is not None:
|
||||||
metafunc.parametrize("item", [1,2], scope="class")
|
metafunc.parametrize("item", [1,2], scope="class")
|
||||||
class TestClass(object):
|
class TestClass(object):
|
||||||
@pytest.fixture(scope="class", autouse=True)
|
@pytest.fixture(scope="class", autouse=True)
|
||||||
def addteardown(self, item, request):
|
def addteardown(self, item, request):
|
||||||
l.append("setup-%d" % item)
|
values.append("setup-%d" % item)
|
||||||
request.addfinalizer(lambda: l.append("teardown-%d" % item))
|
request.addfinalizer(lambda: values.append("teardown-%d" % item))
|
||||||
def test_step1(self, item):
|
def test_step1(self, item):
|
||||||
l.append("step1-%d" % item)
|
values.append("step1-%d" % item)
|
||||||
def test_step2(self, item):
|
def test_step2(self, item):
|
||||||
l.append("step2-%d" % item)
|
values.append("step2-%d" % item)
|
||||||
|
|
||||||
def test_finish():
|
def test_finish():
|
||||||
print (l)
|
print (values)
|
||||||
assert l == ["setup-1", "step1-1", "step2-1", "teardown-1",
|
assert values == ["setup-1", "step1-1", "step2-1", "teardown-1",
|
||||||
"setup-2", "step1-2", "step2-2", "teardown-2",]
|
"setup-2", "step1-2", "step2-2", "teardown-2",]
|
||||||
""")
|
""")
|
||||||
reprec = testdir.inline_run()
|
reprec = testdir.inline_run()
|
||||||
|
@ -1774,15 +1774,15 @@ class TestAutouseManagement(object):
|
||||||
testdir.makepyfile("""
|
testdir.makepyfile("""
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
l = []
|
values = []
|
||||||
@pytest.fixture(autouse=True)
|
@pytest.fixture(autouse=True)
|
||||||
def fix1():
|
def fix1():
|
||||||
l.append(1)
|
values.append(1)
|
||||||
@pytest.fixture()
|
@pytest.fixture()
|
||||||
def arg1():
|
def arg1():
|
||||||
l.append(2)
|
values.append(2)
|
||||||
def test_hello(arg1):
|
def test_hello(arg1):
|
||||||
assert l == [1,2]
|
assert values == [1,2]
|
||||||
""")
|
""")
|
||||||
reprec = testdir.inline_run()
|
reprec = testdir.inline_run()
|
||||||
reprec.assertoutcome(passed=1)
|
reprec.assertoutcome(passed=1)
|
||||||
|
@ -1793,20 +1793,20 @@ class TestAutouseManagement(object):
|
||||||
def test_ordering_dependencies_torndown_first(self, testdir, param1, param2):
|
def test_ordering_dependencies_torndown_first(self, testdir, param1, param2):
|
||||||
testdir.makepyfile("""
|
testdir.makepyfile("""
|
||||||
import pytest
|
import pytest
|
||||||
l = []
|
values = []
|
||||||
@pytest.fixture(%(param1)s)
|
@pytest.fixture(%(param1)s)
|
||||||
def arg1(request):
|
def arg1(request):
|
||||||
request.addfinalizer(lambda: l.append("fin1"))
|
request.addfinalizer(lambda: values.append("fin1"))
|
||||||
l.append("new1")
|
values.append("new1")
|
||||||
@pytest.fixture(%(param2)s)
|
@pytest.fixture(%(param2)s)
|
||||||
def arg2(request, arg1):
|
def arg2(request, arg1):
|
||||||
request.addfinalizer(lambda: l.append("fin2"))
|
request.addfinalizer(lambda: values.append("fin2"))
|
||||||
l.append("new2")
|
values.append("new2")
|
||||||
|
|
||||||
def test_arg(arg2):
|
def test_arg(arg2):
|
||||||
pass
|
pass
|
||||||
def test_check():
|
def test_check():
|
||||||
assert l == ["new1", "new2", "fin2", "fin1"]
|
assert values == ["new1", "new2", "fin2", "fin1"]
|
||||||
""" % locals())
|
""" % locals())
|
||||||
reprec = testdir.inline_run("-s")
|
reprec = testdir.inline_run("-s")
|
||||||
reprec.assertoutcome(passed=2)
|
reprec.assertoutcome(passed=2)
|
||||||
|
@ -1819,11 +1819,11 @@ class TestFixtureMarker(object):
|
||||||
@pytest.fixture(params=["a", "b", "c"])
|
@pytest.fixture(params=["a", "b", "c"])
|
||||||
def arg(request):
|
def arg(request):
|
||||||
return request.param
|
return request.param
|
||||||
l = []
|
values = []
|
||||||
def test_param(arg):
|
def test_param(arg):
|
||||||
l.append(arg)
|
values.append(arg)
|
||||||
def test_result():
|
def test_result():
|
||||||
assert l == list("abc")
|
assert values == list("abc")
|
||||||
""")
|
""")
|
||||||
reprec = testdir.inline_run()
|
reprec = testdir.inline_run()
|
||||||
reprec.assertoutcome(passed=4)
|
reprec.assertoutcome(passed=4)
|
||||||
|
@ -1867,21 +1867,21 @@ class TestFixtureMarker(object):
|
||||||
def test_scope_session(self, testdir):
|
def test_scope_session(self, testdir):
|
||||||
testdir.makepyfile("""
|
testdir.makepyfile("""
|
||||||
import pytest
|
import pytest
|
||||||
l = []
|
values = []
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def arg():
|
def arg():
|
||||||
l.append(1)
|
values.append(1)
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
def test_1(arg):
|
def test_1(arg):
|
||||||
assert arg == 1
|
assert arg == 1
|
||||||
def test_2(arg):
|
def test_2(arg):
|
||||||
assert arg == 1
|
assert arg == 1
|
||||||
assert len(l) == 1
|
assert len(values) == 1
|
||||||
class TestClass(object):
|
class TestClass(object):
|
||||||
def test3(self, arg):
|
def test3(self, arg):
|
||||||
assert arg == 1
|
assert arg == 1
|
||||||
assert len(l) == 1
|
assert len(values) == 1
|
||||||
""")
|
""")
|
||||||
reprec = testdir.inline_run()
|
reprec = testdir.inline_run()
|
||||||
reprec.assertoutcome(passed=3)
|
reprec.assertoutcome(passed=3)
|
||||||
|
@ -1889,10 +1889,10 @@ class TestFixtureMarker(object):
|
||||||
def test_scope_session_exc(self, testdir):
|
def test_scope_session_exc(self, testdir):
|
||||||
testdir.makepyfile("""
|
testdir.makepyfile("""
|
||||||
import pytest
|
import pytest
|
||||||
l = []
|
values = []
|
||||||
@pytest.fixture(scope="session")
|
@pytest.fixture(scope="session")
|
||||||
def fix():
|
def fix():
|
||||||
l.append(1)
|
values.append(1)
|
||||||
pytest.skip('skipping')
|
pytest.skip('skipping')
|
||||||
|
|
||||||
def test_1(fix):
|
def test_1(fix):
|
||||||
|
@ -1900,7 +1900,7 @@ class TestFixtureMarker(object):
|
||||||
def test_2(fix):
|
def test_2(fix):
|
||||||
pass
|
pass
|
||||||
def test_last():
|
def test_last():
|
||||||
assert l == [1]
|
assert values == [1]
|
||||||
""")
|
""")
|
||||||
reprec = testdir.inline_run()
|
reprec = testdir.inline_run()
|
||||||
reprec.assertoutcome(skipped=2, passed=1)
|
reprec.assertoutcome(skipped=2, passed=1)
|
||||||
|
@ -1908,11 +1908,11 @@ class TestFixtureMarker(object):
|
||||||
def test_scope_session_exc_two_fix(self, testdir):
|
def test_scope_session_exc_two_fix(self, testdir):
|
||||||
testdir.makepyfile("""
|
testdir.makepyfile("""
|
||||||
import pytest
|
import pytest
|
||||||
l = []
|
values = []
|
||||||
m = []
|
m = []
|
||||||
@pytest.fixture(scope="session")
|
@pytest.fixture(scope="session")
|
||||||
def a():
|
def a():
|
||||||
l.append(1)
|
values.append(1)
|
||||||
pytest.skip('skipping')
|
pytest.skip('skipping')
|
||||||
@pytest.fixture(scope="session")
|
@pytest.fixture(scope="session")
|
||||||
def b(a):
|
def b(a):
|
||||||
|
@ -1923,7 +1923,7 @@ class TestFixtureMarker(object):
|
||||||
def test_2(b):
|
def test_2(b):
|
||||||
pass
|
pass
|
||||||
def test_last():
|
def test_last():
|
||||||
assert l == [1]
|
assert values == [1]
|
||||||
assert m == []
|
assert m == []
|
||||||
""")
|
""")
|
||||||
reprec = testdir.inline_run()
|
reprec = testdir.inline_run()
|
||||||
|
@ -1961,21 +1961,21 @@ class TestFixtureMarker(object):
|
||||||
def test_scope_module_uses_session(self, testdir):
|
def test_scope_module_uses_session(self, testdir):
|
||||||
testdir.makepyfile("""
|
testdir.makepyfile("""
|
||||||
import pytest
|
import pytest
|
||||||
l = []
|
values = []
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def arg():
|
def arg():
|
||||||
l.append(1)
|
values.append(1)
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
def test_1(arg):
|
def test_1(arg):
|
||||||
assert arg == 1
|
assert arg == 1
|
||||||
def test_2(arg):
|
def test_2(arg):
|
||||||
assert arg == 1
|
assert arg == 1
|
||||||
assert len(l) == 1
|
assert len(values) == 1
|
||||||
class TestClass(object):
|
class TestClass(object):
|
||||||
def test3(self, arg):
|
def test3(self, arg):
|
||||||
assert arg == 1
|
assert arg == 1
|
||||||
assert len(l) == 1
|
assert len(values) == 1
|
||||||
""")
|
""")
|
||||||
reprec = testdir.inline_run()
|
reprec = testdir.inline_run()
|
||||||
reprec.assertoutcome(passed=3)
|
reprec.assertoutcome(passed=3)
|
||||||
|
@ -2070,17 +2070,17 @@ class TestFixtureMarker(object):
|
||||||
@pytest.fixture(scope="module", params=["a", "b", "c"])
|
@pytest.fixture(scope="module", params=["a", "b", "c"])
|
||||||
def arg(request):
|
def arg(request):
|
||||||
return request.param
|
return request.param
|
||||||
l = []
|
values = []
|
||||||
def test_param(arg):
|
def test_param(arg):
|
||||||
l.append(arg)
|
values.append(arg)
|
||||||
""")
|
""")
|
||||||
reprec = testdir.inline_run("-v")
|
reprec = testdir.inline_run("-v")
|
||||||
reprec.assertoutcome(passed=3)
|
reprec.assertoutcome(passed=3)
|
||||||
l = reprec.getcalls("pytest_runtest_call")[0].item.module.l
|
values = reprec.getcalls("pytest_runtest_call")[0].item.module.values
|
||||||
assert len(l) == 3
|
assert len(values) == 3
|
||||||
assert "a" in l
|
assert "a" in values
|
||||||
assert "b" in l
|
assert "b" in values
|
||||||
assert "c" in l
|
assert "c" in values
|
||||||
|
|
||||||
def test_scope_mismatch(self, testdir):
|
def test_scope_mismatch(self, testdir):
|
||||||
testdir.makeconftest("""
|
testdir.makeconftest("""
|
||||||
|
@ -2111,16 +2111,16 @@ class TestFixtureMarker(object):
|
||||||
def arg(request):
|
def arg(request):
|
||||||
return request.param
|
return request.param
|
||||||
|
|
||||||
l = []
|
values = []
|
||||||
def test_1(arg):
|
def test_1(arg):
|
||||||
l.append(arg)
|
values.append(arg)
|
||||||
def test_2(arg):
|
def test_2(arg):
|
||||||
l.append(arg)
|
values.append(arg)
|
||||||
""")
|
""")
|
||||||
reprec = testdir.inline_run("-v")
|
reprec = testdir.inline_run("-v")
|
||||||
reprec.assertoutcome(passed=4)
|
reprec.assertoutcome(passed=4)
|
||||||
l = reprec.getcalls("pytest_runtest_call")[0].item.module.l
|
values = reprec.getcalls("pytest_runtest_call")[0].item.module.values
|
||||||
assert l == [1, 1, 2, 2]
|
assert values == [1, 1, 2, 2]
|
||||||
|
|
||||||
def test_module_parametrized_ordering(self, testdir):
|
def test_module_parametrized_ordering(self, testdir):
|
||||||
testdir.makeconftest("""
|
testdir.makeconftest("""
|
||||||
|
@ -2172,7 +2172,7 @@ class TestFixtureMarker(object):
|
||||||
testdir.makeconftest("""
|
testdir.makeconftest("""
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
l = []
|
values = []
|
||||||
|
|
||||||
@pytest.fixture(scope="function", params=[1,2])
|
@pytest.fixture(scope="function", params=[1,2])
|
||||||
def farg(request):
|
def farg(request):
|
||||||
|
@ -2185,7 +2185,7 @@ class TestFixtureMarker(object):
|
||||||
@pytest.fixture(scope="function", autouse=True)
|
@pytest.fixture(scope="function", autouse=True)
|
||||||
def append(request, farg, carg):
|
def append(request, farg, carg):
|
||||||
def fin():
|
def fin():
|
||||||
l.append("fin_%s%s" % (carg, farg))
|
values.append("fin_%s%s" % (carg, farg))
|
||||||
request.addfinalizer(fin)
|
request.addfinalizer(fin)
|
||||||
""")
|
""")
|
||||||
testdir.makepyfile("""
|
testdir.makepyfile("""
|
||||||
|
@ -2223,30 +2223,30 @@ class TestFixtureMarker(object):
|
||||||
@pytest.fixture(scope="function", params=[1, 2])
|
@pytest.fixture(scope="function", params=[1, 2])
|
||||||
def arg(request):
|
def arg(request):
|
||||||
param = request.param
|
param = request.param
|
||||||
request.addfinalizer(lambda: l.append("fin:%s" % param))
|
request.addfinalizer(lambda: values.append("fin:%s" % param))
|
||||||
l.append("create:%s" % param)
|
values.append("create:%s" % param)
|
||||||
return request.param
|
return request.param
|
||||||
|
|
||||||
@pytest.fixture(scope="module", params=["mod1", "mod2"])
|
@pytest.fixture(scope="module", params=["mod1", "mod2"])
|
||||||
def modarg(request):
|
def modarg(request):
|
||||||
param = request.param
|
param = request.param
|
||||||
request.addfinalizer(lambda: l.append("fin:%s" % param))
|
request.addfinalizer(lambda: values.append("fin:%s" % param))
|
||||||
l.append("create:%s" % param)
|
values.append("create:%s" % param)
|
||||||
return request.param
|
return request.param
|
||||||
|
|
||||||
l = []
|
values = []
|
||||||
def test_1(arg):
|
def test_1(arg):
|
||||||
l.append("test1")
|
values.append("test1")
|
||||||
def test_2(modarg):
|
def test_2(modarg):
|
||||||
l.append("test2")
|
values.append("test2")
|
||||||
def test_3(arg, modarg):
|
def test_3(arg, modarg):
|
||||||
l.append("test3")
|
values.append("test3")
|
||||||
def test_4(modarg, arg):
|
def test_4(modarg, arg):
|
||||||
l.append("test4")
|
values.append("test4")
|
||||||
""")
|
""")
|
||||||
reprec = testdir.inline_run("-v")
|
reprec = testdir.inline_run("-v")
|
||||||
reprec.assertoutcome(passed=12)
|
reprec.assertoutcome(passed=12)
|
||||||
l = reprec.getcalls("pytest_runtest_call")[0].item.module.l
|
values = reprec.getcalls("pytest_runtest_call")[0].item.module.values
|
||||||
expected = [
|
expected = [
|
||||||
'create:1', 'test1', 'fin:1', 'create:2', 'test1',
|
'create:1', 'test1', 'fin:1', 'create:2', 'test1',
|
||||||
'fin:2', 'create:mod1', 'test2', 'create:1', 'test3',
|
'fin:2', 'create:mod1', 'test2', 'create:1', 'test3',
|
||||||
|
@ -2257,8 +2257,8 @@ class TestFixtureMarker(object):
|
||||||
'test4', 'fin:1', 'create:2', 'test4', 'fin:2',
|
'test4', 'fin:1', 'create:2', 'test4', 'fin:2',
|
||||||
'fin:mod2']
|
'fin:mod2']
|
||||||
import pprint
|
import pprint
|
||||||
pprint.pprint(list(zip(l, expected)))
|
pprint.pprint(list(zip(values, expected)))
|
||||||
assert l == expected
|
assert values == expected
|
||||||
|
|
||||||
def test_parametrized_fixture_teardown_order(self, testdir):
|
def test_parametrized_fixture_teardown_order(self, testdir):
|
||||||
testdir.makepyfile("""
|
testdir.makepyfile("""
|
||||||
|
@ -2267,29 +2267,29 @@ class TestFixtureMarker(object):
|
||||||
def param1(request):
|
def param1(request):
|
||||||
return request.param
|
return request.param
|
||||||
|
|
||||||
l = []
|
values = []
|
||||||
|
|
||||||
class TestClass(object):
|
class TestClass(object):
|
||||||
@classmethod
|
@classmethod
|
||||||
@pytest.fixture(scope="class", autouse=True)
|
@pytest.fixture(scope="class", autouse=True)
|
||||||
def setup1(self, request, param1):
|
def setup1(self, request, param1):
|
||||||
l.append(1)
|
values.append(1)
|
||||||
request.addfinalizer(self.teardown1)
|
request.addfinalizer(self.teardown1)
|
||||||
@classmethod
|
@classmethod
|
||||||
def teardown1(self):
|
def teardown1(self):
|
||||||
assert l.pop() == 1
|
assert values.pop() == 1
|
||||||
@pytest.fixture(scope="class", autouse=True)
|
@pytest.fixture(scope="class", autouse=True)
|
||||||
def setup2(self, request, param1):
|
def setup2(self, request, param1):
|
||||||
l.append(2)
|
values.append(2)
|
||||||
request.addfinalizer(self.teardown2)
|
request.addfinalizer(self.teardown2)
|
||||||
@classmethod
|
@classmethod
|
||||||
def teardown2(self):
|
def teardown2(self):
|
||||||
assert l.pop() == 2
|
assert values.pop() == 2
|
||||||
def test(self):
|
def test(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def test_finish():
|
def test_finish():
|
||||||
assert not l
|
assert not values
|
||||||
""")
|
""")
|
||||||
result = testdir.runpytest("-v")
|
result = testdir.runpytest("-v")
|
||||||
result.stdout.fnmatch_lines("""
|
result.stdout.fnmatch_lines("""
|
||||||
|
@ -2354,42 +2354,42 @@ class TestFixtureMarker(object):
|
||||||
def test_request_is_clean(self, testdir):
|
def test_request_is_clean(self, testdir):
|
||||||
testdir.makepyfile("""
|
testdir.makepyfile("""
|
||||||
import pytest
|
import pytest
|
||||||
l = []
|
values = []
|
||||||
@pytest.fixture(params=[1, 2])
|
@pytest.fixture(params=[1, 2])
|
||||||
def fix(request):
|
def fix(request):
|
||||||
request.addfinalizer(lambda: l.append(request.param))
|
request.addfinalizer(lambda: values.append(request.param))
|
||||||
def test_fix(fix):
|
def test_fix(fix):
|
||||||
pass
|
pass
|
||||||
""")
|
""")
|
||||||
reprec = testdir.inline_run("-s")
|
reprec = testdir.inline_run("-s")
|
||||||
l = reprec.getcalls("pytest_runtest_call")[0].item.module.l
|
values = reprec.getcalls("pytest_runtest_call")[0].item.module.values
|
||||||
assert l == [1, 2]
|
assert values == [1, 2]
|
||||||
|
|
||||||
def test_parametrize_separated_lifecycle(self, testdir):
|
def test_parametrize_separated_lifecycle(self, testdir):
|
||||||
testdir.makepyfile("""
|
testdir.makepyfile("""
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
l = []
|
values = []
|
||||||
@pytest.fixture(scope="module", params=[1, 2])
|
@pytest.fixture(scope="module", params=[1, 2])
|
||||||
def arg(request):
|
def arg(request):
|
||||||
x = request.param
|
x = request.param
|
||||||
request.addfinalizer(lambda: l.append("fin%s" % x))
|
request.addfinalizer(lambda: values.append("fin%s" % x))
|
||||||
return request.param
|
return request.param
|
||||||
def test_1(arg):
|
def test_1(arg):
|
||||||
l.append(arg)
|
values.append(arg)
|
||||||
def test_2(arg):
|
def test_2(arg):
|
||||||
l.append(arg)
|
values.append(arg)
|
||||||
""")
|
""")
|
||||||
reprec = testdir.inline_run("-vs")
|
reprec = testdir.inline_run("-vs")
|
||||||
reprec.assertoutcome(passed=4)
|
reprec.assertoutcome(passed=4)
|
||||||
l = reprec.getcalls("pytest_runtest_call")[0].item.module.l
|
values = reprec.getcalls("pytest_runtest_call")[0].item.module.values
|
||||||
import pprint
|
import pprint
|
||||||
pprint.pprint(l)
|
pprint.pprint(values)
|
||||||
# assert len(l) == 6
|
# assert len(values) == 6
|
||||||
assert l[0] == l[1] == 1
|
assert values[0] == values[1] == 1
|
||||||
assert l[2] == "fin1"
|
assert values[2] == "fin1"
|
||||||
assert l[3] == l[4] == 2
|
assert values[3] == values[4] == 2
|
||||||
assert l[5] == "fin2"
|
assert values[5] == "fin2"
|
||||||
|
|
||||||
def test_parametrize_function_scoped_finalizers_called(self, testdir):
|
def test_parametrize_function_scoped_finalizers_called(self, testdir):
|
||||||
testdir.makepyfile("""
|
testdir.makepyfile("""
|
||||||
|
@ -2398,17 +2398,17 @@ class TestFixtureMarker(object):
|
||||||
@pytest.fixture(scope="function", params=[1, 2])
|
@pytest.fixture(scope="function", params=[1, 2])
|
||||||
def arg(request):
|
def arg(request):
|
||||||
x = request.param
|
x = request.param
|
||||||
request.addfinalizer(lambda: l.append("fin%s" % x))
|
request.addfinalizer(lambda: values.append("fin%s" % x))
|
||||||
return request.param
|
return request.param
|
||||||
|
|
||||||
l = []
|
values = []
|
||||||
def test_1(arg):
|
def test_1(arg):
|
||||||
l.append(arg)
|
values.append(arg)
|
||||||
def test_2(arg):
|
def test_2(arg):
|
||||||
l.append(arg)
|
values.append(arg)
|
||||||
def test_3():
|
def test_3():
|
||||||
assert len(l) == 8
|
assert len(values) == 8
|
||||||
assert l == [1, "fin1", 2, "fin2", 1, "fin1", 2, "fin2"]
|
assert values == [1, "fin1", 2, "fin2", 1, "fin1", 2, "fin2"]
|
||||||
""")
|
""")
|
||||||
reprec = testdir.inline_run("-v")
|
reprec = testdir.inline_run("-v")
|
||||||
reprec.assertoutcome(passed=5)
|
reprec.assertoutcome(passed=5)
|
||||||
|
@ -2418,7 +2418,7 @@ class TestFixtureMarker(object):
|
||||||
def test_finalizer_order_on_parametrization(self, scope, testdir):
|
def test_finalizer_order_on_parametrization(self, scope, testdir):
|
||||||
testdir.makepyfile("""
|
testdir.makepyfile("""
|
||||||
import pytest
|
import pytest
|
||||||
l = []
|
values = []
|
||||||
|
|
||||||
@pytest.fixture(scope=%(scope)r, params=["1"])
|
@pytest.fixture(scope=%(scope)r, params=["1"])
|
||||||
def fix1(request):
|
def fix1(request):
|
||||||
|
@ -2427,13 +2427,13 @@ class TestFixtureMarker(object):
|
||||||
@pytest.fixture(scope=%(scope)r)
|
@pytest.fixture(scope=%(scope)r)
|
||||||
def fix2(request, base):
|
def fix2(request, base):
|
||||||
def cleanup_fix2():
|
def cleanup_fix2():
|
||||||
assert not l, "base should not have been finalized"
|
assert not values, "base should not have been finalized"
|
||||||
request.addfinalizer(cleanup_fix2)
|
request.addfinalizer(cleanup_fix2)
|
||||||
|
|
||||||
@pytest.fixture(scope=%(scope)r)
|
@pytest.fixture(scope=%(scope)r)
|
||||||
def base(request, fix1):
|
def base(request, fix1):
|
||||||
def cleanup_base():
|
def cleanup_base():
|
||||||
l.append("fin_base")
|
values.append("fin_base")
|
||||||
print ("finalizing base")
|
print ("finalizing base")
|
||||||
request.addfinalizer(cleanup_base)
|
request.addfinalizer(cleanup_base)
|
||||||
|
|
||||||
|
@ -2451,27 +2451,27 @@ class TestFixtureMarker(object):
|
||||||
def test_class_scope_parametrization_ordering(self, testdir):
|
def test_class_scope_parametrization_ordering(self, testdir):
|
||||||
testdir.makepyfile("""
|
testdir.makepyfile("""
|
||||||
import pytest
|
import pytest
|
||||||
l = []
|
values = []
|
||||||
@pytest.fixture(params=["John", "Doe"], scope="class")
|
@pytest.fixture(params=["John", "Doe"], scope="class")
|
||||||
def human(request):
|
def human(request):
|
||||||
request.addfinalizer(lambda: l.append("fin %s" % request.param))
|
request.addfinalizer(lambda: values.append("fin %s" % request.param))
|
||||||
return request.param
|
return request.param
|
||||||
|
|
||||||
class TestGreetings(object):
|
class TestGreetings(object):
|
||||||
def test_hello(self, human):
|
def test_hello(self, human):
|
||||||
l.append("test_hello")
|
values.append("test_hello")
|
||||||
|
|
||||||
class TestMetrics(object):
|
class TestMetrics(object):
|
||||||
def test_name(self, human):
|
def test_name(self, human):
|
||||||
l.append("test_name")
|
values.append("test_name")
|
||||||
|
|
||||||
def test_population(self, human):
|
def test_population(self, human):
|
||||||
l.append("test_population")
|
values.append("test_population")
|
||||||
""")
|
""")
|
||||||
reprec = testdir.inline_run()
|
reprec = testdir.inline_run()
|
||||||
reprec.assertoutcome(passed=6)
|
reprec.assertoutcome(passed=6)
|
||||||
l = reprec.getcalls("pytest_runtest_call")[0].item.module.l
|
values = reprec.getcalls("pytest_runtest_call")[0].item.module.values
|
||||||
assert l == ["test_hello", "fin John", "test_hello", "fin Doe",
|
assert values == ["test_hello", "fin John", "test_hello", "fin Doe",
|
||||||
"test_name", "test_population", "fin John",
|
"test_name", "test_population", "fin John",
|
||||||
"test_name", "test_population", "fin Doe"]
|
"test_name", "test_population", "fin Doe"]
|
||||||
|
|
||||||
|
@ -2485,21 +2485,21 @@ class TestFixtureMarker(object):
|
||||||
|
|
||||||
@pytest.fixture(scope="module", autouse=True)
|
@pytest.fixture(scope="module", autouse=True)
|
||||||
def mysetup(request, arg):
|
def mysetup(request, arg):
|
||||||
request.addfinalizer(lambda: l.append("fin%s" % arg))
|
request.addfinalizer(lambda: values.append("fin%s" % arg))
|
||||||
l.append("setup%s" % arg)
|
values.append("setup%s" % arg)
|
||||||
|
|
||||||
l = []
|
values = []
|
||||||
def test_1(arg):
|
def test_1(arg):
|
||||||
l.append(arg)
|
values.append(arg)
|
||||||
def test_2(arg):
|
def test_2(arg):
|
||||||
l.append(arg)
|
values.append(arg)
|
||||||
def test_3():
|
def test_3():
|
||||||
import pprint
|
import pprint
|
||||||
pprint.pprint(l)
|
pprint.pprint(values)
|
||||||
if arg == 1:
|
if arg == 1:
|
||||||
assert l == ["setup1", 1, 1, ]
|
assert values == ["setup1", 1, 1, ]
|
||||||
elif arg == 2:
|
elif arg == 2:
|
||||||
assert l == ["setup1", 1, 1, "fin1",
|
assert values == ["setup1", 1, 1, "fin1",
|
||||||
"setup2", 2, 2, ]
|
"setup2", 2, 2, ]
|
||||||
|
|
||||||
""")
|
""")
|
||||||
|
@ -2660,13 +2660,13 @@ class TestErrors(object):
|
||||||
request.addfinalizer(f)
|
request.addfinalizer(f)
|
||||||
return object()
|
return object()
|
||||||
|
|
||||||
l = []
|
values = []
|
||||||
def test_1(fix1):
|
def test_1(fix1):
|
||||||
l.append(fix1)
|
values.append(fix1)
|
||||||
def test_2(fix1):
|
def test_2(fix1):
|
||||||
l.append(fix1)
|
values.append(fix1)
|
||||||
def test_3():
|
def test_3():
|
||||||
assert l[0] != l[1]
|
assert values[0] != values[1]
|
||||||
""")
|
""")
|
||||||
result = testdir.runpytest()
|
result = testdir.runpytest()
|
||||||
result.stdout.fnmatch_lines("""
|
result.stdout.fnmatch_lines("""
|
||||||
|
|
|
@ -93,8 +93,8 @@ class TestMockDecoration(object):
|
||||||
def f(x):
|
def f(x):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
l = getfuncargnames(f)
|
values = getfuncargnames(f)
|
||||||
assert l == ("x",)
|
assert values == ("x",)
|
||||||
|
|
||||||
def test_wrapped_getfuncargnames_patching(self):
|
def test_wrapped_getfuncargnames_patching(self):
|
||||||
from _pytest.compat import getfuncargnames
|
from _pytest.compat import getfuncargnames
|
||||||
|
@ -110,8 +110,8 @@ class TestMockDecoration(object):
|
||||||
def f(x, y, z):
|
def f(x, y, z):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
l = getfuncargnames(f)
|
values = getfuncargnames(f)
|
||||||
assert l == ("y", "z")
|
assert values == ("y", "z")
|
||||||
|
|
||||||
def test_unittest_mock(self, testdir):
|
def test_unittest_mock(self, testdir):
|
||||||
pytest.importorskip("unittest.mock")
|
pytest.importorskip("unittest.mock")
|
||||||
|
|
|
@ -1071,21 +1071,21 @@ class TestMetafuncFunctional(object):
|
||||||
def test_parametrize_scope_overrides(self, testdir, scope, length):
|
def test_parametrize_scope_overrides(self, testdir, scope, length):
|
||||||
testdir.makepyfile("""
|
testdir.makepyfile("""
|
||||||
import pytest
|
import pytest
|
||||||
l = []
|
values = []
|
||||||
def pytest_generate_tests(metafunc):
|
def pytest_generate_tests(metafunc):
|
||||||
if "arg" in metafunc.funcargnames:
|
if "arg" in metafunc.funcargnames:
|
||||||
metafunc.parametrize("arg", [1,2], indirect=True,
|
metafunc.parametrize("arg", [1,2], indirect=True,
|
||||||
scope=%r)
|
scope=%r)
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def arg(request):
|
def arg(request):
|
||||||
l.append(request.param)
|
values.append(request.param)
|
||||||
return request.param
|
return request.param
|
||||||
def test_hello(arg):
|
def test_hello(arg):
|
||||||
assert arg in (1,2)
|
assert arg in (1,2)
|
||||||
def test_world(arg):
|
def test_world(arg):
|
||||||
assert arg in (1,2)
|
assert arg in (1,2)
|
||||||
def test_checklength():
|
def test_checklength():
|
||||||
assert len(l) == %d
|
assert len(values) == %d
|
||||||
""" % (scope, length))
|
""" % (scope, length))
|
||||||
reprec = testdir.inline_run()
|
reprec = testdir.inline_run()
|
||||||
reprec.assertoutcome(passed=5)
|
reprec.assertoutcome(passed=5)
|
||||||
|
|
|
@ -135,3 +135,24 @@ def test_verbose_include_private_fixtures_and_loc(testdir):
|
||||||
'arg3 -- test_verbose_include_private_fixtures_and_loc.py:3',
|
'arg3 -- test_verbose_include_private_fixtures_and_loc.py:3',
|
||||||
' arg3 from testmodule',
|
' 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*',
|
||||||
|
])
|
||||||
|
|
|
@ -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')")
|
||||||
|
|
|
@ -229,9 +229,9 @@ class TestImportHookInstallation(object):
|
||||||
return pkg.helper.tool
|
return pkg.helper.tool
|
||||||
""",
|
""",
|
||||||
'pkg/other.py': """
|
'pkg/other.py': """
|
||||||
l = [3, 2]
|
values = [3, 2]
|
||||||
def tool():
|
def tool():
|
||||||
assert l.pop() == 3
|
assert values.pop() == 3
|
||||||
""",
|
""",
|
||||||
'conftest.py': """
|
'conftest.py': """
|
||||||
pytest_plugins = ['pkg.plugin']
|
pytest_plugins = ['pkg.plugin']
|
||||||
|
@ -248,7 +248,7 @@ class TestImportHookInstallation(object):
|
||||||
result = testdir.runpytest_subprocess('--assert=rewrite')
|
result = testdir.runpytest_subprocess('--assert=rewrite')
|
||||||
result.stdout.fnmatch_lines(['>*assert a == b*',
|
result.stdout.fnmatch_lines(['>*assert a == b*',
|
||||||
'E*assert 2 == 3*',
|
'E*assert 2 == 3*',
|
||||||
'>*assert l.pop() == 3*',
|
'>*assert values.pop() == 3*',
|
||||||
'E*AssertionError'])
|
'E*AssertionError'])
|
||||||
|
|
||||||
def test_register_assert_rewrite_checks_types(self):
|
def test_register_assert_rewrite_checks_types(self):
|
||||||
|
@ -263,13 +263,13 @@ class TestBinReprIntegration(object):
|
||||||
def test_pytest_assertrepr_compare_called(self, testdir):
|
def test_pytest_assertrepr_compare_called(self, testdir):
|
||||||
testdir.makeconftest("""
|
testdir.makeconftest("""
|
||||||
import pytest
|
import pytest
|
||||||
l = []
|
values = []
|
||||||
def pytest_assertrepr_compare(op, left, right):
|
def pytest_assertrepr_compare(op, left, right):
|
||||||
l.append((op, left, right))
|
values.append((op, left, right))
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def list(request):
|
def list(request):
|
||||||
return l
|
return values
|
||||||
""")
|
""")
|
||||||
testdir.makepyfile("""
|
testdir.makepyfile("""
|
||||||
def test_hello():
|
def test_hello():
|
||||||
|
|
|
@ -65,13 +65,18 @@ class TestAssertionRewrite(object):
|
||||||
def test_place_initial_imports(self):
|
def test_place_initial_imports(self):
|
||||||
s = """'Doc string'\nother = stuff"""
|
s = """'Doc string'\nother = stuff"""
|
||||||
m = rewrite(s)
|
m = rewrite(s)
|
||||||
|
# Module docstrings in 3.7 are part of Module node, it's not in the body
|
||||||
|
# so we remove it so the following body items have the same indexes on
|
||||||
|
# all Python versions
|
||||||
|
if sys.version_info < (3, 7):
|
||||||
assert isinstance(m.body[0], ast.Expr)
|
assert isinstance(m.body[0], ast.Expr)
|
||||||
assert isinstance(m.body[0].value, ast.Str)
|
assert isinstance(m.body[0].value, ast.Str)
|
||||||
for imp in m.body[1:3]:
|
del m.body[0]
|
||||||
|
for imp in m.body[0:2]:
|
||||||
assert isinstance(imp, ast.Import)
|
assert isinstance(imp, ast.Import)
|
||||||
assert imp.lineno == 2
|
assert imp.lineno == 2
|
||||||
assert imp.col_offset == 0
|
assert imp.col_offset == 0
|
||||||
assert isinstance(m.body[3], ast.Assign)
|
assert isinstance(m.body[2], ast.Assign)
|
||||||
s = """from __future__ import with_statement\nother_stuff"""
|
s = """from __future__ import with_statement\nother_stuff"""
|
||||||
m = rewrite(s)
|
m = rewrite(s)
|
||||||
assert isinstance(m.body[0], ast.ImportFrom)
|
assert isinstance(m.body[0], ast.ImportFrom)
|
||||||
|
@ -80,16 +85,29 @@ class TestAssertionRewrite(object):
|
||||||
assert imp.lineno == 2
|
assert imp.lineno == 2
|
||||||
assert imp.col_offset == 0
|
assert imp.col_offset == 0
|
||||||
assert isinstance(m.body[3], ast.Expr)
|
assert isinstance(m.body[3], ast.Expr)
|
||||||
s = """'doc string'\nfrom __future__ import with_statement\nother"""
|
s = """'doc string'\nfrom __future__ import with_statement"""
|
||||||
m = rewrite(s)
|
m = rewrite(s)
|
||||||
|
if sys.version_info < (3, 7):
|
||||||
assert isinstance(m.body[0], ast.Expr)
|
assert isinstance(m.body[0], ast.Expr)
|
||||||
assert isinstance(m.body[0].value, ast.Str)
|
assert isinstance(m.body[0].value, ast.Str)
|
||||||
assert isinstance(m.body[1], ast.ImportFrom)
|
del m.body[0]
|
||||||
for imp in m.body[2:4]:
|
assert isinstance(m.body[0], ast.ImportFrom)
|
||||||
|
for imp in m.body[1:3]:
|
||||||
|
assert isinstance(imp, ast.Import)
|
||||||
|
assert imp.lineno == 2
|
||||||
|
assert imp.col_offset == 0
|
||||||
|
s = """'doc string'\nfrom __future__ import with_statement\nother"""
|
||||||
|
m = rewrite(s)
|
||||||
|
if sys.version_info < (3, 7):
|
||||||
|
assert isinstance(m.body[0], ast.Expr)
|
||||||
|
assert isinstance(m.body[0].value, ast.Str)
|
||||||
|
del m.body[0]
|
||||||
|
assert isinstance(m.body[0], ast.ImportFrom)
|
||||||
|
for imp in m.body[1:3]:
|
||||||
assert isinstance(imp, ast.Import)
|
assert isinstance(imp, ast.Import)
|
||||||
assert imp.lineno == 3
|
assert imp.lineno == 3
|
||||||
assert imp.col_offset == 0
|
assert imp.col_offset == 0
|
||||||
assert isinstance(m.body[4], ast.Expr)
|
assert isinstance(m.body[3], ast.Expr)
|
||||||
s = """from . import relative\nother_stuff"""
|
s = """from . import relative\nother_stuff"""
|
||||||
m = rewrite(s)
|
m = rewrite(s)
|
||||||
for imp in m.body[0:2]:
|
for imp in m.body[0:2]:
|
||||||
|
@ -101,10 +119,14 @@ class TestAssertionRewrite(object):
|
||||||
def test_dont_rewrite(self):
|
def test_dont_rewrite(self):
|
||||||
s = """'PYTEST_DONT_REWRITE'\nassert 14"""
|
s = """'PYTEST_DONT_REWRITE'\nassert 14"""
|
||||||
m = rewrite(s)
|
m = rewrite(s)
|
||||||
|
if sys.version_info < (3, 7):
|
||||||
assert len(m.body) == 2
|
assert len(m.body) == 2
|
||||||
|
assert isinstance(m.body[0], ast.Expr)
|
||||||
assert isinstance(m.body[0].value, ast.Str)
|
assert isinstance(m.body[0].value, ast.Str)
|
||||||
assert isinstance(m.body[1], ast.Assert)
|
del m.body[0]
|
||||||
assert m.body[1].msg is None
|
else:
|
||||||
|
assert len(m.body) == 1
|
||||||
|
assert m.body[0].msg is None
|
||||||
|
|
||||||
def test_name(self):
|
def test_name(self):
|
||||||
def f():
|
def f():
|
||||||
|
@ -451,8 +473,8 @@ class TestAssertionRewrite(object):
|
||||||
def test_len(self):
|
def test_len(self):
|
||||||
|
|
||||||
def f():
|
def f():
|
||||||
l = list(range(10))
|
values = list(range(10))
|
||||||
assert len(l) == 11
|
assert len(values) == 11
|
||||||
|
|
||||||
assert getmsg(f).startswith("""assert 10 == 11
|
assert getmsg(f).startswith("""assert 10 == 11
|
||||||
+ where 10 = len([""")
|
+ where 10 = len([""")
|
||||||
|
|
|
@ -2,6 +2,7 @@ from __future__ import absolute_import, division, print_function
|
||||||
import pytest
|
import pytest
|
||||||
import py
|
import py
|
||||||
|
|
||||||
|
import _pytest._code
|
||||||
from _pytest.main import Session, EXIT_NOTESTSCOLLECTED, _in_venv
|
from _pytest.main import Session, EXIT_NOTESTSCOLLECTED, _in_venv
|
||||||
|
|
||||||
|
|
||||||
|
@ -702,9 +703,9 @@ class TestNodekeywords(object):
|
||||||
def test_pass(): pass
|
def test_pass(): pass
|
||||||
def test_fail(): assert 0
|
def test_fail(): assert 0
|
||||||
""")
|
""")
|
||||||
l = list(modcol.keywords)
|
values = list(modcol.keywords)
|
||||||
assert modcol.name in l
|
assert modcol.name in values
|
||||||
for x in l:
|
for x in values:
|
||||||
assert not x.startswith("_")
|
assert not x.startswith("_")
|
||||||
assert modcol.name in repr(modcol.keywords)
|
assert modcol.name in repr(modcol.keywords)
|
||||||
|
|
||||||
|
@ -830,3 +831,28 @@ def test_continue_on_collection_errors_maxfail(testdir):
|
||||||
"*Interrupted: stopping after 3 failures*",
|
"*Interrupted: stopping after 3 failures*",
|
||||||
"*1 failed, 2 error*",
|
"*1 failed, 2 error*",
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
||||||
|
def test_fixture_scope_sibling_conftests(testdir):
|
||||||
|
"""Regression test case for https://github.com/pytest-dev/pytest/issues/2836"""
|
||||||
|
foo_path = testdir.mkpydir("foo")
|
||||||
|
foo_path.join("conftest.py").write(_pytest._code.Source("""
|
||||||
|
import pytest
|
||||||
|
@pytest.fixture
|
||||||
|
def fix():
|
||||||
|
return 1
|
||||||
|
"""))
|
||||||
|
foo_path.join("test_foo.py").write("def test_foo(fix): assert fix == 1")
|
||||||
|
|
||||||
|
# Tests in `food/` should not see the conftest fixture from `foo/`
|
||||||
|
food_path = testdir.mkpydir("food")
|
||||||
|
food_path.join("test_food.py").write("def test_food(fix): assert fix == 1")
|
||||||
|
|
||||||
|
res = testdir.runpytest()
|
||||||
|
assert res.ret == 1
|
||||||
|
|
||||||
|
res.stdout.fnmatch_lines([
|
||||||
|
"*ERROR at setup of test_food*",
|
||||||
|
"E*fixture 'fix' not found",
|
||||||
|
"*1 passed, 1 error*",
|
||||||
|
])
|
||||||
|
|
|
@ -123,11 +123,11 @@ class TestConfigCmdlineParsing(object):
|
||||||
class TestConfigAPI(object):
|
class TestConfigAPI(object):
|
||||||
def test_config_trace(self, testdir):
|
def test_config_trace(self, testdir):
|
||||||
config = testdir.parseconfig()
|
config = testdir.parseconfig()
|
||||||
l = []
|
values = []
|
||||||
config.trace.root.setwriter(l.append)
|
config.trace.root.setwriter(values.append)
|
||||||
config.trace("hello")
|
config.trace("hello")
|
||||||
assert len(l) == 1
|
assert len(values) == 1
|
||||||
assert l[0] == "hello [config]\n"
|
assert values[0] == "hello [config]\n"
|
||||||
|
|
||||||
def test_config_getoption(self, testdir):
|
def test_config_getoption(self, testdir):
|
||||||
testdir.makeconftest("""
|
testdir.makeconftest("""
|
||||||
|
@ -209,10 +209,10 @@ class TestConfigAPI(object):
|
||||||
paths=hello world/sub.py
|
paths=hello world/sub.py
|
||||||
""")
|
""")
|
||||||
config = testdir.parseconfig()
|
config = testdir.parseconfig()
|
||||||
l = config.getini("paths")
|
values = config.getini("paths")
|
||||||
assert len(l) == 2
|
assert len(values) == 2
|
||||||
assert l[0] == p.dirpath('hello')
|
assert values[0] == p.dirpath('hello')
|
||||||
assert l[1] == p.dirpath('world/sub.py')
|
assert values[1] == p.dirpath('world/sub.py')
|
||||||
pytest.raises(ValueError, config.getini, 'other')
|
pytest.raises(ValueError, config.getini, 'other')
|
||||||
|
|
||||||
def test_addini_args(self, testdir):
|
def test_addini_args(self, testdir):
|
||||||
|
@ -226,11 +226,11 @@ class TestConfigAPI(object):
|
||||||
args=123 "123 hello" "this"
|
args=123 "123 hello" "this"
|
||||||
""")
|
""")
|
||||||
config = testdir.parseconfig()
|
config = testdir.parseconfig()
|
||||||
l = config.getini("args")
|
values = config.getini("args")
|
||||||
assert len(l) == 3
|
assert len(values) == 3
|
||||||
assert l == ["123", "123 hello", "this"]
|
assert values == ["123", "123 hello", "this"]
|
||||||
l = config.getini("a2")
|
values = config.getini("a2")
|
||||||
assert l == list("123")
|
assert values == list("123")
|
||||||
|
|
||||||
def test_addini_linelist(self, testdir):
|
def test_addini_linelist(self, testdir):
|
||||||
testdir.makeconftest("""
|
testdir.makeconftest("""
|
||||||
|
@ -244,11 +244,11 @@ class TestConfigAPI(object):
|
||||||
second line
|
second line
|
||||||
""")
|
""")
|
||||||
config = testdir.parseconfig()
|
config = testdir.parseconfig()
|
||||||
l = config.getini("xy")
|
values = config.getini("xy")
|
||||||
assert len(l) == 2
|
assert len(values) == 2
|
||||||
assert l == ["123 345", "second line"]
|
assert values == ["123 345", "second line"]
|
||||||
l = config.getini("a2")
|
values = config.getini("a2")
|
||||||
assert l == []
|
assert values == []
|
||||||
|
|
||||||
@pytest.mark.parametrize('str_val, bool_val',
|
@pytest.mark.parametrize('str_val, bool_val',
|
||||||
[('True', True), ('no', False), ('no-ini', True)])
|
[('True', True), ('no', False), ('no-ini', True)])
|
||||||
|
@ -275,13 +275,13 @@ class TestConfigAPI(object):
|
||||||
xy= 123
|
xy= 123
|
||||||
""")
|
""")
|
||||||
config = testdir.parseconfig()
|
config = testdir.parseconfig()
|
||||||
l = config.getini("xy")
|
values = config.getini("xy")
|
||||||
assert len(l) == 1
|
assert len(values) == 1
|
||||||
assert l == ["123"]
|
assert values == ["123"]
|
||||||
config.addinivalue_line("xy", "456")
|
config.addinivalue_line("xy", "456")
|
||||||
l = config.getini("xy")
|
values = config.getini("xy")
|
||||||
assert len(l) == 2
|
assert len(values) == 2
|
||||||
assert l == ["123", "456"]
|
assert values == ["123", "456"]
|
||||||
|
|
||||||
def test_addinivalue_line_new(self, testdir):
|
def test_addinivalue_line_new(self, testdir):
|
||||||
testdir.makeconftest("""
|
testdir.makeconftest("""
|
||||||
|
@ -291,13 +291,13 @@ class TestConfigAPI(object):
|
||||||
config = testdir.parseconfig()
|
config = testdir.parseconfig()
|
||||||
assert not config.getini("xy")
|
assert not config.getini("xy")
|
||||||
config.addinivalue_line("xy", "456")
|
config.addinivalue_line("xy", "456")
|
||||||
l = config.getini("xy")
|
values = config.getini("xy")
|
||||||
assert len(l) == 1
|
assert len(values) == 1
|
||||||
assert l == ["456"]
|
assert values == ["456"]
|
||||||
config.addinivalue_line("xy", "123")
|
config.addinivalue_line("xy", "123")
|
||||||
l = config.getini("xy")
|
values = config.getini("xy")
|
||||||
assert len(l) == 2
|
assert len(values) == 2
|
||||||
assert l == ["456", "123"]
|
assert values == ["456", "123"]
|
||||||
|
|
||||||
def test_confcutdir_check_isdir(self, testdir):
|
def test_confcutdir_check_isdir(self, testdir):
|
||||||
"""Give an error if --confcutdir is not a valid directory (#2078)"""
|
"""Give an error if --confcutdir is not a valid directory (#2078)"""
|
||||||
|
@ -596,13 +596,13 @@ def test_load_initial_conftest_last_ordering(testdir):
|
||||||
m = My()
|
m = My()
|
||||||
pm.register(m)
|
pm.register(m)
|
||||||
hc = pm.hook.pytest_load_initial_conftests
|
hc = pm.hook.pytest_load_initial_conftests
|
||||||
l = hc._nonwrappers + hc._wrappers
|
values = hc._nonwrappers + hc._wrappers
|
||||||
expected = [
|
expected = [
|
||||||
"_pytest.config",
|
"_pytest.config",
|
||||||
'test_config',
|
'test_config',
|
||||||
'_pytest.capture',
|
'_pytest.capture',
|
||||||
]
|
]
|
||||||
assert [x.function.__module__ for x in l] == expected
|
assert [x.function.__module__ for x in values] == expected
|
||||||
|
|
||||||
|
|
||||||
def test_get_plugin_specs_as_list():
|
def test_get_plugin_specs_as_list():
|
||||||
|
@ -623,17 +623,17 @@ def test_get_plugin_specs_as_list():
|
||||||
class TestWarning(object):
|
class TestWarning(object):
|
||||||
def test_warn_config(self, testdir):
|
def test_warn_config(self, testdir):
|
||||||
testdir.makeconftest("""
|
testdir.makeconftest("""
|
||||||
l = []
|
values = []
|
||||||
def pytest_configure(config):
|
def pytest_configure(config):
|
||||||
config.warn("C1", "hello")
|
config.warn("C1", "hello")
|
||||||
def pytest_logwarning(code, message):
|
def pytest_logwarning(code, message):
|
||||||
if message == "hello" and code == "C1":
|
if message == "hello" and code == "C1":
|
||||||
l.append(1)
|
values.append(1)
|
||||||
""")
|
""")
|
||||||
testdir.makepyfile("""
|
testdir.makepyfile("""
|
||||||
def test_proper(pytestconfig):
|
def test_proper(pytestconfig):
|
||||||
import conftest
|
import conftest
|
||||||
assert conftest.l == [1]
|
assert conftest.values == [1]
|
||||||
""")
|
""")
|
||||||
reprec = testdir.inline_run()
|
reprec = testdir.inline_run()
|
||||||
reprec.assertoutcome(passed=1)
|
reprec.assertoutcome(passed=1)
|
||||||
|
|
|
@ -87,8 +87,8 @@ def test_doubledash_considered(testdir):
|
||||||
conf.join("conftest.py").ensure()
|
conf.join("conftest.py").ensure()
|
||||||
conftest = PytestPluginManager()
|
conftest = PytestPluginManager()
|
||||||
conftest_setinitial(conftest, [conf.basename, conf.basename])
|
conftest_setinitial(conftest, [conf.basename, conf.basename])
|
||||||
l = conftest._getconftestmodules(conf)
|
values = conftest._getconftestmodules(conf)
|
||||||
assert len(l) == 1
|
assert len(values) == 1
|
||||||
|
|
||||||
|
|
||||||
def test_issue151_load_all_conftests(testdir):
|
def test_issue151_load_all_conftests(testdir):
|
||||||
|
@ -130,28 +130,28 @@ def test_conftestcutdir(testdir):
|
||||||
p = testdir.mkdir("x")
|
p = testdir.mkdir("x")
|
||||||
conftest = PytestPluginManager()
|
conftest = PytestPluginManager()
|
||||||
conftest_setinitial(conftest, [testdir.tmpdir], confcutdir=p)
|
conftest_setinitial(conftest, [testdir.tmpdir], confcutdir=p)
|
||||||
l = conftest._getconftestmodules(p)
|
values = conftest._getconftestmodules(p)
|
||||||
assert len(l) == 0
|
assert len(values) == 0
|
||||||
l = conftest._getconftestmodules(conf.dirpath())
|
values = conftest._getconftestmodules(conf.dirpath())
|
||||||
assert len(l) == 0
|
assert len(values) == 0
|
||||||
assert conf not in conftest._conftestpath2mod
|
assert conf not in conftest._conftestpath2mod
|
||||||
# but we can still import a conftest directly
|
# but we can still import a conftest directly
|
||||||
conftest._importconftest(conf)
|
conftest._importconftest(conf)
|
||||||
l = conftest._getconftestmodules(conf.dirpath())
|
values = conftest._getconftestmodules(conf.dirpath())
|
||||||
assert l[0].__file__.startswith(str(conf))
|
assert values[0].__file__.startswith(str(conf))
|
||||||
# and all sub paths get updated properly
|
# and all sub paths get updated properly
|
||||||
l = conftest._getconftestmodules(p)
|
values = conftest._getconftestmodules(p)
|
||||||
assert len(l) == 1
|
assert len(values) == 1
|
||||||
assert l[0].__file__.startswith(str(conf))
|
assert values[0].__file__.startswith(str(conf))
|
||||||
|
|
||||||
|
|
||||||
def test_conftestcutdir_inplace_considered(testdir):
|
def test_conftestcutdir_inplace_considered(testdir):
|
||||||
conf = testdir.makeconftest("")
|
conf = testdir.makeconftest("")
|
||||||
conftest = PytestPluginManager()
|
conftest = PytestPluginManager()
|
||||||
conftest_setinitial(conftest, [conf.dirpath()], confcutdir=conf.dirpath())
|
conftest_setinitial(conftest, [conf.dirpath()], confcutdir=conf.dirpath())
|
||||||
l = conftest._getconftestmodules(conf.dirpath())
|
values = conftest._getconftestmodules(conf.dirpath())
|
||||||
assert len(l) == 1
|
assert len(values) == 1
|
||||||
assert l[0].__file__.startswith(str(conf))
|
assert values[0].__file__.startswith(str(conf))
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("name", 'test tests whatever .dotdir'.split())
|
@pytest.mark.parametrize("name", 'test tests whatever .dotdir'.split())
|
||||||
|
|
|
@ -173,7 +173,7 @@ class TestDoctests(object):
|
||||||
"*UNEXPECTED*ZeroDivision*",
|
"*UNEXPECTED*ZeroDivision*",
|
||||||
])
|
])
|
||||||
|
|
||||||
def test_docstring_context_around_error(self, testdir):
|
def test_docstring_partial_context_around_error(self, testdir):
|
||||||
"""Test that we show some context before the actual line of a failing
|
"""Test that we show some context before the actual line of a failing
|
||||||
doctest.
|
doctest.
|
||||||
"""
|
"""
|
||||||
|
@ -199,7 +199,7 @@ class TestDoctests(object):
|
||||||
''')
|
''')
|
||||||
result = testdir.runpytest('--doctest-modules')
|
result = testdir.runpytest('--doctest-modules')
|
||||||
result.stdout.fnmatch_lines([
|
result.stdout.fnmatch_lines([
|
||||||
'*docstring_context_around_error*',
|
'*docstring_partial_context_around_error*',
|
||||||
'005*text-line-3',
|
'005*text-line-3',
|
||||||
'006*text-line-4',
|
'006*text-line-4',
|
||||||
'013*text-line-11',
|
'013*text-line-11',
|
||||||
|
@ -213,6 +213,32 @@ class TestDoctests(object):
|
||||||
assert 'text-line-2' not in result.stdout.str()
|
assert 'text-line-2' not in result.stdout.str()
|
||||||
assert 'text-line-after' not in result.stdout.str()
|
assert 'text-line-after' not in result.stdout.str()
|
||||||
|
|
||||||
|
def test_docstring_full_context_around_error(self, testdir):
|
||||||
|
"""Test that we show the whole context before the actual line of a failing
|
||||||
|
doctest, provided that the context is up to 10 lines long.
|
||||||
|
"""
|
||||||
|
testdir.makepyfile('''
|
||||||
|
def foo():
|
||||||
|
"""
|
||||||
|
text-line-1
|
||||||
|
text-line-2
|
||||||
|
|
||||||
|
>>> 1 + 1
|
||||||
|
3
|
||||||
|
"""
|
||||||
|
''')
|
||||||
|
result = testdir.runpytest('--doctest-modules')
|
||||||
|
result.stdout.fnmatch_lines([
|
||||||
|
'*docstring_full_context_around_error*',
|
||||||
|
'003*text-line-1',
|
||||||
|
'004*text-line-2',
|
||||||
|
'006*>>> 1 + 1',
|
||||||
|
'Expected:',
|
||||||
|
' 3',
|
||||||
|
'Got:',
|
||||||
|
' 2',
|
||||||
|
])
|
||||||
|
|
||||||
def test_doctest_linedata_missing(self, testdir):
|
def test_doctest_linedata_missing(self, testdir):
|
||||||
testdir.tmpdir.join('hello.py').write(_pytest._code.Source("""
|
testdir.tmpdir.join('hello.py').write(_pytest._code.Source("""
|
||||||
class Fun(object):
|
class Fun(object):
|
||||||
|
|
|
@ -169,6 +169,23 @@ def test_markers_option(testdir):
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
||||||
|
def test_ini_markers_whitespace(testdir):
|
||||||
|
testdir.makeini("""
|
||||||
|
[pytest]
|
||||||
|
markers =
|
||||||
|
a1 : this is a whitespace marker
|
||||||
|
""")
|
||||||
|
testdir.makepyfile("""
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
@pytest.mark.a1
|
||||||
|
def test_markers():
|
||||||
|
assert True
|
||||||
|
""")
|
||||||
|
rec = testdir.inline_run("--strict", "-m", "a1")
|
||||||
|
rec.assertoutcome(passed=1)
|
||||||
|
|
||||||
|
|
||||||
def test_markers_option_with_plugin_in_current_dir(testdir):
|
def test_markers_option_with_plugin_in_current_dir(testdir):
|
||||||
testdir.makeconftest('pytest_plugins = "flip_flop"')
|
testdir.makeconftest('pytest_plugins = "flip_flop"')
|
||||||
testdir.makepyfile(flip_flop="""\
|
testdir.makepyfile(flip_flop="""\
|
||||||
|
@ -342,6 +359,24 @@ def test_parametrized_collect_with_wrong_args(testdir):
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
||||||
|
def test_parametrized_with_kwargs(testdir):
|
||||||
|
"""Test collect parametrized func with wrong number of args."""
|
||||||
|
py_file = testdir.makepyfile("""
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
@pytest.fixture(params=[1,2])
|
||||||
|
def a(request):
|
||||||
|
return request.param
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(argnames='b', argvalues=[1, 2])
|
||||||
|
def test_func(a, b):
|
||||||
|
pass
|
||||||
|
""")
|
||||||
|
|
||||||
|
result = testdir.runpytest(py_file)
|
||||||
|
assert(result.ret == 0)
|
||||||
|
|
||||||
|
|
||||||
class TestFunctional(object):
|
class TestFunctional(object):
|
||||||
|
|
||||||
def test_mark_per_function(self, testdir):
|
def test_mark_per_function(self, testdir):
|
||||||
|
@ -433,11 +468,11 @@ class TestFunctional(object):
|
||||||
assert marker.kwargs == {'x': 1, 'y': 2, 'z': 4}
|
assert marker.kwargs == {'x': 1, 'y': 2, 'z': 4}
|
||||||
|
|
||||||
# test the new __iter__ interface
|
# test the new __iter__ interface
|
||||||
l = list(marker)
|
values = list(marker)
|
||||||
assert len(l) == 3
|
assert len(values) == 3
|
||||||
assert l[0].args == ("pos0",)
|
assert values[0].args == ("pos0",)
|
||||||
assert l[1].args == ()
|
assert values[1].args == ()
|
||||||
assert l[2].args == ("pos1", )
|
assert values[2].args == ("pos1", )
|
||||||
|
|
||||||
@pytest.mark.xfail(reason='unfixed')
|
@pytest.mark.xfail(reason='unfixed')
|
||||||
def test_merging_markers_deep(self, testdir):
|
def test_merging_markers_deep(self, testdir):
|
||||||
|
@ -529,9 +564,9 @@ class TestFunctional(object):
|
||||||
def test_func():
|
def test_func():
|
||||||
pass
|
pass
|
||||||
""")
|
""")
|
||||||
l = reprec.getfailedcollections()
|
values = reprec.getfailedcollections()
|
||||||
assert len(l) == 1
|
assert len(values) == 1
|
||||||
assert "TypeError" in str(l[0].longrepr)
|
assert "TypeError" in str(values[0].longrepr)
|
||||||
|
|
||||||
def test_mark_dynamically_in_funcarg(self, testdir):
|
def test_mark_dynamically_in_funcarg(self, testdir):
|
||||||
testdir.makeconftest("""
|
testdir.makeconftest("""
|
||||||
|
@ -540,8 +575,8 @@ class TestFunctional(object):
|
||||||
def arg(request):
|
def arg(request):
|
||||||
request.applymarker(pytest.mark.hello)
|
request.applymarker(pytest.mark.hello)
|
||||||
def pytest_terminal_summary(terminalreporter):
|
def pytest_terminal_summary(terminalreporter):
|
||||||
l = terminalreporter.stats['passed']
|
values = terminalreporter.stats['passed']
|
||||||
terminalreporter.writer.line("keyword: %s" % l[0].keywords)
|
terminalreporter.writer.line("keyword: %s" % values[0].keywords)
|
||||||
""")
|
""")
|
||||||
testdir.makepyfile("""
|
testdir.makepyfile("""
|
||||||
def test_func(arg):
|
def test_func(arg):
|
||||||
|
@ -564,10 +599,10 @@ class TestFunctional(object):
|
||||||
item, = items
|
item, = items
|
||||||
keywords = item.keywords
|
keywords = item.keywords
|
||||||
marker = keywords['hello']
|
marker = keywords['hello']
|
||||||
l = list(marker)
|
values = list(marker)
|
||||||
assert len(l) == 2
|
assert len(values) == 2
|
||||||
assert l[0].args == ("pos0",)
|
assert values[0].args == ("pos0",)
|
||||||
assert l[1].args == ("pos1",)
|
assert values[1].args == ("pos1",)
|
||||||
|
|
||||||
def test_no_marker_match_on_unmarked_names(self, testdir):
|
def test_no_marker_match_on_unmarked_names(self, testdir):
|
||||||
p = testdir.makepyfile("""
|
p = testdir.makepyfile("""
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from _pytest import nodes
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("baseid, nodeid, expected", (
|
||||||
|
('', '', True),
|
||||||
|
('', 'foo', True),
|
||||||
|
('', 'foo/bar', True),
|
||||||
|
('', 'foo/bar::TestBaz::()', True),
|
||||||
|
('foo', 'food', False),
|
||||||
|
('foo/bar::TestBaz::()', 'foo/bar', False),
|
||||||
|
('foo/bar::TestBaz::()', 'foo/bar::TestBop::()', False),
|
||||||
|
('foo/bar', 'foo/bar::TestBop::()', True),
|
||||||
|
))
|
||||||
|
def test_ischildnode(baseid, nodeid, expected):
|
||||||
|
result = nodes.ischildnode(baseid, nodeid)
|
||||||
|
assert result is expected
|
|
@ -8,18 +8,18 @@ def setup_module(mod):
|
||||||
|
|
||||||
def test_nose_setup(testdir):
|
def test_nose_setup(testdir):
|
||||||
p = testdir.makepyfile("""
|
p = testdir.makepyfile("""
|
||||||
l = []
|
values = []
|
||||||
from nose.tools import with_setup
|
from nose.tools import with_setup
|
||||||
|
|
||||||
@with_setup(lambda: l.append(1), lambda: l.append(2))
|
@with_setup(lambda: values.append(1), lambda: values.append(2))
|
||||||
def test_hello():
|
def test_hello():
|
||||||
assert l == [1]
|
assert values == [1]
|
||||||
|
|
||||||
def test_world():
|
def test_world():
|
||||||
assert l == [1,2]
|
assert values == [1,2]
|
||||||
|
|
||||||
test_hello.setup = lambda: l.append(1)
|
test_hello.setup = lambda: values.append(1)
|
||||||
test_hello.teardown = lambda: l.append(2)
|
test_hello.teardown = lambda: values.append(2)
|
||||||
""")
|
""")
|
||||||
result = testdir.runpytest(p, '-p', 'nose')
|
result = testdir.runpytest(p, '-p', 'nose')
|
||||||
result.assert_outcomes(passed=2)
|
result.assert_outcomes(passed=2)
|
||||||
|
@ -27,15 +27,15 @@ def test_nose_setup(testdir):
|
||||||
|
|
||||||
def test_setup_func_with_setup_decorator():
|
def test_setup_func_with_setup_decorator():
|
||||||
from _pytest.nose import call_optional
|
from _pytest.nose import call_optional
|
||||||
l = []
|
values = []
|
||||||
|
|
||||||
class A(object):
|
class A(object):
|
||||||
@pytest.fixture(autouse=True)
|
@pytest.fixture(autouse=True)
|
||||||
def f(self):
|
def f(self):
|
||||||
l.append(1)
|
values.append(1)
|
||||||
|
|
||||||
call_optional(A(), "f")
|
call_optional(A(), "f")
|
||||||
assert not l
|
assert not values
|
||||||
|
|
||||||
|
|
||||||
def test_setup_func_not_callable():
|
def test_setup_func_not_callable():
|
||||||
|
@ -51,24 +51,24 @@ def test_nose_setup_func(testdir):
|
||||||
p = testdir.makepyfile("""
|
p = testdir.makepyfile("""
|
||||||
from nose.tools import with_setup
|
from nose.tools import with_setup
|
||||||
|
|
||||||
l = []
|
values = []
|
||||||
|
|
||||||
def my_setup():
|
def my_setup():
|
||||||
a = 1
|
a = 1
|
||||||
l.append(a)
|
values.append(a)
|
||||||
|
|
||||||
def my_teardown():
|
def my_teardown():
|
||||||
b = 2
|
b = 2
|
||||||
l.append(b)
|
values.append(b)
|
||||||
|
|
||||||
@with_setup(my_setup, my_teardown)
|
@with_setup(my_setup, my_teardown)
|
||||||
def test_hello():
|
def test_hello():
|
||||||
print (l)
|
print (values)
|
||||||
assert l == [1]
|
assert values == [1]
|
||||||
|
|
||||||
def test_world():
|
def test_world():
|
||||||
print (l)
|
print (values)
|
||||||
assert l == [1,2]
|
assert values == [1,2]
|
||||||
|
|
||||||
""")
|
""")
|
||||||
result = testdir.runpytest(p, '-p', 'nose')
|
result = testdir.runpytest(p, '-p', 'nose')
|
||||||
|
@ -79,18 +79,18 @@ def test_nose_setup_func_failure(testdir):
|
||||||
p = testdir.makepyfile("""
|
p = testdir.makepyfile("""
|
||||||
from nose.tools import with_setup
|
from nose.tools import with_setup
|
||||||
|
|
||||||
l = []
|
values = []
|
||||||
my_setup = lambda x: 1
|
my_setup = lambda x: 1
|
||||||
my_teardown = lambda x: 2
|
my_teardown = lambda x: 2
|
||||||
|
|
||||||
@with_setup(my_setup, my_teardown)
|
@with_setup(my_setup, my_teardown)
|
||||||
def test_hello():
|
def test_hello():
|
||||||
print (l)
|
print (values)
|
||||||
assert l == [1]
|
assert values == [1]
|
||||||
|
|
||||||
def test_world():
|
def test_world():
|
||||||
print (l)
|
print (values)
|
||||||
assert l == [1,2]
|
assert values == [1,2]
|
||||||
|
|
||||||
""")
|
""")
|
||||||
result = testdir.runpytest(p, '-p', 'nose')
|
result = testdir.runpytest(p, '-p', 'nose')
|
||||||
|
@ -101,13 +101,13 @@ def test_nose_setup_func_failure(testdir):
|
||||||
|
|
||||||
def test_nose_setup_func_failure_2(testdir):
|
def test_nose_setup_func_failure_2(testdir):
|
||||||
testdir.makepyfile("""
|
testdir.makepyfile("""
|
||||||
l = []
|
values = []
|
||||||
|
|
||||||
my_setup = 1
|
my_setup = 1
|
||||||
my_teardown = 2
|
my_teardown = 2
|
||||||
|
|
||||||
def test_hello():
|
def test_hello():
|
||||||
assert l == []
|
assert values == []
|
||||||
|
|
||||||
test_hello.setup = my_setup
|
test_hello.setup = my_setup
|
||||||
test_hello.teardown = my_teardown
|
test_hello.teardown = my_teardown
|
||||||
|
@ -121,26 +121,26 @@ def test_nose_setup_partial(testdir):
|
||||||
p = testdir.makepyfile("""
|
p = testdir.makepyfile("""
|
||||||
from functools import partial
|
from functools import partial
|
||||||
|
|
||||||
l = []
|
values = []
|
||||||
|
|
||||||
def my_setup(x):
|
def my_setup(x):
|
||||||
a = x
|
a = x
|
||||||
l.append(a)
|
values.append(a)
|
||||||
|
|
||||||
def my_teardown(x):
|
def my_teardown(x):
|
||||||
b = x
|
b = x
|
||||||
l.append(b)
|
values.append(b)
|
||||||
|
|
||||||
my_setup_partial = partial(my_setup, 1)
|
my_setup_partial = partial(my_setup, 1)
|
||||||
my_teardown_partial = partial(my_teardown, 2)
|
my_teardown_partial = partial(my_teardown, 2)
|
||||||
|
|
||||||
def test_hello():
|
def test_hello():
|
||||||
print (l)
|
print (values)
|
||||||
assert l == [1]
|
assert values == [1]
|
||||||
|
|
||||||
def test_world():
|
def test_world():
|
||||||
print (l)
|
print (values)
|
||||||
assert l == [1,2]
|
assert values == [1,2]
|
||||||
|
|
||||||
test_hello.setup = my_setup_partial
|
test_hello.setup = my_setup_partial
|
||||||
test_hello.teardown = my_teardown_partial
|
test_hello.teardown = my_teardown_partial
|
||||||
|
@ -251,19 +251,19 @@ def test_module_level_setup(testdir):
|
||||||
|
|
||||||
def test_nose_style_setup_teardown(testdir):
|
def test_nose_style_setup_teardown(testdir):
|
||||||
testdir.makepyfile("""
|
testdir.makepyfile("""
|
||||||
l = []
|
values = []
|
||||||
|
|
||||||
def setup_module():
|
def setup_module():
|
||||||
l.append(1)
|
values.append(1)
|
||||||
|
|
||||||
def teardown_module():
|
def teardown_module():
|
||||||
del l[0]
|
del values[0]
|
||||||
|
|
||||||
def test_hello():
|
def test_hello():
|
||||||
assert l == [1]
|
assert values == [1]
|
||||||
|
|
||||||
def test_world():
|
def test_world():
|
||||||
assert l == [1]
|
assert values == [1]
|
||||||
""")
|
""")
|
||||||
result = testdir.runpytest('-p', 'nose')
|
result = testdir.runpytest('-p', 'nose')
|
||||||
result.stdout.fnmatch_lines([
|
result.stdout.fnmatch_lines([
|
||||||
|
|
|
@ -85,23 +85,23 @@ class TestPytestPluginInteractions(object):
|
||||||
|
|
||||||
def test_configure(self, testdir):
|
def test_configure(self, testdir):
|
||||||
config = testdir.parseconfig()
|
config = testdir.parseconfig()
|
||||||
l = []
|
values = []
|
||||||
|
|
||||||
class A(object):
|
class A(object):
|
||||||
def pytest_configure(self, config):
|
def pytest_configure(self, config):
|
||||||
l.append(self)
|
values.append(self)
|
||||||
|
|
||||||
config.pluginmanager.register(A())
|
config.pluginmanager.register(A())
|
||||||
assert len(l) == 0
|
assert len(values) == 0
|
||||||
config._do_configure()
|
config._do_configure()
|
||||||
assert len(l) == 1
|
assert len(values) == 1
|
||||||
config.pluginmanager.register(A()) # leads to a configured() plugin
|
config.pluginmanager.register(A()) # leads to a configured() plugin
|
||||||
assert len(l) == 2
|
assert len(values) == 2
|
||||||
assert l[0] != l[1]
|
assert values[0] != values[1]
|
||||||
|
|
||||||
config._ensure_unconfigure()
|
config._ensure_unconfigure()
|
||||||
config.pluginmanager.register(A())
|
config.pluginmanager.register(A())
|
||||||
assert len(l) == 2
|
assert len(values) == 2
|
||||||
|
|
||||||
def test_hook_tracing(self):
|
def test_hook_tracing(self):
|
||||||
pytestpm = get_config().pluginmanager # fully initialized with plugins
|
pytestpm = get_config().pluginmanager # fully initialized with plugins
|
||||||
|
@ -116,19 +116,19 @@ class TestPytestPluginInteractions(object):
|
||||||
saveindent.append(pytestpm.trace.root.indent)
|
saveindent.append(pytestpm.trace.root.indent)
|
||||||
raise ValueError()
|
raise ValueError()
|
||||||
|
|
||||||
l = []
|
values = []
|
||||||
pytestpm.trace.root.setwriter(l.append)
|
pytestpm.trace.root.setwriter(values.append)
|
||||||
undo = pytestpm.enable_tracing()
|
undo = pytestpm.enable_tracing()
|
||||||
try:
|
try:
|
||||||
indent = pytestpm.trace.root.indent
|
indent = pytestpm.trace.root.indent
|
||||||
p = api1()
|
p = api1()
|
||||||
pytestpm.register(p)
|
pytestpm.register(p)
|
||||||
assert pytestpm.trace.root.indent == indent
|
assert pytestpm.trace.root.indent == indent
|
||||||
assert len(l) >= 2
|
assert len(values) >= 2
|
||||||
assert 'pytest_plugin_registered' in l[0]
|
assert 'pytest_plugin_registered' in values[0]
|
||||||
assert 'finish' in l[1]
|
assert 'finish' in values[1]
|
||||||
|
|
||||||
l[:] = []
|
values[:] = []
|
||||||
with pytest.raises(ValueError):
|
with pytest.raises(ValueError):
|
||||||
pytestpm.register(api2())
|
pytestpm.register(api2())
|
||||||
assert pytestpm.trace.root.indent == indent
|
assert pytestpm.trace.root.indent == indent
|
||||||
|
@ -230,12 +230,12 @@ class TestPytestPluginManager(object):
|
||||||
mod = py.std.types.ModuleType("x.y.pytest_hello")
|
mod = py.std.types.ModuleType("x.y.pytest_hello")
|
||||||
pm.register(mod)
|
pm.register(mod)
|
||||||
assert pm.is_registered(mod)
|
assert pm.is_registered(mod)
|
||||||
l = pm.get_plugins()
|
values = pm.get_plugins()
|
||||||
assert mod in l
|
assert mod in values
|
||||||
pytest.raises(ValueError, "pm.register(mod)")
|
pytest.raises(ValueError, "pm.register(mod)")
|
||||||
pytest.raises(ValueError, lambda: pm.register(mod))
|
pytest.raises(ValueError, lambda: pm.register(mod))
|
||||||
# assert not pm.is_registered(mod2)
|
# assert not pm.is_registered(mod2)
|
||||||
assert pm.get_plugins() == l
|
assert pm.get_plugins() == values
|
||||||
|
|
||||||
def test_canonical_import(self, monkeypatch):
|
def test_canonical_import(self, monkeypatch):
|
||||||
mod = py.std.types.ModuleType("pytest_xyz")
|
mod = py.std.types.ModuleType("pytest_xyz")
|
||||||
|
@ -269,8 +269,8 @@ class TestPytestPluginManager(object):
|
||||||
|
|
||||||
# check that it is not registered twice
|
# check that it is not registered twice
|
||||||
pytestpm.consider_module(mod)
|
pytestpm.consider_module(mod)
|
||||||
l = reprec.getcalls("pytest_plugin_registered")
|
values = reprec.getcalls("pytest_plugin_registered")
|
||||||
assert len(l) == 1
|
assert len(values) == 1
|
||||||
|
|
||||||
def test_consider_env_fails_to_import(self, monkeypatch, pytestpm):
|
def test_consider_env_fails_to_import(self, monkeypatch, pytestpm):
|
||||||
monkeypatch.setenv('PYTEST_PLUGINS', 'nonexisting', prepend=",")
|
monkeypatch.setenv('PYTEST_PLUGINS', 'nonexisting', prepend=",")
|
||||||
|
|
|
@ -30,10 +30,10 @@ class TestWarningsRecorderChecker(object):
|
||||||
assert len(rec.list) == 2
|
assert len(rec.list) == 2
|
||||||
warn = rec.pop()
|
warn = rec.pop()
|
||||||
assert str(warn.message) == "hello"
|
assert str(warn.message) == "hello"
|
||||||
l = rec.list
|
values = rec.list
|
||||||
rec.clear()
|
rec.clear()
|
||||||
assert len(rec.list) == 0
|
assert len(rec.list) == 0
|
||||||
assert l is rec.list
|
assert values is rec.list
|
||||||
pytest.raises(AssertionError, "rec.pop()")
|
pytest.raises(AssertionError, "rec.pop()")
|
||||||
|
|
||||||
def test_typechecking(self):
|
def test_typechecking(self):
|
||||||
|
|
|
@ -13,12 +13,12 @@ class TestSetupState(object):
|
||||||
def test_setup(self, testdir):
|
def test_setup(self, testdir):
|
||||||
ss = runner.SetupState()
|
ss = runner.SetupState()
|
||||||
item = testdir.getitem("def test_func(): pass")
|
item = testdir.getitem("def test_func(): pass")
|
||||||
l = [1]
|
values = [1]
|
||||||
ss.prepare(item)
|
ss.prepare(item)
|
||||||
ss.addfinalizer(l.pop, colitem=item)
|
ss.addfinalizer(values.pop, colitem=item)
|
||||||
assert l
|
assert values
|
||||||
ss._pop_and_teardown()
|
ss._pop_and_teardown()
|
||||||
assert not l
|
assert not values
|
||||||
|
|
||||||
def test_teardown_exact_stack_empty(self, testdir):
|
def test_teardown_exact_stack_empty(self, testdir):
|
||||||
item = testdir.getitem("def test_func(): pass")
|
item = testdir.getitem("def test_func(): pass")
|
||||||
|
|
|
@ -39,20 +39,20 @@ def test_module_and_function_setup(testdir):
|
||||||
|
|
||||||
def test_module_setup_failure_no_teardown(testdir):
|
def test_module_setup_failure_no_teardown(testdir):
|
||||||
reprec = testdir.inline_runsource("""
|
reprec = testdir.inline_runsource("""
|
||||||
l = []
|
values = []
|
||||||
def setup_module(module):
|
def setup_module(module):
|
||||||
l.append(1)
|
values.append(1)
|
||||||
0/0
|
0/0
|
||||||
|
|
||||||
def test_nothing():
|
def test_nothing():
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def teardown_module(module):
|
def teardown_module(module):
|
||||||
l.append(2)
|
values.append(2)
|
||||||
""")
|
""")
|
||||||
reprec.assertoutcome(failed=1)
|
reprec.assertoutcome(failed=1)
|
||||||
calls = reprec.getcalls("pytest_runtest_setup")
|
calls = reprec.getcalls("pytest_runtest_setup")
|
||||||
assert calls[0].item.module.l == [1]
|
assert calls[0].item.module.values == [1]
|
||||||
|
|
||||||
|
|
||||||
def test_setup_function_failure_no_teardown(testdir):
|
def test_setup_function_failure_no_teardown(testdir):
|
||||||
|
|
|
@ -45,9 +45,9 @@ class SessionTests(object):
|
||||||
a = 1
|
a = 1
|
||||||
""")
|
""")
|
||||||
reprec = testdir.inline_run(tfile)
|
reprec = testdir.inline_run(tfile)
|
||||||
l = reprec.getfailedcollections()
|
values = reprec.getfailedcollections()
|
||||||
assert len(l) == 1
|
assert len(values) == 1
|
||||||
out = str(l[0].longrepr)
|
out = str(values[0].longrepr)
|
||||||
assert out.find('does_not_work') != -1
|
assert out.find('does_not_work') != -1
|
||||||
|
|
||||||
def test_raises_output(self, testdir):
|
def test_raises_output(self, testdir):
|
||||||
|
@ -75,9 +75,9 @@ class SessionTests(object):
|
||||||
|
|
||||||
def test_syntax_error_module(self, testdir):
|
def test_syntax_error_module(self, testdir):
|
||||||
reprec = testdir.inline_runsource("this is really not python")
|
reprec = testdir.inline_runsource("this is really not python")
|
||||||
l = reprec.getfailedcollections()
|
values = reprec.getfailedcollections()
|
||||||
assert len(l) == 1
|
assert len(values) == 1
|
||||||
out = str(l[0].longrepr)
|
out = str(values[0].longrepr)
|
||||||
assert out.find(str('not python')) != -1
|
assert out.find(str('not python')) != -1
|
||||||
|
|
||||||
def test_exit_first_problem(self, testdir):
|
def test_exit_first_problem(self, testdir):
|
||||||
|
@ -144,15 +144,15 @@ class TestNewSession(SessionTests):
|
||||||
|
|
||||||
def test_order_of_execution(self, testdir):
|
def test_order_of_execution(self, testdir):
|
||||||
reprec = testdir.inline_runsource("""
|
reprec = testdir.inline_runsource("""
|
||||||
l = []
|
values = []
|
||||||
def test_1():
|
def test_1():
|
||||||
l.append(1)
|
values.append(1)
|
||||||
def test_2():
|
def test_2():
|
||||||
l.append(2)
|
values.append(2)
|
||||||
def test_3():
|
def test_3():
|
||||||
assert l == [1,2]
|
assert values == [1,2]
|
||||||
class Testmygroup(object):
|
class Testmygroup(object):
|
||||||
reslist = l
|
reslist = values
|
||||||
def test_1(self):
|
def test_1(self):
|
||||||
self.reslist.append(1)
|
self.reslist.append(1)
|
||||||
def test_2(self):
|
def test_2(self):
|
||||||
|
@ -242,13 +242,13 @@ def test_exclude(testdir):
|
||||||
def test_sessionfinish_with_start(testdir):
|
def test_sessionfinish_with_start(testdir):
|
||||||
testdir.makeconftest("""
|
testdir.makeconftest("""
|
||||||
import os
|
import os
|
||||||
l = []
|
values = []
|
||||||
def pytest_sessionstart():
|
def pytest_sessionstart():
|
||||||
l.append(os.getcwd())
|
values.append(os.getcwd())
|
||||||
os.chdir("..")
|
os.chdir("..")
|
||||||
|
|
||||||
def pytest_sessionfinish():
|
def pytest_sessionfinish():
|
||||||
assert l[0] == os.getcwd()
|
assert values[0] == os.getcwd()
|
||||||
|
|
||||||
""")
|
""")
|
||||||
res = testdir.runpytest("--collect-only")
|
res = testdir.runpytest("--collect-only")
|
||||||
|
|
|
@ -679,9 +679,9 @@ def test_skip_reasons_folding():
|
||||||
ev2.longrepr = longrepr
|
ev2.longrepr = longrepr
|
||||||
ev2.skipped = True
|
ev2.skipped = True
|
||||||
|
|
||||||
l = folded_skips([ev1, ev2])
|
values = folded_skips([ev1, ev2])
|
||||||
assert len(l) == 1
|
assert len(values) == 1
|
||||||
num, fspath, lineno, reason = l[0]
|
num, fspath, lineno, reason = values[0]
|
||||||
assert num == 2
|
assert num == 2
|
||||||
assert fspath == path
|
assert fspath == path
|
||||||
assert lineno == lineno
|
assert lineno == lineno
|
||||||
|
|
|
@ -24,12 +24,12 @@ class Option(object):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def args(self):
|
def args(self):
|
||||||
l = []
|
values = []
|
||||||
if self.verbose:
|
if self.verbose:
|
||||||
l.append('-v')
|
values.append('-v')
|
||||||
if self.fulltrace:
|
if self.fulltrace:
|
||||||
l.append('--fulltrace')
|
values.append('--fulltrace')
|
||||||
return l
|
return values
|
||||||
|
|
||||||
|
|
||||||
def pytest_generate_tests(metafunc):
|
def pytest_generate_tests(metafunc):
|
||||||
|
|
|
@ -73,19 +73,19 @@ def test_setup(testdir):
|
||||||
|
|
||||||
def test_setUpModule(testdir):
|
def test_setUpModule(testdir):
|
||||||
testpath = testdir.makepyfile("""
|
testpath = testdir.makepyfile("""
|
||||||
l = []
|
values = []
|
||||||
|
|
||||||
def setUpModule():
|
def setUpModule():
|
||||||
l.append(1)
|
values.append(1)
|
||||||
|
|
||||||
def tearDownModule():
|
def tearDownModule():
|
||||||
del l[0]
|
del values[0]
|
||||||
|
|
||||||
def test_hello():
|
def test_hello():
|
||||||
assert l == [1]
|
assert values == [1]
|
||||||
|
|
||||||
def test_world():
|
def test_world():
|
||||||
assert l == [1]
|
assert values == [1]
|
||||||
""")
|
""")
|
||||||
result = testdir.runpytest(testpath)
|
result = testdir.runpytest(testpath)
|
||||||
result.stdout.fnmatch_lines([
|
result.stdout.fnmatch_lines([
|
||||||
|
@ -95,13 +95,13 @@ def test_setUpModule(testdir):
|
||||||
|
|
||||||
def test_setUpModule_failing_no_teardown(testdir):
|
def test_setUpModule_failing_no_teardown(testdir):
|
||||||
testpath = testdir.makepyfile("""
|
testpath = testdir.makepyfile("""
|
||||||
l = []
|
values = []
|
||||||
|
|
||||||
def setUpModule():
|
def setUpModule():
|
||||||
0/0
|
0/0
|
||||||
|
|
||||||
def tearDownModule():
|
def tearDownModule():
|
||||||
l.append(1)
|
values.append(1)
|
||||||
|
|
||||||
def test_hello():
|
def test_hello():
|
||||||
pass
|
pass
|
||||||
|
@ -109,7 +109,7 @@ def test_setUpModule_failing_no_teardown(testdir):
|
||||||
reprec = testdir.inline_run(testpath)
|
reprec = testdir.inline_run(testpath)
|
||||||
reprec.assertoutcome(passed=0, failed=1)
|
reprec.assertoutcome(passed=0, failed=1)
|
||||||
call = reprec.getcalls("pytest_runtest_setup")[0]
|
call = reprec.getcalls("pytest_runtest_setup")[0]
|
||||||
assert not call.item.module.l
|
assert not call.item.module.values
|
||||||
|
|
||||||
|
|
||||||
def test_new_instances(testdir):
|
def test_new_instances(testdir):
|
||||||
|
@ -129,14 +129,14 @@ def test_teardown(testdir):
|
||||||
testpath = testdir.makepyfile("""
|
testpath = testdir.makepyfile("""
|
||||||
import unittest
|
import unittest
|
||||||
class MyTestCase(unittest.TestCase):
|
class MyTestCase(unittest.TestCase):
|
||||||
l = []
|
values = []
|
||||||
def test_one(self):
|
def test_one(self):
|
||||||
pass
|
pass
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
self.l.append(None)
|
self.values.append(None)
|
||||||
class Second(unittest.TestCase):
|
class Second(unittest.TestCase):
|
||||||
def test_check(self):
|
def test_check(self):
|
||||||
self.assertEqual(MyTestCase.l, [None])
|
self.assertEqual(MyTestCase.values, [None])
|
||||||
""")
|
""")
|
||||||
reprec = testdir.inline_run(testpath)
|
reprec = testdir.inline_run(testpath)
|
||||||
passed, skipped, failed = reprec.countoutcomes()
|
passed, skipped, failed = reprec.countoutcomes()
|
||||||
|
|
|
@ -144,6 +144,8 @@ def test_unicode(testdir, pyfile_with_warnings):
|
||||||
@pytest.mark.skipif(sys.version_info >= (3, 0),
|
@pytest.mark.skipif(sys.version_info >= (3, 0),
|
||||||
reason='warnings message is broken as it is not str instance')
|
reason='warnings message is broken as it is not str instance')
|
||||||
def test_py2_unicode(testdir, pyfile_with_warnings):
|
def test_py2_unicode(testdir, pyfile_with_warnings):
|
||||||
|
if getattr(sys, "pypy_version_info", ())[:2] == (5, 9) and sys.platform.startswith('win'):
|
||||||
|
pytest.xfail("fails with unicode error on PyPy2 5.9 and Windows (#2905)")
|
||||||
testdir.makepyfile('''
|
testdir.makepyfile('''
|
||||||
# -*- coding: utf8 -*-
|
# -*- coding: utf8 -*-
|
||||||
import warnings
|
import warnings
|
||||||
|
|
18
tox.ini
18
tox.ini
|
@ -12,7 +12,7 @@ envlist =
|
||||||
py36
|
py36
|
||||||
py37
|
py37
|
||||||
pypy
|
pypy
|
||||||
{py27,py35}-{pexpect,xdist,trial,numpy}
|
{py27,py36}-{pexpect,xdist,trial,numpy}
|
||||||
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
|
||||||
|
@ -65,10 +64,11 @@ deps =
|
||||||
mock
|
mock
|
||||||
nose
|
nose
|
||||||
hypothesis>=3.5.2
|
hypothesis>=3.5.2
|
||||||
|
changedir=testing
|
||||||
commands =
|
commands =
|
||||||
pytest -n1 -rfsxX {posargs:testing}
|
pytest -n1 -rfsxX {posargs:.}
|
||||||
|
|
||||||
[testenv:py35-xdist]
|
[testenv:py36-xdist]
|
||||||
deps = {[testenv:py27-xdist]deps}
|
deps = {[testenv:py27-xdist]deps}
|
||||||
commands =
|
commands =
|
||||||
pytest -n3 -rfsxX {posargs:testing}
|
pytest -n3 -rfsxX {posargs:testing}
|
||||||
|
@ -80,7 +80,7 @@ deps = pexpect
|
||||||
commands =
|
commands =
|
||||||
pytest -rfsxX test_pdb.py test_terminal.py test_unittest.py
|
pytest -rfsxX 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}
|
||||||
|
@ -92,17 +92,18 @@ deps =
|
||||||
pytest-xdist>=1.13
|
pytest-xdist>=1.13
|
||||||
hypothesis>=3.5.2
|
hypothesis>=3.5.2
|
||||||
distribute = true
|
distribute = true
|
||||||
|
changedir=testing
|
||||||
setenv =
|
setenv =
|
||||||
PYTHONDONTWRITEBYTECODE=1
|
PYTHONDONTWRITEBYTECODE=1
|
||||||
commands =
|
commands =
|
||||||
pytest -n3 -rfsxX {posargs:testing}
|
pytest -n3 -rfsxX {posargs:.}
|
||||||
|
|
||||||
[testenv:py27-trial]
|
[testenv:py27-trial]
|
||||||
deps = twisted
|
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 +113,7 @@ deps=numpy
|
||||||
commands=
|
commands=
|
||||||
pytest -rfsxX {posargs:testing/python/approx.py}
|
pytest -rfsxX {posargs:testing/python/approx.py}
|
||||||
|
|
||||||
[testenv:py35-numpy]
|
[testenv:py36-numpy]
|
||||||
deps=numpy
|
deps=numpy
|
||||||
commands=
|
commands=
|
||||||
pytest -rfsxX {posargs:testing/python/approx.py}
|
pytest -rfsxX {posargs:testing/python/approx.py}
|
||||||
|
@ -180,7 +181,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}
|
||||||
|
|
Loading…
Reference in New Issue