Merge remote-tracking branch 'upstream/master' into features
This commit is contained in:
commit
aff463a3c4
1
AUTHORS
1
AUTHORS
|
@ -41,6 +41,7 @@ Christian Boelsen
|
||||||
Christian Theunert
|
Christian Theunert
|
||||||
Christian Tismer
|
Christian Tismer
|
||||||
Christopher Gilling
|
Christopher Gilling
|
||||||
|
Cyrus Maden
|
||||||
Daniel Grana
|
Daniel Grana
|
||||||
Daniel Hahler
|
Daniel Hahler
|
||||||
Daniel Nuri
|
Daniel Nuri
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
from __future__ import absolute_import, division, print_function
|
from __future__ import absolute_import, division, print_function
|
||||||
|
import inspect
|
||||||
import sys
|
import sys
|
||||||
|
import traceback
|
||||||
from inspect import CO_VARARGS, CO_VARKEYWORDS
|
from inspect import CO_VARARGS, CO_VARKEYWORDS
|
||||||
import re
|
import re
|
||||||
from weakref import ref
|
from weakref import ref
|
||||||
|
@ -422,7 +424,7 @@ class ExceptionInfo(object):
|
||||||
"""
|
"""
|
||||||
if style == 'native':
|
if style == 'native':
|
||||||
return ReprExceptionInfo(ReprTracebackNative(
|
return ReprExceptionInfo(ReprTracebackNative(
|
||||||
py.std.traceback.format_exception(
|
traceback.format_exception(
|
||||||
self.type,
|
self.type,
|
||||||
self.value,
|
self.value,
|
||||||
self.traceback[0]._rawentry,
|
self.traceback[0]._rawentry,
|
||||||
|
@ -556,7 +558,7 @@ class FormattedExcinfo(object):
|
||||||
# else:
|
# else:
|
||||||
# self._line("%-10s =\\" % (name,))
|
# self._line("%-10s =\\" % (name,))
|
||||||
# # XXX
|
# # XXX
|
||||||
# py.std.pprint.pprint(value, stream=self.excinfowriter)
|
# pprint.pprint(value, stream=self.excinfowriter)
|
||||||
return ReprLocals(lines)
|
return ReprLocals(lines)
|
||||||
|
|
||||||
def repr_traceback_entry(self, entry, excinfo=None):
|
def repr_traceback_entry(self, entry, excinfo=None):
|
||||||
|
@ -669,7 +671,7 @@ class FormattedExcinfo(object):
|
||||||
else:
|
else:
|
||||||
# fallback to native repr if the exception doesn't have a traceback:
|
# fallback to native repr if the exception doesn't have a traceback:
|
||||||
# ExceptionInfo objects require a full traceback to work
|
# ExceptionInfo objects require a full traceback to work
|
||||||
reprtraceback = ReprTracebackNative(py.std.traceback.format_exception(type(e), e, None))
|
reprtraceback = ReprTracebackNative(traceback.format_exception(type(e), e, None))
|
||||||
reprcrash = None
|
reprcrash = None
|
||||||
|
|
||||||
repr_chain += [(reprtraceback, reprcrash, descr)]
|
repr_chain += [(reprtraceback, reprcrash, descr)]
|
||||||
|
@ -886,7 +888,7 @@ def getrawcode(obj, trycall=True):
|
||||||
obj = getattr(obj, 'f_code', obj)
|
obj = getattr(obj, 'f_code', obj)
|
||||||
obj = getattr(obj, '__code__', obj)
|
obj = getattr(obj, '__code__', obj)
|
||||||
if trycall and not hasattr(obj, 'co_firstlineno'):
|
if trycall and not hasattr(obj, 'co_firstlineno'):
|
||||||
if hasattr(obj, '__call__') and not py.std.inspect.isclass(obj):
|
if hasattr(obj, '__call__') and not inspect.isclass(obj):
|
||||||
x = getrawcode(obj.__call__, trycall=False)
|
x = getrawcode(obj.__call__, trycall=False)
|
||||||
if hasattr(x, 'co_firstlineno'):
|
if hasattr(x, 'co_firstlineno'):
|
||||||
return x
|
return x
|
||||||
|
|
|
@ -3,6 +3,7 @@ from __future__ import absolute_import, division, generators, print_function
|
||||||
import ast
|
import ast
|
||||||
from ast import PyCF_ONLY_AST as _AST_FLAG
|
from ast import PyCF_ONLY_AST as _AST_FLAG
|
||||||
from bisect import bisect_right
|
from bisect import bisect_right
|
||||||
|
import linecache
|
||||||
import sys
|
import sys
|
||||||
import six
|
import six
|
||||||
import inspect
|
import inspect
|
||||||
|
@ -191,7 +192,7 @@ class Source(object):
|
||||||
if flag & _AST_FLAG:
|
if flag & _AST_FLAG:
|
||||||
return co
|
return co
|
||||||
lines = [(x + "\n") for x in self.lines]
|
lines = [(x + "\n") for x in self.lines]
|
||||||
py.std.linecache.cache[filename] = (1, None, lines, filename)
|
linecache.cache[filename] = (1, None, lines, filename)
|
||||||
return co
|
return co
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -223,8 +224,7 @@ def getfslineno(obj):
|
||||||
code = _pytest._code.Code(obj)
|
code = _pytest._code.Code(obj)
|
||||||
except TypeError:
|
except TypeError:
|
||||||
try:
|
try:
|
||||||
fn = (py.std.inspect.getsourcefile(obj) or
|
fn = inspect.getsourcefile(obj) or inspect.getfile(obj)
|
||||||
py.std.inspect.getfile(obj))
|
|
||||||
except TypeError:
|
except TypeError:
|
||||||
return "", -1
|
return "", -1
|
||||||
|
|
||||||
|
@ -248,7 +248,7 @@ def getfslineno(obj):
|
||||||
|
|
||||||
def findsource(obj):
|
def findsource(obj):
|
||||||
try:
|
try:
|
||||||
sourcelines, lineno = py.std.inspect.findsource(obj)
|
sourcelines, lineno = inspect.findsource(obj)
|
||||||
except py.builtin._sysex:
|
except py.builtin._sysex:
|
||||||
raise
|
raise
|
||||||
except: # noqa
|
except: # noqa
|
||||||
|
|
|
@ -16,6 +16,9 @@ def pytest_addhooks(pluginmanager):
|
||||||
|
|
||||||
|
|
||||||
:param _pytest.config.PytestPluginManager pluginmanager: pytest plugin manager
|
:param _pytest.config.PytestPluginManager pluginmanager: pytest plugin manager
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
This hook is incompatible with ``hookwrapper=True``.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
@ -27,6 +30,9 @@ def pytest_namespace():
|
||||||
the pytest namespace.
|
the pytest namespace.
|
||||||
|
|
||||||
This hook is called at plugin registration time.
|
This hook is called at plugin registration time.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
This hook is incompatible with ``hookwrapper=True``.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
@ -36,6 +42,9 @@ def pytest_plugin_registered(plugin, manager):
|
||||||
|
|
||||||
:param plugin: the plugin module or instance
|
:param plugin: the plugin module or instance
|
||||||
:param _pytest.config.PytestPluginManager manager: pytest plugin manager
|
:param _pytest.config.PytestPluginManager manager: pytest plugin manager
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
This hook is incompatible with ``hookwrapper=True``.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
@ -66,6 +75,9 @@ def pytest_addoption(parser):
|
||||||
|
|
||||||
The config object is passed around on many internal objects via the ``.config``
|
The config object is passed around on many internal objects via the ``.config``
|
||||||
attribute or can be retrieved as the ``pytestconfig`` fixture.
|
attribute or can be retrieved as the ``pytestconfig`` fixture.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
This hook is incompatible with ``hookwrapper=True``.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
@ -80,13 +92,15 @@ def pytest_configure(config):
|
||||||
After that, the hook is called for other conftest files as they are
|
After that, the hook is called for other conftest files as they are
|
||||||
imported.
|
imported.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
This hook is incompatible with ``hookwrapper=True``.
|
||||||
|
|
||||||
:arg _pytest.config.Config config: pytest config object
|
:arg _pytest.config.Config config: pytest config object
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# -------------------------------------------------------------------------
|
# -------------------------------------------------------------------------
|
||||||
# Bootstrapping hooks called for plugins registered early enough:
|
# Bootstrapping hooks called for plugins registered early enough:
|
||||||
# internal and 3rd party plugins as well as directly
|
# internal and 3rd party plugins.
|
||||||
# discoverable conftest.py local plugins.
|
|
||||||
# -------------------------------------------------------------------------
|
# -------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
@ -96,6 +110,9 @@ def pytest_cmdline_parse(pluginmanager, args):
|
||||||
|
|
||||||
Stops at first non-None result, see :ref:`firstresult`
|
Stops at first non-None result, see :ref:`firstresult`
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
This hook will not be called for ``conftest.py`` files, only for setuptools plugins.
|
||||||
|
|
||||||
:param _pytest.config.PytestPluginManager pluginmanager: pytest plugin manager
|
:param _pytest.config.PytestPluginManager pluginmanager: pytest plugin manager
|
||||||
:param list[str] args: list of arguments passed on the command line
|
:param list[str] args: list of arguments passed on the command line
|
||||||
"""
|
"""
|
||||||
|
@ -107,6 +124,9 @@ def pytest_cmdline_preparse(config, args):
|
||||||
This hook is considered deprecated and will be removed in a future pytest version. Consider
|
This hook is considered deprecated and will be removed in a future pytest version. Consider
|
||||||
using :func:`pytest_load_initial_conftests` instead.
|
using :func:`pytest_load_initial_conftests` instead.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
This hook will not be called for ``conftest.py`` files, only for setuptools plugins.
|
||||||
|
|
||||||
:param _pytest.config.Config config: pytest config object
|
:param _pytest.config.Config config: pytest config object
|
||||||
:param list[str] args: list of arguments passed on the command line
|
:param list[str] args: list of arguments passed on the command line
|
||||||
"""
|
"""
|
||||||
|
@ -117,6 +137,9 @@ def pytest_cmdline_main(config):
|
||||||
""" called for performing the main command line action. The default
|
""" called for performing the main command line action. The default
|
||||||
implementation will invoke the configure hooks and runtest_mainloop.
|
implementation will invoke the configure hooks and runtest_mainloop.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
This hook will not be called for ``conftest.py`` files, only for setuptools plugins.
|
||||||
|
|
||||||
Stops at first non-None result, see :ref:`firstresult`
|
Stops at first non-None result, see :ref:`firstresult`
|
||||||
|
|
||||||
:param _pytest.config.Config config: pytest config object
|
:param _pytest.config.Config config: pytest config object
|
||||||
|
@ -127,6 +150,9 @@ def pytest_load_initial_conftests(early_config, parser, args):
|
||||||
""" implements the loading of initial conftest files ahead
|
""" implements the loading of initial conftest files ahead
|
||||||
of command line option parsing.
|
of command line option parsing.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
This hook will not be called for ``conftest.py`` files, only for setuptools plugins.
|
||||||
|
|
||||||
:param _pytest.config.Config early_config: pytest config object
|
:param _pytest.config.Config early_config: pytest config object
|
||||||
:param list[str] args: list of arguments passed on the command line
|
:param list[str] args: list of arguments passed on the command line
|
||||||
:param _pytest.config.Parser parser: to add command line options
|
:param _pytest.config.Parser parser: to add command line options
|
||||||
|
@ -365,7 +391,15 @@ def pytest_runtest_logreport(report):
|
||||||
def pytest_fixture_setup(fixturedef, request):
|
def pytest_fixture_setup(fixturedef, request):
|
||||||
""" performs fixture setup execution.
|
""" performs fixture setup execution.
|
||||||
|
|
||||||
Stops at first non-None result, see :ref:`firstresult` """
|
:return: The return value of the call to the fixture function
|
||||||
|
|
||||||
|
Stops at first non-None result, see :ref:`firstresult`
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
If the fixture function returns None, other implementations of
|
||||||
|
this hook function will continue to be called, according to the
|
||||||
|
behavior of the :ref:`firstresult` option.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
def pytest_fixture_post_finalizer(fixturedef, request):
|
def pytest_fixture_post_finalizer(fixturedef, request):
|
||||||
|
@ -463,7 +497,11 @@ def pytest_terminal_summary(terminalreporter, exitstatus):
|
||||||
def pytest_logwarning(message, code, nodeid, fslocation):
|
def pytest_logwarning(message, code, nodeid, fslocation):
|
||||||
""" process a warning specified by a message, a code string,
|
""" process a warning specified by a message, a code string,
|
||||||
a nodeid and fslocation (both of which may be None
|
a nodeid and fslocation (both of which may be None
|
||||||
if the warning is not tied to a particular node/location)."""
|
if the warning is not tied to a particular node/location).
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
This hook is incompatible with ``hookwrapper=True``.
|
||||||
|
"""
|
||||||
|
|
||||||
# -------------------------------------------------------------------------
|
# -------------------------------------------------------------------------
|
||||||
# doctest hooks
|
# doctest hooks
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Fixed hanging pexpect test on MacOS by using flush() instead of wait().
|
|
@ -0,0 +1 @@
|
||||||
|
Document hooks (defined with ``historic=True``) which cannot be used with ``hookwrapper=True``.
|
|
@ -0,0 +1 @@
|
||||||
|
Clarify that warning capturing doesn't change the warning filter by default.
|
|
@ -0,0 +1 @@
|
||||||
|
Clarify a possible confusion when using pytest_fixture_setup with fixture functions that return None.
|
|
@ -0,0 +1 @@
|
||||||
|
Replace py.std with stdlib imports.
|
|
@ -0,0 +1 @@
|
||||||
|
Corrected 'you' to 'your' in logging docs.
|
|
@ -0,0 +1 @@
|
||||||
|
Improve readability (wording, grammar) of Getting Started guide
|
|
@ -0,0 +1 @@
|
||||||
|
Added note that calling pytest.main multiple times from the same process is not recommended because of import caching.
|
|
@ -15,91 +15,6 @@ We will only remove deprecated functionality in major releases (e.g. if we depre
|
||||||
Deprecation Roadmap
|
Deprecation Roadmap
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
This page lists deprecated features and when we plan to remove them. It is important to list the feature, the version where it got deprecated and the version we plan to remove it.
|
We track deprecation and removal of features using milestones and the `deprecation <https://github.com/pytest-dev/pytest/issues?q=label%3A%22type%3A+deprecation%22>`_ and `removal <https://github.com/pytest-dev/pytest/labels/type%3A%20removal>`_ labels on GitHub.
|
||||||
|
|
||||||
Following our deprecation policy, we should aim to keep features for *at least* two minor versions after it was considered deprecated.
|
Following our deprecation policy, after starting issuing deprecation warnings we keep features for *at least* two minor versions before considering removal.
|
||||||
|
|
||||||
|
|
||||||
Future Releases
|
|
||||||
~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
3.4
|
|
||||||
^^^
|
|
||||||
|
|
||||||
**Old style classes**
|
|
||||||
|
|
||||||
Issue: `#2147 <https://github.com/pytest-dev/pytest/issues/2147>`_.
|
|
||||||
|
|
||||||
Deprecated in ``3.2``.
|
|
||||||
|
|
||||||
4.0
|
|
||||||
^^^
|
|
||||||
|
|
||||||
**Yield tests**
|
|
||||||
|
|
||||||
Deprecated in ``3.0``.
|
|
||||||
|
|
||||||
**pytest-namespace hook**
|
|
||||||
|
|
||||||
deprecated in ``3.2``.
|
|
||||||
|
|
||||||
**Marks in parameter sets**
|
|
||||||
|
|
||||||
Deprecated in ``3.2``.
|
|
||||||
|
|
||||||
**--result-log**
|
|
||||||
|
|
||||||
Deprecated in ``3.0``.
|
|
||||||
|
|
||||||
See `#830 <https://github.com/pytest-dev/pytest/issues/830>`_ for more information. Suggested alternative: `pytest-tap <https://pypi.python.org/pypi/pytest-tap>`_.
|
|
||||||
|
|
||||||
**metafunc.addcall**
|
|
||||||
|
|
||||||
Issue: `#2876 <https://github.com/pytest-dev/pytest/issues/2876>`_.
|
|
||||||
|
|
||||||
Deprecated in ``3.3``.
|
|
||||||
|
|
||||||
**pytest_plugins in non-toplevel conftests**
|
|
||||||
|
|
||||||
There is a deep conceptual confusion as ``conftest.py`` files themselves are activated/deactivated based on path, but the plugins they depend on aren't.
|
|
||||||
|
|
||||||
Issue: `#2639 <https://github.com/pytest-dev/pytest/issues/2639>`_.
|
|
||||||
|
|
||||||
Not yet officially deprecated.
|
|
||||||
|
|
||||||
**passing a single string to pytest.main()**
|
|
||||||
|
|
||||||
Pass a list of strings to ``pytest.main()`` instead.
|
|
||||||
|
|
||||||
Deprecated in ``3.1``.
|
|
||||||
|
|
||||||
**[pytest] section in setup.cfg**
|
|
||||||
|
|
||||||
Use ``[tool:pytest]`` instead for compatibility with other tools.
|
|
||||||
|
|
||||||
Deprecated in ``3.0``.
|
|
||||||
|
|
||||||
Past Releases
|
|
||||||
~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
3.0
|
|
||||||
^^^
|
|
||||||
|
|
||||||
* The following deprecated commandline options were removed:
|
|
||||||
|
|
||||||
* ``--genscript``: no longer supported;
|
|
||||||
* ``--no-assert``: use ``--assert=plain`` instead;
|
|
||||||
* ``--nomagic``: use ``--assert=plain`` instead;
|
|
||||||
* ``--report``: use ``-r`` instead;
|
|
||||||
|
|
||||||
* Removed all ``py.test-X*`` entry points. The versioned, suffixed entry points
|
|
||||||
were never documented and a leftover from a pre-virtualenv era. These entry
|
|
||||||
points also created broken entry points in wheels, so removing them also
|
|
||||||
removes a source of confusion for users.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
3.3
|
|
||||||
^^^
|
|
||||||
|
|
||||||
* Dropped support for EOL Python 2.6 and 3.3.
|
|
||||||
|
|
|
@ -159,10 +159,10 @@ class TestRaises(object):
|
||||||
def test_dynamic_compile_shows_nicely():
|
def test_dynamic_compile_shows_nicely():
|
||||||
src = 'def foo():\n assert 1 == 0\n'
|
src = 'def foo():\n assert 1 == 0\n'
|
||||||
name = 'abc-123'
|
name = 'abc-123'
|
||||||
module = py.std.imp.new_module(name)
|
module = imp.new_module(name)
|
||||||
code = _pytest._code.compile(src, name, 'exec')
|
code = _pytest._code.compile(src, name, 'exec')
|
||||||
py.builtin.exec_(code, module.__dict__)
|
py.builtin.exec_(code, module.__dict__)
|
||||||
py.std.sys.modules[name] = module
|
sys.modules[name] = module
|
||||||
module.foo()
|
module.foo()
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -413,10 +413,10 @@ get on the terminal - we are working on that)::
|
||||||
def test_dynamic_compile_shows_nicely():
|
def test_dynamic_compile_shows_nicely():
|
||||||
src = 'def foo():\n assert 1 == 0\n'
|
src = 'def foo():\n assert 1 == 0\n'
|
||||||
name = 'abc-123'
|
name = 'abc-123'
|
||||||
module = py.std.imp.new_module(name)
|
module = imp.new_module(name)
|
||||||
code = _pytest._code.compile(src, name, 'exec')
|
code = _pytest._code.compile(src, name, 'exec')
|
||||||
py.builtin.exec_(code, module.__dict__)
|
py.builtin.exec_(code, module.__dict__)
|
||||||
py.std.sys.modules[name] = module
|
sys.modules[name] = module
|
||||||
> module.foo()
|
> module.foo()
|
||||||
|
|
||||||
failure_demo.py:166:
|
failure_demo.py:166:
|
||||||
|
|
|
@ -826,15 +826,20 @@ Instead of freezing the pytest runner as a separate executable, you can make
|
||||||
your frozen program work as the pytest runner by some clever
|
your frozen program work as the pytest runner by some clever
|
||||||
argument handling during program startup. This allows you to
|
argument handling during program startup. This allows you to
|
||||||
have a single executable, which is usually more convenient.
|
have a single executable, which is usually more convenient.
|
||||||
|
Please note that the mechanism for plugin discovery used by pytest
|
||||||
|
(setupttools entry points) doesn't work with frozen executables so pytest
|
||||||
|
can't find any third party plugins automatically. To include third party plugins
|
||||||
|
like ``pytest-timeout`` they must be imported explicitly and passed on to pytest.main.
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
# contents of app_main.py
|
# contents of app_main.py
|
||||||
import sys
|
import sys
|
||||||
|
import pytest_timeout # Third party plugin
|
||||||
|
|
||||||
if len(sys.argv) > 1 and sys.argv[1] == '--pytest':
|
if len(sys.argv) > 1 and sys.argv[1] == '--pytest':
|
||||||
import pytest
|
import pytest
|
||||||
sys.exit(pytest.main(sys.argv[2:]))
|
sys.exit(pytest.main(sys.argv[2:], plugins=[pytest_timeout]))
|
||||||
else:
|
else:
|
||||||
# normal application execution: at this point argv can be parsed
|
# normal application execution: at this point argv can be parsed
|
||||||
# by your argument-parsing library of choice as usual
|
# by your argument-parsing library of choice as usual
|
||||||
|
@ -845,3 +850,4 @@ This allows you to execute tests using the frozen
|
||||||
application with standard ``pytest`` command-line options::
|
application with standard ``pytest`` command-line options::
|
||||||
|
|
||||||
./app_main --pytest --verbose --tb=long --junitxml=results.xml test-suite/
|
./app_main --pytest --verbose --tb=long --junitxml=results.xml test-suite/
|
||||||
|
|
||||||
|
|
|
@ -7,32 +7,34 @@ Installation and Getting Started
|
||||||
|
|
||||||
**PyPI package name**: `pytest <http://pypi.python.org/pypi/pytest>`_
|
**PyPI package name**: `pytest <http://pypi.python.org/pypi/pytest>`_
|
||||||
|
|
||||||
**dependencies**: `py <http://pypi.python.org/pypi/py>`_,
|
**Dependencies**: `py <http://pypi.python.org/pypi/py>`_,
|
||||||
`colorama (Windows) <http://pypi.python.org/pypi/colorama>`_,
|
`colorama (Windows) <http://pypi.python.org/pypi/colorama>`_,
|
||||||
|
|
||||||
**documentation as PDF**: `download latest <https://media.readthedocs.org/pdf/pytest/latest/pytest.pdf>`_
|
**Documentation as PDF**: `download latest <https://media.readthedocs.org/pdf/pytest/latest/pytest.pdf>`_
|
||||||
|
|
||||||
|
``pytest`` is a framework that makes building simple and scalable tests easy. Tests are expressive and readable—no boilerplate code required. Get started in minutes with a small unit test or complex functional test for your application or library.
|
||||||
|
|
||||||
.. _`getstarted`:
|
.. _`getstarted`:
|
||||||
.. _installation:
|
.. _`installation`:
|
||||||
|
|
||||||
Installation
|
Install ``pytest``
|
||||||
----------------------------------------
|
----------------------------------------
|
||||||
|
|
||||||
Installation::
|
1. Run the following command in your command line::
|
||||||
|
|
||||||
pip install -U pytest
|
pip install -U pytest
|
||||||
|
|
||||||
To check your installation has installed the correct version::
|
2. Check that you installed the correct version::
|
||||||
|
|
||||||
$ pytest --version
|
$ pytest --version
|
||||||
This is pytest version 3.x.y, imported from $PYTHON_PREFIX/lib/python3.5/site-packages/pytest.py
|
This is pytest version 3.x.y, imported from $PYTHON_PREFIX/lib/python3.5/site-packages/pytest.py
|
||||||
|
|
||||||
.. _`simpletest`:
|
.. _`simpletest`:
|
||||||
|
|
||||||
Our first test run
|
Create your first test
|
||||||
----------------------------------------------------------
|
----------------------------------------------------------
|
||||||
|
|
||||||
Let's create a first test file with a simple test function::
|
Create a simple test function with just four lines of code::
|
||||||
|
|
||||||
# content of test_sample.py
|
# content of test_sample.py
|
||||||
def func(x):
|
def func(x):
|
||||||
|
@ -41,7 +43,7 @@ Let's create a first test file with a simple test function::
|
||||||
def test_answer():
|
def test_answer():
|
||||||
assert func(3) == 5
|
assert func(3) == 5
|
||||||
|
|
||||||
That's it. You can execute the test function now::
|
That’s it. You can now execute the test function::
|
||||||
|
|
||||||
$ pytest
|
$ pytest
|
||||||
=========================== test session starts ============================
|
=========================== test session starts ============================
|
||||||
|
@ -62,30 +64,22 @@ That's it. You can execute the test function now::
|
||||||
test_sample.py:5: AssertionError
|
test_sample.py:5: AssertionError
|
||||||
========================= 1 failed in 0.12 seconds =========================
|
========================= 1 failed in 0.12 seconds =========================
|
||||||
|
|
||||||
We got a failure report because our little ``func(3)`` call did not return ``5``.
|
This test returns a failure report because ``func(3)`` does not return ``5``.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
You can simply use the ``assert`` statement for asserting test
|
You can use the ``assert`` statement to verify test expectations. pytest’s `Advanced assertion introspection <http://docs.python.org/reference/simple_stmts.html#the-assert-statement>`_ will intelligently report intermediate values of the assert expression so you can avoid the many names `of JUnit legacy methods <http://docs.python.org/library/unittest.html#test-cases>`_.
|
||||||
expectations. pytest's :ref:`assert introspection` will intelligently
|
|
||||||
report intermediate values of the assert expression freeing
|
|
||||||
you from the need to learn the many names of `JUnit legacy methods`_.
|
|
||||||
|
|
||||||
.. _`JUnit legacy methods`: http://docs.python.org/library/unittest.html#test-cases
|
Run multiple tests
|
||||||
|
|
||||||
.. _`assert statement`: http://docs.python.org/reference/simple_stmts.html#the-assert-statement
|
|
||||||
|
|
||||||
Running multiple tests
|
|
||||||
----------------------------------------------------------
|
----------------------------------------------------------
|
||||||
|
|
||||||
``pytest`` will run all files in the current directory and its subdirectories of the form test_*.py or \*_test.py. More generally, it follows :ref:`standard test discovery rules <test discovery>`.
|
``pytest`` will run all files of the form test_*.py or \*_test.py in the current directory and its subdirectories. More generally, it follows :ref:`standard test discovery rules <test discovery>`.
|
||||||
|
|
||||||
|
|
||||||
Asserting that a certain exception is raised
|
Assert that a certain exception is raised
|
||||||
--------------------------------------------------------------
|
--------------------------------------------------------------
|
||||||
|
|
||||||
If you want to assert that some code raises an exception you can
|
Use the ``raises`` helper to assert that some code raises an exception::
|
||||||
use the ``raises`` helper::
|
|
||||||
|
|
||||||
# content of test_sysexit.py
|
# content of test_sysexit.py
|
||||||
import pytest
|
import pytest
|
||||||
|
@ -96,18 +90,16 @@ use the ``raises`` helper::
|
||||||
with pytest.raises(SystemExit):
|
with pytest.raises(SystemExit):
|
||||||
f()
|
f()
|
||||||
|
|
||||||
Running it with, this time in "quiet" reporting mode::
|
Execute the test function with “quiet” reporting mode::
|
||||||
|
|
||||||
$ pytest -q test_sysexit.py
|
$ pytest -q test_sysexit.py
|
||||||
. [100%]
|
. [100%]
|
||||||
1 passed in 0.12 seconds
|
1 passed in 0.12 seconds
|
||||||
|
|
||||||
Grouping multiple tests in a class
|
Group multiple tests in a class
|
||||||
--------------------------------------------------------------
|
--------------------------------------------------------------
|
||||||
|
|
||||||
Once you start to have more than a few tests it often makes sense
|
Once you develop multiple tests, you may want to group them into a class. pytest makes it easy to create a class containing more than one test::
|
||||||
to group tests logically, in classes and modules. Let's write a class
|
|
||||||
containing two tests::
|
|
||||||
|
|
||||||
# content of test_class.py
|
# content of test_class.py
|
||||||
class TestClass(object):
|
class TestClass(object):
|
||||||
|
@ -119,9 +111,7 @@ containing two tests::
|
||||||
x = "hello"
|
x = "hello"
|
||||||
assert hasattr(x, 'check')
|
assert hasattr(x, 'check')
|
||||||
|
|
||||||
The two tests are found because of the standard :ref:`test discovery`.
|
``pytest`` discovers all tests following its :ref:`Conventions for Python test discovery <test discovery>`, so it finds both ``test_`` prefixed functions. There is no need to subclass anything. We can simply run the module by passing its filename::
|
||||||
There is no need to subclass anything. We can simply
|
|
||||||
run the module by passing its filename::
|
|
||||||
|
|
||||||
$ pytest -q test_class.py
|
$ pytest -q test_class.py
|
||||||
.F [100%]
|
.F [100%]
|
||||||
|
@ -139,26 +129,19 @@ run the module by passing its filename::
|
||||||
test_class.py:8: AssertionError
|
test_class.py:8: AssertionError
|
||||||
1 failed, 1 passed in 0.12 seconds
|
1 failed, 1 passed in 0.12 seconds
|
||||||
|
|
||||||
The first test passed, the second failed. Again we can easily see
|
The first test passed and the second failed. You can easily see the intermediate values in the assertion to help you understand the reason for the failure.
|
||||||
the intermediate values used in the assertion, helping us to
|
|
||||||
understand the reason for the failure.
|
|
||||||
|
|
||||||
Going functional: requesting a unique temporary directory
|
Request a unique temporary directory for functional tests
|
||||||
--------------------------------------------------------------
|
--------------------------------------------------------------
|
||||||
|
|
||||||
For functional tests one often needs to create some files
|
``pytest`` provides `Builtin fixtures/function arguments <https://docs.pytest.org/en/latest/builtin.html#builtinfixtures>`_ to request arbitrary resources, like a unique temporary directory::
|
||||||
and pass them to application objects. pytest provides
|
|
||||||
:ref:`builtinfixtures` which allow to request arbitrary
|
|
||||||
resources, for example a unique temporary directory::
|
|
||||||
|
|
||||||
# content of test_tmpdir.py
|
# content of test_tmpdir.py
|
||||||
def test_needsfiles(tmpdir):
|
def test_needsfiles(tmpdir):
|
||||||
print (tmpdir)
|
print (tmpdir)
|
||||||
assert 0
|
assert 0
|
||||||
|
|
||||||
We list the name ``tmpdir`` in the test function signature and
|
List the name ``tmpdir`` in the test function signature and ``pytest`` will lookup and call a fixture factory to create the resource before performing the test function call. Before the test runs, ``pytest`` creates a unique-per-test-invocation temporary directory::
|
||||||
``pytest`` will lookup and call a fixture factory to create the resource
|
|
||||||
before performing the test function call. Let's just run it::
|
|
||||||
|
|
||||||
$ pytest -q test_tmpdir.py
|
$ pytest -q test_tmpdir.py
|
||||||
F [100%]
|
F [100%]
|
||||||
|
@ -177,22 +160,21 @@ before performing the test function call. Let's just run it::
|
||||||
PYTEST_TMPDIR/test_needsfiles0
|
PYTEST_TMPDIR/test_needsfiles0
|
||||||
1 failed in 0.12 seconds
|
1 failed in 0.12 seconds
|
||||||
|
|
||||||
Before the test runs, a unique-per-test-invocation temporary directory
|
More info on tmpdir handling is available at `Temporary directories and files <tmpdir handling>`_.
|
||||||
was created. More info at :ref:`tmpdir handling`.
|
|
||||||
|
|
||||||
You can find out what kind of builtin :ref:`fixtures` exist by typing::
|
Find out what kind of builtin ```pytest`` fixtures <fixtures>`_ exist with the command::
|
||||||
|
|
||||||
pytest --fixtures # shows builtin and custom fixtures
|
pytest --fixtures # shows builtin and custom fixtures
|
||||||
|
|
||||||
Where to go next
|
Continue reading
|
||||||
-------------------------------------
|
-------------------------------------
|
||||||
|
|
||||||
Here are a few suggestions where to go next:
|
Check out additional pytest resources to help you customize tests for your unique workflow:
|
||||||
|
|
||||||
* :ref:`cmdline` for command line invocation examples
|
* ":ref:`cmdline`" for command line invocation examples
|
||||||
* :ref:`good practices <goodpractices>` for virtualenv, test layout
|
* ":ref:`goodpractices`" for virtualenv and test layouts
|
||||||
* :ref:`existingtestsuite` for working with pre-existing tests
|
* ":ref:`existingtestsuite`" for working with pre-existing tests
|
||||||
* :ref:`fixtures` for providing a functional baseline to your tests
|
* ":ref:`fixtures`" for providing a functional baseline to your tests
|
||||||
* :ref:`plugins` managing and writing plugins
|
* ":ref:`plugins`" for managing and writing plugins
|
||||||
|
|
||||||
.. include:: links.inc
|
.. include:: links.inc
|
||||||
|
|
|
@ -123,7 +123,7 @@ To get all combinations of multiple parametrized arguments you can stack
|
||||||
def test_foo(x, y):
|
def test_foo(x, y):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
This will run the test with the arguments set to ``x=0/y=2``,``x=1/y=2``,
|
This will run the test with the arguments set to ``x=0/y=2``, ``x=1/y=2``,
|
||||||
``x=0/y=3``, and ``x=1/y=3`` exhausting parameters in the order of the decorators.
|
``x=0/y=3``, and ``x=1/y=3`` exhausting parameters in the order of the decorators.
|
||||||
|
|
||||||
.. _`pytest_generate_tests`:
|
.. _`pytest_generate_tests`:
|
||||||
|
|
|
@ -387,6 +387,15 @@ hook was invoked::
|
||||||
|
|
||||||
$ python myinvoke.py
|
$ python myinvoke.py
|
||||||
*** test run reporting finishing
|
*** test run reporting finishing
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
Calling ``pytest.main()`` will result in importing your tests and any modules
|
||||||
|
that they import. Due to the caching mechanism of python's import system,
|
||||||
|
making subsequent calls to ``pytest.main()`` from the same process will not
|
||||||
|
reflect changes to those files between the calls. For this reason, making
|
||||||
|
multiple calls to ``pytest.main()`` from the same process (in order to re-run
|
||||||
|
tests, for example) is not recommended.
|
||||||
|
|
||||||
|
|
||||||
.. include:: links.inc
|
.. include:: links.inc
|
||||||
|
|
|
@ -112,6 +112,12 @@ decorator or to all tests in a module by setting the ``pytestmark`` variable:
|
||||||
pytestmark = pytest.mark.filterwarnings('error')
|
pytestmark = pytest.mark.filterwarnings('error')
|
||||||
|
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
Except for these features, pytest does not change the python warning filter; it only captures
|
||||||
|
and displays the warnings which are issued with respect to the currently configured filter,
|
||||||
|
including changes to the filter made by test functions or by the system under test.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
``DeprecationWarning`` and ``PendingDeprecationWarning`` are hidden by the standard library
|
``DeprecationWarning`` and ``PendingDeprecationWarning`` are hidden by the standard library
|
||||||
|
|
|
@ -583,11 +583,22 @@ pytest hook reference
|
||||||
Initialization, command line and configuration hooks
|
Initialization, command line and configuration hooks
|
||||||
----------------------------------------------------
|
----------------------------------------------------
|
||||||
|
|
||||||
|
Bootstrapping hooks
|
||||||
|
~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Bootstrapping hooks called for plugins registered early enough (internal and setuptools plugins).
|
||||||
|
|
||||||
.. autofunction:: pytest_load_initial_conftests
|
.. autofunction:: pytest_load_initial_conftests
|
||||||
.. autofunction:: pytest_cmdline_preparse
|
.. autofunction:: pytest_cmdline_preparse
|
||||||
.. autofunction:: pytest_cmdline_parse
|
.. autofunction:: pytest_cmdline_parse
|
||||||
.. autofunction:: pytest_addoption
|
|
||||||
.. autofunction:: pytest_cmdline_main
|
.. autofunction:: pytest_cmdline_main
|
||||||
|
|
||||||
|
Initialization hooks
|
||||||
|
~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Initialization hooks called for plugins and ``conftest.py`` files.
|
||||||
|
|
||||||
|
.. autofunction:: pytest_addoption
|
||||||
.. autofunction:: pytest_configure
|
.. autofunction:: pytest_configure
|
||||||
.. autofunction:: pytest_unconfigure
|
.. autofunction:: pytest_unconfigure
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import json
|
import json
|
||||||
import py
|
import py
|
||||||
import textwrap
|
|
||||||
|
|
||||||
issues_url = "https://api.github.com/repos/pytest-dev/pytest/issues"
|
issues_url = "https://api.github.com/repos/pytest-dev/pytest/issues"
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
from __future__ import absolute_import, division, print_function
|
from __future__ import absolute_import, division, print_function
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
import types
|
||||||
|
|
||||||
import six
|
import six
|
||||||
|
|
||||||
|
@ -398,7 +399,7 @@ class TestGeneralUsage(object):
|
||||||
|
|
||||||
p = tmpdir.join('test_test_plugins_given_as_strings.py')
|
p = tmpdir.join('test_test_plugins_given_as_strings.py')
|
||||||
p.write('def test_foo(): pass')
|
p.write('def test_foo(): pass')
|
||||||
mod = py.std.types.ModuleType("myplugin")
|
mod = types.ModuleType("myplugin")
|
||||||
monkeypatch.setitem(sys.modules, 'myplugin', mod)
|
monkeypatch.setitem(sys.modules, 'myplugin', mod)
|
||||||
assert pytest.main(args=[str(tmpdir)], plugins=['myplugin']) == 0
|
assert pytest.main(args=[str(tmpdir)], plugins=['myplugin']) == 0
|
||||||
|
|
||||||
|
@ -492,17 +493,17 @@ class TestInvocationVariants(object):
|
||||||
|
|
||||||
def test_python_minus_m_invocation_ok(self, testdir):
|
def test_python_minus_m_invocation_ok(self, testdir):
|
||||||
p1 = testdir.makepyfile("def test_hello(): pass")
|
p1 = testdir.makepyfile("def test_hello(): pass")
|
||||||
res = testdir.run(py.std.sys.executable, "-m", "pytest", str(p1))
|
res = testdir.run(sys.executable, "-m", "pytest", str(p1))
|
||||||
assert res.ret == 0
|
assert res.ret == 0
|
||||||
|
|
||||||
def test_python_minus_m_invocation_fail(self, testdir):
|
def test_python_minus_m_invocation_fail(self, testdir):
|
||||||
p1 = testdir.makepyfile("def test_fail(): 0/0")
|
p1 = testdir.makepyfile("def test_fail(): 0/0")
|
||||||
res = testdir.run(py.std.sys.executable, "-m", "pytest", str(p1))
|
res = testdir.run(sys.executable, "-m", "pytest", str(p1))
|
||||||
assert res.ret == 1
|
assert res.ret == 1
|
||||||
|
|
||||||
def test_python_pytest_package(self, testdir):
|
def test_python_pytest_package(self, testdir):
|
||||||
p1 = testdir.makepyfile("def test_pass(): pass")
|
p1 = testdir.makepyfile("def test_pass(): pass")
|
||||||
res = testdir.run(py.std.sys.executable, "-m", "pytest", str(p1))
|
res = testdir.run(sys.executable, "-m", "pytest", str(p1))
|
||||||
assert res.ret == 0
|
assert res.ret == 0
|
||||||
res.stdout.fnmatch_lines(["*1 passed*"])
|
res.stdout.fnmatch_lines(["*1 passed*"])
|
||||||
|
|
||||||
|
@ -560,7 +561,7 @@ class TestInvocationVariants(object):
|
||||||
])
|
])
|
||||||
|
|
||||||
def join_pythonpath(what):
|
def join_pythonpath(what):
|
||||||
cur = py.std.os.environ.get('PYTHONPATH')
|
cur = os.environ.get('PYTHONPATH')
|
||||||
if cur:
|
if cur:
|
||||||
return str(what) + os.pathsep + cur
|
return str(what) + os.pathsep + cur
|
||||||
return what
|
return what
|
||||||
|
@ -618,7 +619,7 @@ class TestInvocationVariants(object):
|
||||||
# └── test_world.py
|
# └── test_world.py
|
||||||
|
|
||||||
def join_pythonpath(*dirs):
|
def join_pythonpath(*dirs):
|
||||||
cur = py.std.os.environ.get('PYTHONPATH')
|
cur = os.environ.get('PYTHONPATH')
|
||||||
if cur:
|
if cur:
|
||||||
dirs += (cur,)
|
dirs += (cur,)
|
||||||
return os.pathsep.join(str(p) for p in dirs)
|
return os.pathsep.join(str(p) for p in dirs)
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
from __future__ import absolute_import, division, print_function
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
import operator
|
import operator
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
import _pytest
|
import _pytest
|
||||||
import py
|
import py
|
||||||
import pytest
|
import pytest
|
||||||
|
@ -472,7 +474,7 @@ class TestFormattedExcinfo(object):
|
||||||
excinfo = _pytest._code.ExceptionInfo()
|
excinfo = _pytest._code.ExceptionInfo()
|
||||||
repr = pr.repr_excinfo(excinfo)
|
repr = pr.repr_excinfo(excinfo)
|
||||||
assert repr.reprtraceback.reprentries[1].lines[0] == "> ???"
|
assert repr.reprtraceback.reprentries[1].lines[0] == "> ???"
|
||||||
if py.std.sys.version_info[0] >= 3:
|
if sys.version_info[0] >= 3:
|
||||||
assert repr.chain[0][0].reprentries[1].lines[0] == "> ???"
|
assert repr.chain[0][0].reprentries[1].lines[0] == "> ???"
|
||||||
|
|
||||||
def test_repr_many_line_source_not_existing(self):
|
def test_repr_many_line_source_not_existing(self):
|
||||||
|
@ -487,7 +489,7 @@ raise ValueError()
|
||||||
excinfo = _pytest._code.ExceptionInfo()
|
excinfo = _pytest._code.ExceptionInfo()
|
||||||
repr = pr.repr_excinfo(excinfo)
|
repr = pr.repr_excinfo(excinfo)
|
||||||
assert repr.reprtraceback.reprentries[1].lines[0] == "> ???"
|
assert repr.reprtraceback.reprentries[1].lines[0] == "> ???"
|
||||||
if py.std.sys.version_info[0] >= 3:
|
if sys.version_info[0] >= 3:
|
||||||
assert repr.chain[0][0].reprentries[1].lines[0] == "> ???"
|
assert repr.chain[0][0].reprentries[1].lines[0] == "> ???"
|
||||||
|
|
||||||
def test_repr_source_failing_fullsource(self):
|
def test_repr_source_failing_fullsource(self):
|
||||||
|
@ -545,13 +547,13 @@ raise ValueError()
|
||||||
fail = IOError()
|
fail = IOError()
|
||||||
repr = pr.repr_excinfo(excinfo)
|
repr = pr.repr_excinfo(excinfo)
|
||||||
assert repr.reprtraceback.reprentries[0].lines[0] == "> ???"
|
assert repr.reprtraceback.reprentries[0].lines[0] == "> ???"
|
||||||
if py.std.sys.version_info[0] >= 3:
|
if sys.version_info[0] >= 3:
|
||||||
assert repr.chain[0][0].reprentries[0].lines[0] == "> ???"
|
assert repr.chain[0][0].reprentries[0].lines[0] == "> ???"
|
||||||
|
|
||||||
fail = py.error.ENOENT # noqa
|
fail = py.error.ENOENT # noqa
|
||||||
repr = pr.repr_excinfo(excinfo)
|
repr = pr.repr_excinfo(excinfo)
|
||||||
assert repr.reprtraceback.reprentries[0].lines[0] == "> ???"
|
assert repr.reprtraceback.reprentries[0].lines[0] == "> ???"
|
||||||
if py.std.sys.version_info[0] >= 3:
|
if sys.version_info[0] >= 3:
|
||||||
assert repr.chain[0][0].reprentries[0].lines[0] == "> ???"
|
assert repr.chain[0][0].reprentries[0].lines[0] == "> ???"
|
||||||
|
|
||||||
def test_repr_local(self):
|
def test_repr_local(self):
|
||||||
|
@ -738,7 +740,7 @@ raise ValueError()
|
||||||
repr = p.repr_excinfo(excinfo)
|
repr = p.repr_excinfo(excinfo)
|
||||||
assert repr.reprtraceback
|
assert repr.reprtraceback
|
||||||
assert len(repr.reprtraceback.reprentries) == len(reprtb.reprentries)
|
assert len(repr.reprtraceback.reprentries) == len(reprtb.reprentries)
|
||||||
if py.std.sys.version_info[0] >= 3:
|
if sys.version_info[0] >= 3:
|
||||||
assert repr.chain[0][0]
|
assert repr.chain[0][0]
|
||||||
assert len(repr.chain[0][0].reprentries) == len(reprtb.reprentries)
|
assert len(repr.chain[0][0].reprentries) == len(reprtb.reprentries)
|
||||||
assert repr.reprcrash.path.endswith("mod.py")
|
assert repr.reprcrash.path.endswith("mod.py")
|
||||||
|
@ -758,7 +760,7 @@ raise ValueError()
|
||||||
def raiseos():
|
def raiseos():
|
||||||
raise OSError(2)
|
raise OSError(2)
|
||||||
|
|
||||||
monkeypatch.setattr(py.std.os, 'getcwd', raiseos)
|
monkeypatch.setattr(os, 'getcwd', raiseos)
|
||||||
assert p._makepath(__file__) == __file__
|
assert p._makepath(__file__) == __file__
|
||||||
p.repr_traceback(excinfo)
|
p.repr_traceback(excinfo)
|
||||||
|
|
||||||
|
@ -816,10 +818,10 @@ raise ValueError()
|
||||||
for style in ("short", "long", "no"):
|
for style in ("short", "long", "no"):
|
||||||
for showlocals in (True, False):
|
for showlocals in (True, False):
|
||||||
repr = excinfo.getrepr(style=style, showlocals=showlocals)
|
repr = excinfo.getrepr(style=style, showlocals=showlocals)
|
||||||
if py.std.sys.version_info[0] < 3:
|
if sys.version_info[0] < 3:
|
||||||
assert isinstance(repr, ReprExceptionInfo)
|
assert isinstance(repr, ReprExceptionInfo)
|
||||||
assert repr.reprtraceback.style == style
|
assert repr.reprtraceback.style == style
|
||||||
if py.std.sys.version_info[0] >= 3:
|
if sys.version_info[0] >= 3:
|
||||||
assert isinstance(repr, ExceptionChainRepr)
|
assert isinstance(repr, ExceptionChainRepr)
|
||||||
for repr in repr.chain:
|
for repr in repr.chain:
|
||||||
assert repr[0].style == style
|
assert repr[0].style == style
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
# disable flake check on this file because some constructs are strange
|
# disable flake check on this file because some constructs are strange
|
||||||
# or redundant on purpose and can't be disable on a line-by-line basis
|
# or redundant on purpose and can't be disable on a line-by-line basis
|
||||||
from __future__ import absolute_import, division, print_function
|
from __future__ import absolute_import, division, print_function
|
||||||
|
import inspect
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
import _pytest._code
|
import _pytest._code
|
||||||
|
@ -187,9 +188,9 @@ class TestSourceParsingAndCompiling(object):
|
||||||
def f():
|
def f():
|
||||||
raise ValueError()
|
raise ValueError()
|
||||||
""")
|
""")
|
||||||
source1 = py.std.inspect.getsource(co1)
|
source1 = inspect.getsource(co1)
|
||||||
assert 'KeyError' in source1
|
assert 'KeyError' in source1
|
||||||
source2 = py.std.inspect.getsource(co2)
|
source2 = inspect.getsource(co2)
|
||||||
assert 'ValueError' in source2
|
assert 'ValueError' in source2
|
||||||
|
|
||||||
def test_getstatement(self):
|
def test_getstatement(self):
|
||||||
|
@ -373,7 +374,6 @@ def test_deindent():
|
||||||
c = '''while True:
|
c = '''while True:
|
||||||
pass
|
pass
|
||||||
'''
|
'''
|
||||||
import inspect
|
|
||||||
lines = deindent(inspect.getsource(f).splitlines())
|
lines = deindent(inspect.getsource(f).splitlines())
|
||||||
assert lines == ["def f():", " c = '''while True:", " pass", "'''"]
|
assert lines == ["def f():", " c = '''while True:", " pass", "'''"]
|
||||||
|
|
||||||
|
@ -461,7 +461,7 @@ def test_getfslineno():
|
||||||
|
|
||||||
fspath, lineno = getfslineno(A)
|
fspath, lineno = getfslineno(A)
|
||||||
|
|
||||||
_, A_lineno = py.std.inspect.findsource(A)
|
_, A_lineno = inspect.findsource(A)
|
||||||
assert fspath.basename == "test_source.py"
|
assert fspath.basename == "test_source.py"
|
||||||
assert lineno == A_lineno
|
assert lineno == A_lineno
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,6 @@ import sys
|
||||||
from textwrap import dedent
|
from textwrap import dedent
|
||||||
|
|
||||||
import _pytest._code
|
import _pytest._code
|
||||||
import py
|
|
||||||
import pytest
|
import pytest
|
||||||
from _pytest.main import EXIT_NOTESTSCOLLECTED
|
from _pytest.main import EXIT_NOTESTSCOLLECTED
|
||||||
from _pytest.nodes import Collector
|
from _pytest.nodes import Collector
|
||||||
|
@ -22,7 +21,7 @@ class TestModule(object):
|
||||||
b = testdir.mkdir("b")
|
b = testdir.mkdir("b")
|
||||||
p = a.ensure("test_whatever.py")
|
p = a.ensure("test_whatever.py")
|
||||||
p.pyimport()
|
p.pyimport()
|
||||||
del py.std.sys.modules['test_whatever']
|
del sys.modules['test_whatever']
|
||||||
b.ensure("test_whatever.py")
|
b.ensure("test_whatever.py")
|
||||||
result = testdir.runpytest()
|
result = testdir.runpytest()
|
||||||
result.stdout.fnmatch_lines([
|
result.stdout.fnmatch_lines([
|
||||||
|
@ -751,7 +750,7 @@ class TestSorting(object):
|
||||||
|
|
||||||
assert fn1 == fn2
|
assert fn1 == fn2
|
||||||
assert fn1 != modcol
|
assert fn1 != modcol
|
||||||
if py.std.sys.version_info < (3, 0):
|
if sys.version_info < (3, 0):
|
||||||
assert cmp(fn1, fn2) == 0
|
assert cmp(fn1, fn2) == 0
|
||||||
assert hash(fn1) == hash(fn2)
|
assert hash(fn1) == hash(fn2)
|
||||||
|
|
||||||
|
|
|
@ -761,7 +761,7 @@ class TestMetafuncFunctional(object):
|
||||||
def test_attributes(self, testdir):
|
def test_attributes(self, testdir):
|
||||||
p = testdir.makepyfile("""
|
p = testdir.makepyfile("""
|
||||||
# assumes that generate/provide runs in the same process
|
# assumes that generate/provide runs in the same process
|
||||||
import py, pytest
|
import sys, pytest
|
||||||
def pytest_generate_tests(metafunc):
|
def pytest_generate_tests(metafunc):
|
||||||
metafunc.addcall(param=metafunc)
|
metafunc.addcall(param=metafunc)
|
||||||
|
|
||||||
|
@ -780,7 +780,7 @@ class TestMetafuncFunctional(object):
|
||||||
def test_method(self, metafunc, pytestconfig):
|
def test_method(self, metafunc, pytestconfig):
|
||||||
assert metafunc.config == pytestconfig
|
assert metafunc.config == pytestconfig
|
||||||
assert metafunc.module.__name__ == __name__
|
assert metafunc.module.__name__ == __name__
|
||||||
if py.std.sys.version_info > (3, 0):
|
if sys.version_info > (3, 0):
|
||||||
unbound = TestClass.test_method
|
unbound = TestClass.test_method
|
||||||
else:
|
else:
|
||||||
unbound = TestClass.test_method.im_func
|
unbound = TestClass.test_method.im_func
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
from __future__ import absolute_import, division, print_function
|
from __future__ import absolute_import, division, print_function
|
||||||
import py
|
import subprocess
|
||||||
|
import sys
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
# test for _argcomplete but not specific for any application
|
# test for _argcomplete but not specific for any application
|
||||||
|
@ -23,21 +24,21 @@ def equal_with_bash(prefix, ffc, fc, out=None):
|
||||||
|
|
||||||
def _wrapcall(*args, **kargs):
|
def _wrapcall(*args, **kargs):
|
||||||
try:
|
try:
|
||||||
if py.std.sys.version_info > (2, 7):
|
if sys.version_info > (2, 7):
|
||||||
return py.std.subprocess.check_output(*args, **kargs).decode().splitlines()
|
return subprocess.check_output(*args, **kargs).decode().splitlines()
|
||||||
if 'stdout' in kargs:
|
if 'stdout' in kargs:
|
||||||
raise ValueError('stdout argument not allowed, it will be overridden.')
|
raise ValueError('stdout argument not allowed, it will be overridden.')
|
||||||
process = py.std.subprocess.Popen(
|
process = subprocess.Popen(
|
||||||
stdout=py.std.subprocess.PIPE, *args, **kargs)
|
stdout=subprocess.PIPE, *args, **kargs)
|
||||||
output, unused_err = process.communicate()
|
output, unused_err = process.communicate()
|
||||||
retcode = process.poll()
|
retcode = process.poll()
|
||||||
if retcode:
|
if retcode:
|
||||||
cmd = kargs.get("args")
|
cmd = kargs.get("args")
|
||||||
if cmd is None:
|
if cmd is None:
|
||||||
cmd = args[0]
|
cmd = args[0]
|
||||||
raise py.std.subprocess.CalledProcessError(retcode, cmd)
|
raise subprocess.CalledProcessError(retcode, cmd)
|
||||||
return output.decode().splitlines()
|
return output.decode().splitlines()
|
||||||
except py.std.subprocess.CalledProcessError:
|
except subprocess.CalledProcessError:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
|
||||||
|
@ -83,7 +84,7 @@ class TestArgComplete(object):
|
||||||
ffc = FastFilesCompleter()
|
ffc = FastFilesCompleter()
|
||||||
fc = FilesCompleter()
|
fc = FilesCompleter()
|
||||||
for x in ['/', '/d', '/data', 'qqq', '']:
|
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=sys.stdout)
|
||||||
|
|
||||||
@pytest.mark.skipif("sys.platform in ('win32', 'darwin')")
|
@pytest.mark.skipif("sys.platform in ('win32', 'darwin')")
|
||||||
def test_remove_dir_prefix(self):
|
def test_remove_dir_prefix(self):
|
||||||
|
@ -94,4 +95,4 @@ class TestArgComplete(object):
|
||||||
ffc = FastFilesCompleter()
|
ffc = FastFilesCompleter()
|
||||||
fc = FilesCompleter()
|
fc = FilesCompleter()
|
||||||
for x in '/usr/'.split():
|
for x in '/usr/'.split():
|
||||||
assert not equal_with_bash(x, ffc, fc, out=py.std.sys.stdout)
|
assert not equal_with_bash(x, ffc, fc, out=sys.stdout)
|
||||||
|
|
|
@ -5,6 +5,7 @@ import os
|
||||||
import py_compile
|
import py_compile
|
||||||
import stat
|
import stat
|
||||||
import sys
|
import sys
|
||||||
|
import textwrap
|
||||||
import zipfile
|
import zipfile
|
||||||
import py
|
import py
|
||||||
import pytest
|
import pytest
|
||||||
|
@ -911,7 +912,7 @@ class TestAssertionRewriteHookDetails(object):
|
||||||
def test_reload_is_same(self, testdir):
|
def test_reload_is_same(self, testdir):
|
||||||
# A file that will be picked up during collecting.
|
# A file that will be picked up during collecting.
|
||||||
testdir.tmpdir.join("file.py").ensure()
|
testdir.tmpdir.join("file.py").ensure()
|
||||||
testdir.tmpdir.join("pytest.ini").write(py.std.textwrap.dedent("""
|
testdir.tmpdir.join("pytest.ini").write(textwrap.dedent("""
|
||||||
[pytest]
|
[pytest]
|
||||||
python_files = *.py
|
python_files = *.py
|
||||||
"""))
|
"""))
|
||||||
|
@ -997,7 +998,7 @@ class TestIssue2121():
|
||||||
def test_simple_failure():
|
def test_simple_failure():
|
||||||
assert 1 + 1 == 3
|
assert 1 + 1 == 3
|
||||||
""")
|
""")
|
||||||
testdir.tmpdir.join("pytest.ini").write(py.std.textwrap.dedent("""
|
testdir.tmpdir.join("pytest.ini").write(textwrap.dedent("""
|
||||||
[pytest]
|
[pytest]
|
||||||
python_files = tests/**.py
|
python_files = tests/**.py
|
||||||
"""))
|
"""))
|
||||||
|
|
|
@ -410,8 +410,8 @@ class TestLastFailed(object):
|
||||||
def test_lastfailed_collectfailure(self, testdir, monkeypatch):
|
def test_lastfailed_collectfailure(self, testdir, monkeypatch):
|
||||||
|
|
||||||
testdir.makepyfile(test_maybe="""
|
testdir.makepyfile(test_maybe="""
|
||||||
import py
|
import os
|
||||||
env = py.std.os.environ
|
env = os.environ
|
||||||
if '1' == env['FAILIMPORT']:
|
if '1' == env['FAILIMPORT']:
|
||||||
raise ImportError('fail')
|
raise ImportError('fail')
|
||||||
def test_hello():
|
def test_hello():
|
||||||
|
@ -439,8 +439,8 @@ class TestLastFailed(object):
|
||||||
def test_lastfailed_failure_subset(self, testdir, monkeypatch):
|
def test_lastfailed_failure_subset(self, testdir, monkeypatch):
|
||||||
|
|
||||||
testdir.makepyfile(test_maybe="""
|
testdir.makepyfile(test_maybe="""
|
||||||
import py
|
import os
|
||||||
env = py.std.os.environ
|
env = os.environ
|
||||||
if '1' == env['FAILIMPORT']:
|
if '1' == env['FAILIMPORT']:
|
||||||
raise ImportError('fail')
|
raise ImportError('fail')
|
||||||
def test_hello():
|
def test_hello():
|
||||||
|
@ -448,8 +448,8 @@ class TestLastFailed(object):
|
||||||
""")
|
""")
|
||||||
|
|
||||||
testdir.makepyfile(test_maybe2="""
|
testdir.makepyfile(test_maybe2="""
|
||||||
import py
|
import os
|
||||||
env = py.std.os.environ
|
env = os.environ
|
||||||
if '1' == env['FAILIMPORT']:
|
if '1' == env['FAILIMPORT']:
|
||||||
raise ImportError('fail')
|
raise ImportError('fail')
|
||||||
def test_hello():
|
def test_hello():
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
from __future__ import absolute_import, division, print_function
|
from __future__ import absolute_import, division, print_function
|
||||||
|
import pprint
|
||||||
|
import sys
|
||||||
import pytest
|
import pytest
|
||||||
import py
|
|
||||||
|
|
||||||
import _pytest._code
|
import _pytest._code
|
||||||
from _pytest.main import Session, EXIT_NOTESTSCOLLECTED, _in_venv
|
from _pytest.main import Session, EXIT_NOTESTSCOLLECTED, _in_venv
|
||||||
|
@ -36,7 +37,7 @@ class TestCollector(object):
|
||||||
|
|
||||||
assert fn1 == fn2
|
assert fn1 == fn2
|
||||||
assert fn1 != modcol
|
assert fn1 != modcol
|
||||||
if py.std.sys.version_info < (3, 0):
|
if sys.version_info < (3, 0):
|
||||||
assert cmp(fn1, fn2) == 0
|
assert cmp(fn1, fn2) == 0
|
||||||
assert hash(fn1) == hash(fn2)
|
assert hash(fn1) == hash(fn2)
|
||||||
|
|
||||||
|
@ -128,7 +129,7 @@ class TestCollectFS(object):
|
||||||
("activate", "activate.csh", "activate.fish",
|
("activate", "activate.csh", "activate.fish",
|
||||||
"Activate", "Activate.bat", "Activate.ps1"))
|
"Activate", "Activate.bat", "Activate.ps1"))
|
||||||
def test_ignored_virtualenvs(self, testdir, fname):
|
def test_ignored_virtualenvs(self, testdir, fname):
|
||||||
bindir = "Scripts" if py.std.sys.platform.startswith("win") else "bin"
|
bindir = "Scripts" if sys.platform.startswith("win") else "bin"
|
||||||
testdir.tmpdir.ensure("virtual", bindir, fname)
|
testdir.tmpdir.ensure("virtual", bindir, fname)
|
||||||
testfile = testdir.tmpdir.ensure("virtual", "test_invenv.py")
|
testfile = testdir.tmpdir.ensure("virtual", "test_invenv.py")
|
||||||
testfile.write("def test_hello(): pass")
|
testfile.write("def test_hello(): pass")
|
||||||
|
@ -147,7 +148,7 @@ class TestCollectFS(object):
|
||||||
("activate", "activate.csh", "activate.fish",
|
("activate", "activate.csh", "activate.fish",
|
||||||
"Activate", "Activate.bat", "Activate.ps1"))
|
"Activate", "Activate.bat", "Activate.ps1"))
|
||||||
def test_ignored_virtualenvs_norecursedirs_precedence(self, testdir, fname):
|
def test_ignored_virtualenvs_norecursedirs_precedence(self, testdir, fname):
|
||||||
bindir = "Scripts" if py.std.sys.platform.startswith("win") else "bin"
|
bindir = "Scripts" if sys.platform.startswith("win") else "bin"
|
||||||
# norecursedirs takes priority
|
# norecursedirs takes priority
|
||||||
testdir.tmpdir.ensure(".virtual", bindir, fname)
|
testdir.tmpdir.ensure(".virtual", bindir, fname)
|
||||||
testfile = testdir.tmpdir.ensure(".virtual", "test_invenv.py")
|
testfile = testdir.tmpdir.ensure(".virtual", "test_invenv.py")
|
||||||
|
@ -163,7 +164,7 @@ class TestCollectFS(object):
|
||||||
"Activate", "Activate.bat", "Activate.ps1"))
|
"Activate", "Activate.bat", "Activate.ps1"))
|
||||||
def test__in_venv(self, testdir, fname):
|
def test__in_venv(self, testdir, fname):
|
||||||
"""Directly test the virtual env detection function"""
|
"""Directly test the virtual env detection function"""
|
||||||
bindir = "Scripts" if py.std.sys.platform.startswith("win") else "bin"
|
bindir = "Scripts" if sys.platform.startswith("win") else "bin"
|
||||||
# no bin/activate, not a virtualenv
|
# no bin/activate, not a virtualenv
|
||||||
base_path = testdir.tmpdir.mkdir('venv')
|
base_path = testdir.tmpdir.mkdir('venv')
|
||||||
assert _in_venv(base_path) is False
|
assert _in_venv(base_path) is False
|
||||||
|
@ -436,7 +437,7 @@ class TestSession(object):
|
||||||
assert item.name == "test_func"
|
assert item.name == "test_func"
|
||||||
newid = item.nodeid
|
newid = item.nodeid
|
||||||
assert newid == id
|
assert newid == id
|
||||||
py.std.pprint.pprint(hookrec.calls)
|
pprint.pprint(hookrec.calls)
|
||||||
topdir = testdir.tmpdir # noqa
|
topdir = testdir.tmpdir # noqa
|
||||||
hookrec.assert_contains([
|
hookrec.assert_contains([
|
||||||
("pytest_collectstart", "collector.fspath == topdir"),
|
("pytest_collectstart", "collector.fspath == topdir"),
|
||||||
|
@ -486,7 +487,7 @@ class TestSession(object):
|
||||||
id = p.basename
|
id = p.basename
|
||||||
|
|
||||||
items, hookrec = testdir.inline_genitems(id)
|
items, hookrec = testdir.inline_genitems(id)
|
||||||
py.std.pprint.pprint(hookrec.calls)
|
pprint.pprint(hookrec.calls)
|
||||||
assert len(items) == 2
|
assert len(items) == 2
|
||||||
hookrec.assert_contains([
|
hookrec.assert_contains([
|
||||||
("pytest_collectstart",
|
("pytest_collectstart",
|
||||||
|
@ -508,7 +509,7 @@ class TestSession(object):
|
||||||
|
|
||||||
items, hookrec = testdir.inline_genitems()
|
items, hookrec = testdir.inline_genitems()
|
||||||
assert len(items) == 1
|
assert len(items) == 1
|
||||||
py.std.pprint.pprint(hookrec.calls)
|
pprint.pprint(hookrec.calls)
|
||||||
hookrec.assert_contains([
|
hookrec.assert_contains([
|
||||||
("pytest_collectstart", "collector.fspath == test_aaa"),
|
("pytest_collectstart", "collector.fspath == test_aaa"),
|
||||||
("pytest_pycollect_makeitem", "name == 'test_func'"),
|
("pytest_pycollect_makeitem", "name == 'test_func'"),
|
||||||
|
@ -529,7 +530,7 @@ class TestSession(object):
|
||||||
|
|
||||||
items, hookrec = testdir.inline_genitems(id)
|
items, hookrec = testdir.inline_genitems(id)
|
||||||
assert len(items) == 2
|
assert len(items) == 2
|
||||||
py.std.pprint.pprint(hookrec.calls)
|
pprint.pprint(hookrec.calls)
|
||||||
hookrec.assert_contains([
|
hookrec.assert_contains([
|
||||||
("pytest_collectstart", "collector.fspath == test_aaa"),
|
("pytest_collectstart", "collector.fspath == test_aaa"),
|
||||||
("pytest_pycollect_makeitem", "name == 'test_func'"),
|
("pytest_pycollect_makeitem", "name == 'test_func'"),
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
from __future__ import absolute_import, division, print_function
|
from __future__ import absolute_import, division, print_function
|
||||||
import sys
|
import sys
|
||||||
import py
|
import textwrap
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
import _pytest._code
|
import _pytest._code
|
||||||
|
@ -57,7 +57,7 @@ class TestParseIni(object):
|
||||||
('pytest', 'pytest.ini')],
|
('pytest', 'pytest.ini')],
|
||||||
)
|
)
|
||||||
def test_ini_names(self, testdir, name, section):
|
def test_ini_names(self, testdir, name, section):
|
||||||
testdir.tmpdir.join(name).write(py.std.textwrap.dedent("""
|
testdir.tmpdir.join(name).write(textwrap.dedent("""
|
||||||
[{section}]
|
[{section}]
|
||||||
minversion = 1.0
|
minversion = 1.0
|
||||||
""".format(section=section)))
|
""".format(section=section)))
|
||||||
|
@ -66,11 +66,11 @@ class TestParseIni(object):
|
||||||
|
|
||||||
def test_toxini_before_lower_pytestini(self, testdir):
|
def test_toxini_before_lower_pytestini(self, testdir):
|
||||||
sub = testdir.tmpdir.mkdir("sub")
|
sub = testdir.tmpdir.mkdir("sub")
|
||||||
sub.join("tox.ini").write(py.std.textwrap.dedent("""
|
sub.join("tox.ini").write(textwrap.dedent("""
|
||||||
[pytest]
|
[pytest]
|
||||||
minversion = 2.0
|
minversion = 2.0
|
||||||
"""))
|
"""))
|
||||||
testdir.tmpdir.join("pytest.ini").write(py.std.textwrap.dedent("""
|
testdir.tmpdir.join("pytest.ini").write(textwrap.dedent("""
|
||||||
[pytest]
|
[pytest]
|
||||||
minversion = 1.5
|
minversion = 1.5
|
||||||
"""))
|
"""))
|
||||||
|
@ -731,7 +731,7 @@ class TestRootdir(object):
|
||||||
class TestOverrideIniArgs(object):
|
class TestOverrideIniArgs(object):
|
||||||
@pytest.mark.parametrize("name", "setup.cfg tox.ini pytest.ini".split())
|
@pytest.mark.parametrize("name", "setup.cfg tox.ini pytest.ini".split())
|
||||||
def test_override_ini_names(self, testdir, name):
|
def test_override_ini_names(self, testdir, name):
|
||||||
testdir.tmpdir.join(name).write(py.std.textwrap.dedent("""
|
testdir.tmpdir.join(name).write(textwrap.dedent("""
|
||||||
[pytest]
|
[pytest]
|
||||||
custom = 1.0"""))
|
custom = 1.0"""))
|
||||||
testdir.makeconftest("""
|
testdir.makeconftest("""
|
||||||
|
|
|
@ -232,7 +232,7 @@ def test_fixture_dependency(testdir, monkeypatch):
|
||||||
ct1.write("")
|
ct1.write("")
|
||||||
sub = testdir.mkdir("sub")
|
sub = testdir.mkdir("sub")
|
||||||
sub.join("__init__.py").write("")
|
sub.join("__init__.py").write("")
|
||||||
sub.join("conftest.py").write(py.std.textwrap.dedent("""
|
sub.join("conftest.py").write(dedent("""
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
@ -249,7 +249,7 @@ def test_fixture_dependency(testdir, monkeypatch):
|
||||||
"""))
|
"""))
|
||||||
subsub = sub.mkdir("subsub")
|
subsub = sub.mkdir("subsub")
|
||||||
subsub.join("__init__.py").write("")
|
subsub.join("__init__.py").write("")
|
||||||
subsub.join("test_bar.py").write(py.std.textwrap.dedent("""
|
subsub.join("test_bar.py").write(dedent("""
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
@ -265,7 +265,7 @@ def test_fixture_dependency(testdir, monkeypatch):
|
||||||
|
|
||||||
def test_conftest_found_with_double_dash(testdir):
|
def test_conftest_found_with_double_dash(testdir):
|
||||||
sub = testdir.mkdir("sub")
|
sub = testdir.mkdir("sub")
|
||||||
sub.join("conftest.py").write(py.std.textwrap.dedent("""
|
sub.join("conftest.py").write(dedent("""
|
||||||
def pytest_addoption(parser):
|
def pytest_addoption(parser):
|
||||||
parser.addoption("--hello-world", action="store_true")
|
parser.addoption("--hello-world", action="store_true")
|
||||||
"""))
|
"""))
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
from __future__ import absolute_import, division, print_function
|
from __future__ import absolute_import, division, print_function
|
||||||
|
import argparse
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
import py
|
import py
|
||||||
|
@ -189,7 +190,7 @@ class TestParser(object):
|
||||||
assert option.no is False
|
assert option.no is False
|
||||||
|
|
||||||
def test_drop_short_helper(self):
|
def test_drop_short_helper(self):
|
||||||
parser = py.std.argparse.ArgumentParser(formatter_class=parseopt.DropShorterLongHelpFormatter)
|
parser = argparse.ArgumentParser(formatter_class=parseopt.DropShorterLongHelpFormatter)
|
||||||
parser.add_argument('-t', '--twoword', '--duo', '--two-word', '--two',
|
parser.add_argument('-t', '--twoword', '--duo', '--two-word', '--two',
|
||||||
help='foo').map_long_option = {'two': 'two-word'}
|
help='foo').map_long_option = {'two': 'two-word'}
|
||||||
# throws error on --deux only!
|
# throws error on --deux only!
|
||||||
|
|
|
@ -402,5 +402,4 @@ class TestPDB(object):
|
||||||
child = testdir.spawn_pytest("--pdbcls=custom_pdb:CustomPdb %s" % str(p1))
|
child = testdir.spawn_pytest("--pdbcls=custom_pdb:CustomPdb %s" % str(p1))
|
||||||
|
|
||||||
child.expect('custom set_trace>')
|
child.expect('custom set_trace>')
|
||||||
if child.isalive():
|
self.flush(child)
|
||||||
child.wait()
|
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
# encoding: UTF-8
|
# encoding: UTF-8
|
||||||
from __future__ import absolute_import, division, print_function
|
from __future__ import absolute_import, division, print_function
|
||||||
import pytest
|
import pytest
|
||||||
import py
|
|
||||||
import os
|
import os
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
import types
|
||||||
|
|
||||||
from _pytest.config import get_config, PytestPluginManager
|
from _pytest.config import get_config, PytestPluginManager
|
||||||
from _pytest.main import EXIT_NOTESTSCOLLECTED, Session
|
from _pytest.main import EXIT_NOTESTSCOLLECTED, Session
|
||||||
|
@ -208,14 +210,14 @@ def test_importplugin_error_message(testdir, pytestpm):
|
||||||
|
|
||||||
expected_message = '.*Error importing plugin "qwe": Not possible to import: .'
|
expected_message = '.*Error importing plugin "qwe": Not possible to import: .'
|
||||||
expected_traceback = ".*in test_traceback"
|
expected_traceback = ".*in test_traceback"
|
||||||
assert py.std.re.match(expected_message, str(excinfo.value))
|
assert re.match(expected_message, str(excinfo.value))
|
||||||
assert py.std.re.match(expected_traceback, str(excinfo.traceback[-1]))
|
assert re.match(expected_traceback, str(excinfo.traceback[-1]))
|
||||||
|
|
||||||
|
|
||||||
class TestPytestPluginManager(object):
|
class TestPytestPluginManager(object):
|
||||||
def test_register_imported_modules(self):
|
def test_register_imported_modules(self):
|
||||||
pm = PytestPluginManager()
|
pm = PytestPluginManager()
|
||||||
mod = py.std.types.ModuleType("x.y.pytest_hello")
|
mod = types.ModuleType("x.y.pytest_hello")
|
||||||
pm.register(mod)
|
pm.register(mod)
|
||||||
assert pm.is_registered(mod)
|
assert pm.is_registered(mod)
|
||||||
values = pm.get_plugins()
|
values = pm.get_plugins()
|
||||||
|
@ -226,8 +228,8 @@ class TestPytestPluginManager(object):
|
||||||
assert pm.get_plugins() == values
|
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 = types.ModuleType("pytest_xyz")
|
||||||
monkeypatch.setitem(py.std.sys.modules, 'pytest_xyz', mod)
|
monkeypatch.setitem(sys.modules, 'pytest_xyz', mod)
|
||||||
pm = PytestPluginManager()
|
pm = PytestPluginManager()
|
||||||
pm.import_plugin('pytest_xyz')
|
pm.import_plugin('pytest_xyz')
|
||||||
assert pm.get_plugin('pytest_xyz') == mod
|
assert pm.get_plugin('pytest_xyz') == mod
|
||||||
|
@ -237,7 +239,7 @@ class TestPytestPluginManager(object):
|
||||||
testdir.syspathinsert()
|
testdir.syspathinsert()
|
||||||
testdir.makepyfile(pytest_p1="#")
|
testdir.makepyfile(pytest_p1="#")
|
||||||
testdir.makepyfile(pytest_p2="#")
|
testdir.makepyfile(pytest_p2="#")
|
||||||
mod = py.std.types.ModuleType("temp")
|
mod = types.ModuleType("temp")
|
||||||
mod.pytest_plugins = ["pytest_p1", "pytest_p2"]
|
mod.pytest_plugins = ["pytest_p1", "pytest_p2"]
|
||||||
pytestpm.consider_module(mod)
|
pytestpm.consider_module(mod)
|
||||||
assert pytestpm.get_plugin("pytest_p1").__name__ == "pytest_p1"
|
assert pytestpm.get_plugin("pytest_p1").__name__ == "pytest_p1"
|
||||||
|
@ -245,12 +247,12 @@ class TestPytestPluginManager(object):
|
||||||
|
|
||||||
def test_consider_module_import_module(self, testdir):
|
def test_consider_module_import_module(self, testdir):
|
||||||
pytestpm = get_config().pluginmanager
|
pytestpm = get_config().pluginmanager
|
||||||
mod = py.std.types.ModuleType("x")
|
mod = types.ModuleType("x")
|
||||||
mod.pytest_plugins = "pytest_a"
|
mod.pytest_plugins = "pytest_a"
|
||||||
aplugin = testdir.makepyfile(pytest_a="#")
|
aplugin = testdir.makepyfile(pytest_a="#")
|
||||||
reprec = testdir.make_hook_recorder(pytestpm)
|
reprec = testdir.make_hook_recorder(pytestpm)
|
||||||
# syspath.prepend(aplugin.dirpath())
|
# syspath.prepend(aplugin.dirpath())
|
||||||
py.std.sys.path.insert(0, str(aplugin.dirpath()))
|
sys.path.insert(0, str(aplugin.dirpath()))
|
||||||
pytestpm.consider_module(mod)
|
pytestpm.consider_module(mod)
|
||||||
call = reprec.getcall(pytestpm.hook.pytest_plugin_registered.name)
|
call = reprec.getcall(pytestpm.hook.pytest_plugin_registered.name)
|
||||||
assert call.plugin.__name__ == "pytest_a"
|
assert call.plugin.__name__ == "pytest_a"
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
from __future__ import absolute_import, division, print_function
|
from __future__ import absolute_import, division, print_function
|
||||||
import warnings
|
import warnings
|
||||||
import re
|
import re
|
||||||
import py
|
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from _pytest.recwarn import WarningsRecorder
|
from _pytest.recwarn import WarningsRecorder
|
||||||
|
@ -24,9 +23,9 @@ class TestWarningsRecorderChecker(object):
|
||||||
rec = WarningsRecorder()
|
rec = WarningsRecorder()
|
||||||
with rec:
|
with rec:
|
||||||
assert not rec.list
|
assert not rec.list
|
||||||
py.std.warnings.warn_explicit("hello", UserWarning, "xyz", 13)
|
warnings.warn_explicit("hello", UserWarning, "xyz", 13)
|
||||||
assert len(rec.list) == 1
|
assert len(rec.list) == 1
|
||||||
py.std.warnings.warn(DeprecationWarning("hello"))
|
warnings.warn(DeprecationWarning("hello"))
|
||||||
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"
|
||||||
|
@ -64,14 +63,14 @@ class TestDeprecatedCall(object):
|
||||||
|
|
||||||
def dep(self, i, j=None):
|
def dep(self, i, j=None):
|
||||||
if i == 0:
|
if i == 0:
|
||||||
py.std.warnings.warn("is deprecated", DeprecationWarning,
|
warnings.warn("is deprecated", DeprecationWarning,
|
||||||
stacklevel=1)
|
stacklevel=1)
|
||||||
return 42
|
return 42
|
||||||
|
|
||||||
def dep_explicit(self, i):
|
def dep_explicit(self, i):
|
||||||
if i == 0:
|
if i == 0:
|
||||||
py.std.warnings.warn_explicit("dep_explicit", category=DeprecationWarning,
|
warnings.warn_explicit("dep_explicit", category=DeprecationWarning,
|
||||||
filename="hello", lineno=3)
|
filename="hello", lineno=3)
|
||||||
|
|
||||||
def test_deprecated_call_raises(self):
|
def test_deprecated_call_raises(self):
|
||||||
with pytest.raises(AssertionError) as excinfo:
|
with pytest.raises(AssertionError) as excinfo:
|
||||||
|
@ -86,16 +85,16 @@ class TestDeprecatedCall(object):
|
||||||
assert ret == 42
|
assert ret == 42
|
||||||
|
|
||||||
def test_deprecated_call_preserves(self):
|
def test_deprecated_call_preserves(self):
|
||||||
onceregistry = py.std.warnings.onceregistry.copy()
|
onceregistry = warnings.onceregistry.copy()
|
||||||
filters = py.std.warnings.filters[:]
|
filters = warnings.filters[:]
|
||||||
warn = py.std.warnings.warn
|
warn = warnings.warn
|
||||||
warn_explicit = py.std.warnings.warn_explicit
|
warn_explicit = warnings.warn_explicit
|
||||||
self.test_deprecated_call_raises()
|
self.test_deprecated_call_raises()
|
||||||
self.test_deprecated_call()
|
self.test_deprecated_call()
|
||||||
assert onceregistry == py.std.warnings.onceregistry
|
assert onceregistry == warnings.onceregistry
|
||||||
assert filters == py.std.warnings.filters
|
assert filters == warnings.filters
|
||||||
assert warn is py.std.warnings.warn
|
assert warn is warnings.warn
|
||||||
assert warn_explicit is py.std.warnings.warn_explicit
|
assert warn_explicit is warnings.warn_explicit
|
||||||
|
|
||||||
def test_deprecated_explicit_call_raises(self):
|
def test_deprecated_explicit_call_raises(self):
|
||||||
with pytest.raises(AssertionError):
|
with pytest.raises(AssertionError):
|
||||||
|
|
|
@ -2,10 +2,12 @@
|
||||||
from __future__ import absolute_import, division, print_function
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
import _pytest._code
|
import _pytest._code
|
||||||
|
import inspect
|
||||||
import os
|
import os
|
||||||
import py
|
import py
|
||||||
import pytest
|
import pytest
|
||||||
import sys
|
import sys
|
||||||
|
import types
|
||||||
from _pytest import runner, main, outcomes
|
from _pytest import runner, main, outcomes
|
||||||
|
|
||||||
|
|
||||||
|
@ -404,10 +406,10 @@ reporttypes = [
|
||||||
|
|
||||||
@pytest.mark.parametrize('reporttype', reporttypes, ids=[x.__name__ for x in reporttypes])
|
@pytest.mark.parametrize('reporttype', reporttypes, ids=[x.__name__ for x in reporttypes])
|
||||||
def test_report_extra_parameters(reporttype):
|
def test_report_extra_parameters(reporttype):
|
||||||
if hasattr(py.std.inspect, 'signature'):
|
if hasattr(inspect, 'signature'):
|
||||||
args = list(py.std.inspect.signature(reporttype.__init__).parameters.keys())[1:]
|
args = list(inspect.signature(reporttype.__init__).parameters.keys())[1:]
|
||||||
else:
|
else:
|
||||||
args = py.std.inspect.getargspec(reporttype.__init__)[0][1:]
|
args = inspect.getargspec(reporttype.__init__)[0][1:]
|
||||||
basekw = dict.fromkeys(args, [])
|
basekw = dict.fromkeys(args, [])
|
||||||
report = reporttype(newthing=1, **basekw)
|
report = reporttype(newthing=1, **basekw)
|
||||||
assert report.newthing == 1
|
assert report.newthing == 1
|
||||||
|
@ -576,10 +578,10 @@ def test_importorskip(monkeypatch):
|
||||||
importorskip("asdlkj")
|
importorskip("asdlkj")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
sys = importorskip("sys")
|
sysmod = importorskip("sys")
|
||||||
assert sys == py.std.sys
|
assert sysmod is sys
|
||||||
# path = pytest.importorskip("os.path")
|
# path = pytest.importorskip("os.path")
|
||||||
# assert path == py.std.os.path
|
# assert path == os.path
|
||||||
excinfo = pytest.raises(pytest.skip.Exception, f)
|
excinfo = pytest.raises(pytest.skip.Exception, f)
|
||||||
path = py.path.local(excinfo.getrepr().reprcrash.path)
|
path = py.path.local(excinfo.getrepr().reprcrash.path)
|
||||||
# check that importorskip reports the actual call
|
# check that importorskip reports the actual call
|
||||||
|
@ -587,7 +589,7 @@ def test_importorskip(monkeypatch):
|
||||||
assert path.purebasename == "test_runner"
|
assert path.purebasename == "test_runner"
|
||||||
pytest.raises(SyntaxError, "pytest.importorskip('x y z')")
|
pytest.raises(SyntaxError, "pytest.importorskip('x y z')")
|
||||||
pytest.raises(SyntaxError, "pytest.importorskip('x=y')")
|
pytest.raises(SyntaxError, "pytest.importorskip('x=y')")
|
||||||
mod = py.std.types.ModuleType("hello123")
|
mod = types.ModuleType("hello123")
|
||||||
mod.__version__ = "1.3"
|
mod.__version__ = "1.3"
|
||||||
monkeypatch.setitem(sys.modules, "hello123", mod)
|
monkeypatch.setitem(sys.modules, "hello123", mod)
|
||||||
pytest.raises(pytest.skip.Exception, """
|
pytest.raises(pytest.skip.Exception, """
|
||||||
|
@ -607,7 +609,7 @@ def test_importorskip_imports_last_module_part():
|
||||||
|
|
||||||
def test_importorskip_dev_module(monkeypatch):
|
def test_importorskip_dev_module(monkeypatch):
|
||||||
try:
|
try:
|
||||||
mod = py.std.types.ModuleType("mockmodule")
|
mod = types.ModuleType("mockmodule")
|
||||||
mod.__version__ = '0.13.0.dev-43290'
|
mod.__version__ = '0.13.0.dev-43290'
|
||||||
monkeypatch.setitem(sys.modules, 'mockmodule', mod)
|
monkeypatch.setitem(sys.modules, 'mockmodule', mod)
|
||||||
mod2 = pytest.importorskip('mockmodule', minversion='0.12.0')
|
mod2 = pytest.importorskip('mockmodule', minversion='0.12.0')
|
||||||
|
|
|
@ -326,7 +326,7 @@ def test_repr_python_version(monkeypatch):
|
||||||
try:
|
try:
|
||||||
monkeypatch.setattr(sys, 'version_info', (2, 5, 1, 'final', 0))
|
monkeypatch.setattr(sys, 'version_info', (2, 5, 1, 'final', 0))
|
||||||
assert repr_pythonversion() == "2.5.1-final-0"
|
assert repr_pythonversion() == "2.5.1-final-0"
|
||||||
py.std.sys.version_info = x = (2, 3)
|
sys.version_info = x = (2, 3)
|
||||||
assert repr_pythonversion() == str(x)
|
assert repr_pythonversion() == str(x)
|
||||||
finally:
|
finally:
|
||||||
monkeypatch.undo() # do this early as pytest can get confused
|
monkeypatch.undo() # do this early as pytest can get confused
|
||||||
|
@ -475,11 +475,11 @@ class TestTerminalFunctional(object):
|
||||||
pass
|
pass
|
||||||
""")
|
""")
|
||||||
result = testdir.runpytest()
|
result = testdir.runpytest()
|
||||||
verinfo = ".".join(map(str, py.std.sys.version_info[:3]))
|
verinfo = ".".join(map(str, sys.version_info[:3]))
|
||||||
result.stdout.fnmatch_lines([
|
result.stdout.fnmatch_lines([
|
||||||
"*===== test session starts ====*",
|
"*===== test session starts ====*",
|
||||||
"platform %s -- Python %s*pytest-%s*py-%s*pluggy-%s" % (
|
"platform %s -- Python %s*pytest-%s*py-%s*pluggy-%s" % (
|
||||||
py.std.sys.platform, verinfo,
|
sys.platform, verinfo,
|
||||||
pytest.__version__, py.__version__, pluggy.__version__),
|
pytest.__version__, py.__version__, pluggy.__version__),
|
||||||
"*test_header_trailer_info.py .*",
|
"*test_header_trailer_info.py .*",
|
||||||
"=* 1 passed*in *.[0-9][0-9] seconds *=",
|
"=* 1 passed*in *.[0-9][0-9] seconds *=",
|
||||||
|
|
Loading…
Reference in New Issue