summaryrefslogtreecommitdiff
path: root/_pytest
diff options
context:
space:
mode:
authorRonny Pfannschmidt <opensource@ronnypfannschmidt.de>2018-03-17 09:40:32 +0100
committerGitHub <noreply@github.com>2018-03-17 09:40:32 +0100
commitf61d0525a53de3c51da58313307d2e95fad062e5 (patch)
tree8d64d5fc6160c2f15b2c5e85fe3b57f8fabf9328 /_pytest
parent86d6804e60ecfcdb0a2b7a73e2e274ffea00d0fb (diff)
parent1fff81e21d4145e501d618bced645cbfaa5f5afc (diff)
downloadpytest-f61d0525a53de3c51da58313307d2e95fad062e5.tar.gz
Merge pull request #3318 from nicoddemus/merge-master-into-features
Merge master into features
Diffstat (limited to '_pytest')
-rw-r--r--_pytest/capture.py39
-rw-r--r--_pytest/config.py2
-rw-r--r--_pytest/doctest.py2
-rw-r--r--_pytest/fixtures.py12
-rw-r--r--_pytest/junitxml.py8
-rw-r--r--_pytest/logging.py12
-rw-r--r--_pytest/mark/__init__.py15
-rw-r--r--_pytest/monkeypatch.py2
-rw-r--r--_pytest/python.py2
-rw-r--r--_pytest/python_api.py5
-rw-r--r--_pytest/recwarn.py13
-rw-r--r--_pytest/tmpdir.py2
12 files changed, 87 insertions, 27 deletions
diff --git a/_pytest/capture.py b/_pytest/capture.py
index 36658acce..9f4f41c41 100644
--- a/_pytest/capture.py
+++ b/_pytest/capture.py
@@ -197,9 +197,9 @@ def _ensure_only_one_capture_fixture(request, name):
@pytest.fixture
def capsys(request):
- """Enable capturing of writes to sys.stdout/sys.stderr and make
+ """Enable capturing of writes to ``sys.stdout`` and ``sys.stderr`` and make
captured output available via ``capsys.readouterr()`` method calls
- which return a ``(out, err)`` tuple. ``out`` and ``err`` will be ``text``
+ which return a ``(out, err)`` namedtuple. ``out`` and ``err`` will be ``text``
objects.
"""
_ensure_only_one_capture_fixture(request, 'capsys')
@@ -209,7 +209,7 @@ def capsys(request):
@pytest.fixture
def capsysbinary(request):
- """Enable capturing of writes to sys.stdout/sys.stderr and make
+ """Enable capturing of writes to ``sys.stdout`` and ``sys.stderr`` and make
captured output available via ``capsys.readouterr()`` method calls
which return a ``(out, err)`` tuple. ``out`` and ``err`` will be ``bytes``
objects.
@@ -225,7 +225,7 @@ def capsysbinary(request):
@pytest.fixture
def capfd(request):
- """Enable capturing of writes to file descriptors 1 and 2 and make
+ """Enable capturing of writes to file descriptors ``1`` and ``2`` and make
captured output available via ``capfd.readouterr()`` method calls
which return a ``(out, err)`` tuple. ``out`` and ``err`` will be ``text``
objects.
@@ -272,6 +272,10 @@ def _install_capture_fixture_on_item(request, capture_class):
class CaptureFixture(object):
+ """
+ Object returned by :py:func:`capsys`, :py:func:`capsysbinary`, :py:func:`capfd` and :py:func:`capfdbinary`
+ fixtures.
+ """
def __init__(self, captureclass, request):
self.captureclass = captureclass
self.request = request
@@ -288,6 +292,10 @@ class CaptureFixture(object):
cap.stop_capturing()
def readouterr(self):
+ """Read and return the captured output so far, resetting the internal buffer.
+
+ :return: captured content as a namedtuple with ``out`` and ``err`` string attributes
+ """
try:
return self._capture.readouterr()
except AttributeError:
@@ -295,6 +303,7 @@ class CaptureFixture(object):
@contextlib.contextmanager
def disabled(self):
+ """Temporarily disables capture while inside the 'with' block."""
self._capture.suspend_capturing()
capmanager = self.request.config.pluginmanager.getplugin('capturemanager')
capmanager.suspend_global_capture(item=None, in_=False)
@@ -476,7 +485,7 @@ class FDCaptureBinary(object):
os.dup2(targetfd_save, self.targetfd)
os.close(targetfd_save)
self.syscapture.done()
- self.tmpfile.close()
+ _attempt_to_close_capture_file(self.tmpfile)
def suspend(self):
self.syscapture.suspend()
@@ -530,7 +539,7 @@ class SysCapture(object):
def done(self):
setattr(sys, self.name, self._old)
del self._old
- self.tmpfile.close()
+ _attempt_to_close_capture_file(self.tmpfile)
def suspend(self):
setattr(sys, self.name, self._old)
@@ -551,7 +560,7 @@ class SysCaptureBinary(SysCapture):
return res
-class DontReadFromInput(object):
+class DontReadFromInput(six.Iterator):
"""Temporary stub class. Ideally when stdin is accessed, the
capturing should be turned off, with possibly all data captured
so far sent to the screen. This should be configurable, though,
@@ -565,7 +574,10 @@ class DontReadFromInput(object):
raise IOError("reading from stdin while output is captured")
readline = read
readlines = read
- __iter__ = read
+ __next__ = read
+
+ def __iter__(self):
+ return self
def fileno(self):
raise UnsupportedOperation("redirected stdin is pseudofile, "
@@ -681,3 +693,14 @@ def _py36_windowsconsoleio_workaround(stream):
sys.__stdin__ = sys.stdin = _reopen_stdio(sys.stdin, 'rb')
sys.__stdout__ = sys.stdout = _reopen_stdio(sys.stdout, 'wb')
sys.__stderr__ = sys.stderr = _reopen_stdio(sys.stderr, 'wb')
+
+
+def _attempt_to_close_capture_file(f):
+ """Suppress IOError when closing the temporary file used for capturing streams in py27 (#2370)"""
+ if six.PY2:
+ try:
+ f.close()
+ except IOError:
+ pass
+ else:
+ f.close()
diff --git a/_pytest/config.py b/_pytest/config.py
index 63c7dc3bb..4087d6e9f 100644
--- a/_pytest/config.py
+++ b/_pytest/config.py
@@ -171,7 +171,7 @@ class PytestPluginManager(PluginManager):
Overwrites :py:class:`pluggy.PluginManager <pluggy.PluginManager>` to add pytest-specific
functionality:
- * loading plugins from the command line, ``PYTEST_PLUGIN`` env variable and
+ * loading plugins from the command line, ``PYTEST_PLUGINS`` env variable and
``pytest_plugins`` global variables found in plugins being loaded;
* ``conftest.py`` loading during start-up;
"""
diff --git a/_pytest/doctest.py b/_pytest/doctest.py
index 03775a09a..131109cba 100644
--- a/_pytest/doctest.py
+++ b/_pytest/doctest.py
@@ -462,6 +462,6 @@ def _fix_spoof_python2(runner, encoding):
@pytest.fixture(scope='session')
def doctest_namespace():
"""
- Inject names into the doctest namespace.
+ Fixture that returns a :py:class:`dict` that will be injected into the namespace of doctests.
"""
return dict()
diff --git a/_pytest/fixtures.py b/_pytest/fixtures.py
index df0d1a41a..e2ea84e30 100644
--- a/_pytest/fixtures.py
+++ b/_pytest/fixtures.py
@@ -858,7 +858,7 @@ class FixtureFunctionMarker(object):
def fixture(scope="function", params=None, autouse=False, ids=None, name=None):
- """ (return a) decorator to mark a fixture factory function.
+ """Decorator to mark a fixture factory function.
This decorator can be used (with or without parameters) to define a
fixture function. The name of the fixture function can later be
@@ -923,7 +923,15 @@ defaultfuncargprefixmarker = fixture()
@fixture(scope="session")
def pytestconfig(request):
- """ the pytest config object with access to command line opts."""
+ """Session-scoped fixture that returns the :class:`_pytest.config.Config` object.
+
+ Example::
+
+ def test_foo(pytestconfig):
+ if pytestconfig.getoption("verbose"):
+ ...
+
+ """
return request.config
diff --git a/_pytest/junitxml.py b/_pytest/junitxml.py
index 98b2d13cf..5207c2514 100644
--- a/_pytest/junitxml.py
+++ b/_pytest/junitxml.py
@@ -237,7 +237,13 @@ def record_property(request):
"""Add an extra properties the calling test.
User properties become part of the test report and are available to the
configured reporters, like JUnit XML.
- The fixture is callable with ``(name, value)``.
+ The fixture is callable with ``(name, value)``, with value being automatically
+ xml-encoded.
+
+ Example::
+
+ def test_function(record_property):
+ record_property("example_key", 1)
"""
request.node.warn(
code='C3',
diff --git a/_pytest/logging.py b/_pytest/logging.py
index 7234bdeb0..902872e45 100644
--- a/_pytest/logging.py
+++ b/_pytest/logging.py
@@ -176,6 +176,10 @@ class LogCaptureHandler(logging.StreamHandler):
self.records.append(record)
logging.StreamHandler.emit(self, record)
+ def reset(self):
+ self.records = []
+ self.stream = py.io.TextIO()
+
class LogCaptureFixture(object):
"""Provides access and control of log capturing."""
@@ -197,6 +201,9 @@ class LogCaptureFixture(object):
@property
def handler(self):
+ """
+ :rtype: LogCaptureHandler
+ """
return self._item.catch_log_handler
def get_records(self, when):
@@ -239,8 +246,8 @@ class LogCaptureFixture(object):
return [(r.name, r.levelno, r.getMessage()) for r in self.records]
def clear(self):
- """Reset the list of log records."""
- self.handler.records = []
+ """Reset the list of log records and the captured log text."""
+ self.handler.reset()
def set_level(self, level, logger=None):
"""Sets the level for capturing of logs. The level will be restored to its previous value at the end of
@@ -285,6 +292,7 @@ def caplog(request):
* caplog.text() -> string containing formatted log output
* caplog.records() -> list of logging.LogRecord instances
* caplog.record_tuples() -> list of (logger_name, level, message) tuples
+ * caplog.clear() -> clear captured records and formatted log output string
"""
result = LogCaptureFixture(request.node)
yield result
diff --git a/_pytest/mark/__init__.py b/_pytest/mark/__init__.py
index f22db5820..51540dbd7 100644
--- a/_pytest/mark/__init__.py
+++ b/_pytest/mark/__init__.py
@@ -20,6 +20,21 @@ class MarkerError(Exception):
def param(*values, **kw):
+ """Specify a parameter in a `pytest.mark.parametrize`_ call.
+
+ .. code-block:: python
+
+ @pytest.mark.parametrize("test_input,expected", [
+ ("3+5", 8),
+ pytest.param("6*9", 42, marks=pytest.mark.xfail),
+ ])
+ def test_eval(test_input, expected):
+ assert eval(test_input) == expected
+
+ :param values: variable args of the values of the parameter set, in order.
+ :keyword marks: a single mark or a list of marks to be applied to this parameter set.
+ :keyword str id: the id to attribute to this parameter set.
+ """
return ParameterSet.param(*values, **kw)
diff --git a/_pytest/monkeypatch.py b/_pytest/monkeypatch.py
index c402213e8..c82ffd053 100644
--- a/_pytest/monkeypatch.py
+++ b/_pytest/monkeypatch.py
@@ -113,7 +113,7 @@ class MonkeyPatch(object):
For convenience you can specify a string as ``target`` which
will be interpreted as a dotted import path, with the last part
being the attribute name. Example:
- ``monkeypatch.setattr("os.getcwd", lambda x: "/")``
+ ``monkeypatch.setattr("os.getcwd", lambda: "/")``
would set the ``getcwd`` function of the ``os`` module.
The ``raising`` value determines if the setattr should fail
diff --git a/_pytest/python.py b/_pytest/python.py
index cdcfed49b..f9f17afd7 100644
--- a/_pytest/python.py
+++ b/_pytest/python.py
@@ -717,7 +717,7 @@ class CallSpec2(object):
class Metafunc(fixtures.FuncargnamesCompatAttr):
"""
- Metafunc objects are passed to the ``pytest_generate_tests`` hook.
+ Metafunc objects are passed to the :func:`pytest_generate_tests <_pytest.hookspec.pytest_generate_tests>` hook.
They help to inspect a test function and to generate tests according to
test configuration or values specified in the class or module where a
test function is defined.
diff --git a/_pytest/python_api.py b/_pytest/python_api.py
index 9de4dd2a8..69ae6ed0e 100644
--- a/_pytest/python_api.py
+++ b/_pytest/python_api.py
@@ -564,8 +564,9 @@ def raises(expected_exception, *args, **kwargs):
The string will be evaluated using the same ``locals()`` and ``globals()``
at the moment of the ``raises`` call.
- .. autoclass:: _pytest._code.ExceptionInfo
- :members:
+ .. currentmodule:: _pytest._code
+
+ Consult the API of ``excinfo`` objects: :class:`ExceptionInfo`.
.. note::
Similar to caught exception objects in Python, explicitly clearing
diff --git a/_pytest/recwarn.py b/_pytest/recwarn.py
index 4fceb10a7..ab0f79c75 100644
--- a/_pytest/recwarn.py
+++ b/_pytest/recwarn.py
@@ -16,10 +16,7 @@ from _pytest.outcomes import fail
@yield_fixture
def recwarn():
- """Return a WarningsRecorder instance that provides these methods:
-
- * ``pop(category=None)``: return last warning matching the category.
- * ``clear()``: clear list of warnings
+ """Return a :class:`WarningsRecorder` instance that records all warnings emitted by test functions.
See http://docs.python.org/library/warnings.html for information
on warning categories.
@@ -88,11 +85,11 @@ class _DeprecatedCallContext(object):
def warns(expected_warning, *args, **kwargs):
"""Assert that code raises a particular class of warning.
- Specifically, the input @expected_warning can be a warning class or
- tuple of warning classes, and the code must return that warning
- (if a single class) or one of those warnings (if a tuple).
+ Specifically, the parameter ``expected_warning`` can be a warning class or
+ sequence of warning classes, and the inside the ``with`` block must issue a warning of that class or
+ classes.
- This helper produces a list of ``warnings.WarningMessage`` objects,
+ This helper produces a list of :class:`warnings.WarningMessage` objects,
one for each warning raised.
This function can be used as a context manager, or any of the other ways
diff --git a/_pytest/tmpdir.py b/_pytest/tmpdir.py
index 66b4a2d2f..315ead302 100644
--- a/_pytest/tmpdir.py
+++ b/_pytest/tmpdir.py
@@ -116,6 +116,8 @@ def tmpdir(request, tmpdir_factory):
created as a sub directory of the base temporary
directory. The returned object is a `py.path.local`_
path object.
+
+ .. _`py.path.local`: https://py.readthedocs.io/en/latest/path.html
"""
name = request.node.name
name = re.sub(r"[\W]", "_", name)