commit
67ad0fa364
184
CHANGELOG.rst
184
CHANGELOG.rst
|
@ -8,6 +8,186 @@
|
|||
|
||||
.. towncrier release notes start
|
||||
|
||||
Pytest 3.3.0 (2017-11-23)
|
||||
=========================
|
||||
|
||||
Deprecations and Removals
|
||||
-------------------------
|
||||
|
||||
- Pytest no longer supports Python **2.6** and **3.3**. Those Python versions
|
||||
are EOL for some time now and incur maintenance and compatibility costs on
|
||||
the pytest core team, and following up with the rest of the community we
|
||||
decided that they will no longer be supported starting on this version. Users
|
||||
which still require those versions should pin pytest to ``<3.3``. (`#2812
|
||||
<https://github.com/pytest-dev/pytest/issues/2812>`_)
|
||||
|
||||
- Remove internal ``_preloadplugins()`` function. This removal is part of the
|
||||
``pytest_namespace()`` hook deprecation. (`#2236
|
||||
<https://github.com/pytest-dev/pytest/issues/2236>`_)
|
||||
|
||||
- Internally change ``CallSpec2`` to have a list of marks instead of a broken
|
||||
mapping of keywords. This removes the keywords attribute of the internal
|
||||
``CallSpec2`` class. (`#2672
|
||||
<https://github.com/pytest-dev/pytest/issues/2672>`_)
|
||||
|
||||
- Remove ParameterSet.deprecated_arg_dict - its not a public api and the lack
|
||||
of the underscore was a naming error. (`#2675
|
||||
<https://github.com/pytest-dev/pytest/issues/2675>`_)
|
||||
|
||||
- Remove the internal multi-typed attribute ``Node._evalskip`` and replace it
|
||||
with the boolean ``Node._skipped_by_mark``. (`#2767
|
||||
<https://github.com/pytest-dev/pytest/issues/2767>`_)
|
||||
|
||||
Features
|
||||
--------
|
||||
|
||||
- ``pytest_fixture_post_finalizer`` hook can now receive a ``request``
|
||||
argument. (`#2124 <https://github.com/pytest-dev/pytest/issues/2124>`_)
|
||||
|
||||
- Replace the old introspection code in compat.py that determines the available
|
||||
arguments of fixtures with inspect.signature on Python 3 and
|
||||
funcsigs.signature on Python 2. This should respect ``__signature__``
|
||||
declarations on functions. (`#2267
|
||||
<https://github.com/pytest-dev/pytest/issues/2267>`_)
|
||||
|
||||
- Report tests with global ``pytestmark`` variable only once. (`#2549
|
||||
<https://github.com/pytest-dev/pytest/issues/2549>`_)
|
||||
|
||||
- Now pytest displays the total progress percentage while running tests. The
|
||||
previous output style can be set by configuring the ``console_output_style``
|
||||
setting to ``classic``. (`#2657 <https://github.com/pytest-dev/pytest/issues/2657>`_)
|
||||
|
||||
- Match ``warns`` signature to ``raises`` by adding ``match`` keyword. (`#2708
|
||||
<https://github.com/pytest-dev/pytest/issues/2708>`_)
|
||||
|
||||
- Pytest now captures and displays output from the standard `logging` module.
|
||||
The user can control the logging level to be captured by specifying options
|
||||
in ``pytest.ini``, the command line and also during individual tests using
|
||||
markers. Also, a ``caplog`` fixture is available that enables users to test
|
||||
the captured log during specific tests (similar to ``capsys`` for example).
|
||||
For more information, please see the `logging docs
|
||||
<https://docs.pytest.org/en/latest/logging.html>`_. This feature was
|
||||
introduced by merging the popular `pytest-catchlog
|
||||
<https://pypi.org/project/pytest-catchlog/>`_ plugin, thanks to `Thomas Hisch
|
||||
<https://github.com/thisch>`_. Be advised that during the merging the
|
||||
backward compatibility interface with the defunct ``pytest-capturelog`` has
|
||||
been dropped. (`#2794 <https://github.com/pytest-dev/pytest/issues/2794>`_)
|
||||
|
||||
- Add ``allow_module_level`` kwarg to ``pytest.skip()``, enabling to skip the
|
||||
whole module. (`#2808 <https://github.com/pytest-dev/pytest/issues/2808>`_)
|
||||
|
||||
- Allow setting ``file_or_dir``, ``-c``, and ``-o`` in PYTEST_ADDOPTS. (`#2824
|
||||
<https://github.com/pytest-dev/pytest/issues/2824>`_)
|
||||
|
||||
- Return stdout/stderr capture results as a ``namedtuple``, so ``out`` and
|
||||
``err`` can be accessed by attribute. (`#2879
|
||||
<https://github.com/pytest-dev/pytest/issues/2879>`_)
|
||||
|
||||
- Add ``capfdbinary``, a version of ``capfd`` which returns bytes from
|
||||
``readouterr()``. (`#2923
|
||||
<https://github.com/pytest-dev/pytest/issues/2923>`_)
|
||||
|
||||
- Add ``capsysbinary`` a version of ``capsys`` which returns bytes from
|
||||
``readouterr()``. (`#2934
|
||||
<https://github.com/pytest-dev/pytest/issues/2934>`_)
|
||||
|
||||
- Implement feature to skip ``setup.py`` files when run with
|
||||
``--doctest-modules``. (`#502
|
||||
<https://github.com/pytest-dev/pytest/issues/502>`_)
|
||||
|
||||
|
||||
Bug Fixes
|
||||
---------
|
||||
|
||||
- Resume output capturing after ``capsys/capfd.disabled()`` context manager.
|
||||
(`#1993 <https://github.com/pytest-dev/pytest/issues/1993>`_)
|
||||
|
||||
- ``pytest_fixture_setup`` and ``pytest_fixture_post_finalizer`` hooks are now
|
||||
called for all ``conftest.py`` files. (`#2124
|
||||
<https://github.com/pytest-dev/pytest/issues/2124>`_)
|
||||
|
||||
- If an exception happens while loading a plugin, pytest no longer hides the
|
||||
original traceback. In python2 it will show the original traceback with a new
|
||||
message that explains in which plugin. In python3 it will show 2 canonized
|
||||
exceptions, the original exception while loading the plugin in addition to an
|
||||
exception that PyTest throws about loading a plugin. (`#2491
|
||||
<https://github.com/pytest-dev/pytest/issues/2491>`_)
|
||||
|
||||
- ``capsys`` and ``capfd`` can now be used by other fixtures. (`#2709
|
||||
<https://github.com/pytest-dev/pytest/issues/2709>`_)
|
||||
|
||||
- Internal ``pytester`` plugin properly encodes ``bytes`` arguments to
|
||||
``utf-8``. (`#2738 <https://github.com/pytest-dev/pytest/issues/2738>`_)
|
||||
|
||||
- ``testdir`` now uses use the same method used by ``tmpdir`` to create its
|
||||
temporary directory. This changes the final structure of the ``testdir``
|
||||
directory slightly, but should not affect usage in normal scenarios and
|
||||
avoids a number of potential problems. (`#2751
|
||||
<https://github.com/pytest-dev/pytest/issues/2751>`_)
|
||||
|
||||
- Pytest no longer complains about warnings with unicode messages being
|
||||
non-ascii compatible even for ascii-compatible messages. As a result of this,
|
||||
warnings with unicode messages are converted first to an ascii representation
|
||||
for safety. (`#2809 <https://github.com/pytest-dev/pytest/issues/2809>`_)
|
||||
|
||||
- Change return value of pytest command when ``--maxfail`` is reached from
|
||||
``2`` (interrupted) to ``1`` (failed). (`#2845
|
||||
<https://github.com/pytest-dev/pytest/issues/2845>`_)
|
||||
|
||||
- Fix issue in assertion rewriting which could lead it to rewrite modules which
|
||||
should not be rewritten. (`#2939
|
||||
<https://github.com/pytest-dev/pytest/issues/2939>`_)
|
||||
|
||||
- Handle marks without description in ``pytest.ini``. (`#2942
|
||||
<https://github.com/pytest-dev/pytest/issues/2942>`_)
|
||||
|
||||
|
||||
Trivial/Internal Changes
|
||||
------------------------
|
||||
|
||||
- pytest now depends on `attrs <https://pypi.org/project/attrs/>`_ for internal
|
||||
structures to ease code maintainability. (`#2641
|
||||
<https://github.com/pytest-dev/pytest/issues/2641>`_)
|
||||
|
||||
- Refactored internal Python 2/3 compatibility code to use ``six``. (`#2642
|
||||
<https://github.com/pytest-dev/pytest/issues/2642>`_)
|
||||
|
||||
- Stop vendoring ``pluggy`` - we're missing out on its latest changes for not
|
||||
much benefit (`#2719 <https://github.com/pytest-dev/pytest/issues/2719>`_)
|
||||
|
||||
- Internal refactor: simplify ascii string escaping by using the
|
||||
backslashreplace error handler in newer Python 3 versions. (`#2734
|
||||
<https://github.com/pytest-dev/pytest/issues/2734>`_)
|
||||
|
||||
- Remove unnecessary mark evaluator in unittest plugin (`#2767
|
||||
<https://github.com/pytest-dev/pytest/issues/2767>`_)
|
||||
|
||||
- Calls to ``Metafunc.addcall`` now emit a deprecation warning. This function
|
||||
is scheduled to be removed in ``pytest-4.0``. (`#2876
|
||||
<https://github.com/pytest-dev/pytest/issues/2876>`_)
|
||||
|
||||
- Internal move of the parameterset extraction to a more maintainable place.
|
||||
(`#2877 <https://github.com/pytest-dev/pytest/issues/2877>`_)
|
||||
|
||||
- Internal refactoring to simplify scope node lookup. (`#2910
|
||||
<https://github.com/pytest-dev/pytest/issues/2910>`_)
|
||||
|
||||
- Configure ``pytest`` to prevent pip from installing pytest in unsupported
|
||||
Python versions. (`#2922
|
||||
<https://github.com/pytest-dev/pytest/issues/2922>`_)
|
||||
|
||||
|
||||
Pytest 3.2.5 (2017-11-15)
|
||||
=========================
|
||||
|
||||
Bug Fixes
|
||||
---------
|
||||
|
||||
- Remove ``py<1.5`` restriction from ``pytest`` as this can cause version
|
||||
conflicts in some installations. (`#2926
|
||||
<https://github.com/pytest-dev/pytest/issues/2926>`_)
|
||||
|
||||
|
||||
Pytest 3.2.4 (2017-11-13)
|
||||
=========================
|
||||
|
||||
|
@ -28,6 +208,8 @@ Bug Fixes
|
|||
failed example in the docstring is < 9. (`#2882
|
||||
<https://github.com/pytest-dev/pytest/issues/2882>`_)
|
||||
|
||||
- Match fixture paths against actual path segments in order to avoid matching folders which share a prefix.
|
||||
(`#2836 <https://github.com/pytest-dev/pytest/issues/2836>`_)
|
||||
|
||||
Improved Documentation
|
||||
----------------------
|
||||
|
@ -179,7 +361,7 @@ Deprecations and Removals
|
|||
-------------------------
|
||||
|
||||
- ``pytest.approx`` no longer supports ``>``, ``>=``, ``<`` and ``<=``
|
||||
operators to avoid surprising/inconsistent behavior. See `the docs
|
||||
operators to avoid surprising/inconsistent behavior. See `the approx docs
|
||||
<https://docs.pytest.org/en/latest/builtin.html#pytest.approx>`_ for more
|
||||
information. (`#2003 <https://github.com/pytest-dev/pytest/issues/2003>`_)
|
||||
|
||||
|
|
|
@ -168,7 +168,7 @@ class AssertionRewritingHook(object):
|
|||
return True
|
||||
|
||||
for marked in self._must_rewrite:
|
||||
if name.startswith(marked):
|
||||
if name == marked or name.startswith(marked + '.'):
|
||||
state.trace("matched marked file %r (from %r)" % (name, marked))
|
||||
return True
|
||||
|
||||
|
|
|
@ -242,6 +242,10 @@ class PytestPluginManager(PluginManager):
|
|||
return opts
|
||||
|
||||
def register(self, plugin, name=None):
|
||||
if name == 'pytest_catchlog':
|
||||
self._warn('pytest-catchlog plugin has been merged into the core, '
|
||||
'please remove it from your requirements.')
|
||||
return
|
||||
ret = super(PytestPluginManager, self).register(plugin, name)
|
||||
if ret:
|
||||
self.hook.pytest_plugin_registered.call_historic(
|
||||
|
@ -931,7 +935,7 @@ class Config(object):
|
|||
fslocation=fslocation, nodeid=nodeid))
|
||||
|
||||
def get_terminal_writer(self):
|
||||
return self.pluginmanager.get_plugin("terminalreporter").writer
|
||||
return self.pluginmanager.get_plugin("terminalreporter")._tw
|
||||
|
||||
def pytest_cmdline_parse(self, pluginmanager, args):
|
||||
# REF1 assert self == pluginmanager.config, (self, pluginmanager.config)
|
||||
|
|
|
@ -83,7 +83,7 @@ def _enter_pdb(node, excinfo, rep):
|
|||
# XXX we re-use the TerminalReporter's terminalwriter
|
||||
# because this seems to avoid some encoding related troubles
|
||||
# for not completely clear reasons.
|
||||
tw = node.config.pluginmanager.getplugin("terminalreporter").writer
|
||||
tw = node.config.pluginmanager.getplugin("terminalreporter")._tw
|
||||
tw.line()
|
||||
tw.sep(">", "traceback")
|
||||
rep.toterminal(tw)
|
||||
|
|
|
@ -107,7 +107,7 @@ def pytest_cmdline_main(config):
|
|||
|
||||
def showhelp(config):
|
||||
reporter = config.pluginmanager.get_plugin('terminalreporter')
|
||||
tw = reporter.writer
|
||||
tw = reporter._tw
|
||||
tw.write(config._parser.optparser.format_help())
|
||||
tw.line()
|
||||
tw.line()
|
||||
|
|
|
@ -141,7 +141,9 @@ def pytest_cmdline_main(config):
|
|||
config._do_configure()
|
||||
tw = _pytest.config.create_terminal_writer(config)
|
||||
for line in config.getini("markers"):
|
||||
name, rest = line.split(":", 1)
|
||||
parts = line.split(":", 1)
|
||||
name = parts[0]
|
||||
rest = parts[1] if len(parts) == 2 else ''
|
||||
tw.write("@pytest.mark.%s:" % name, bold=True)
|
||||
tw.line(rest)
|
||||
tw.line()
|
||||
|
@ -298,7 +300,7 @@ class MarkGenerator:
|
|||
pass
|
||||
self._markers = values = set()
|
||||
for line in self._config.getini("markers"):
|
||||
marker, _ = line.split(":", 1)
|
||||
marker = line.split(":", 1)[0]
|
||||
marker = marker.rstrip()
|
||||
x = marker.split("(", 1)[0]
|
||||
values.add(x)
|
||||
|
|
|
@ -25,7 +25,7 @@ def pytest_configure(config):
|
|||
if tr is not None:
|
||||
# pastebin file will be utf-8 encoded binary file
|
||||
config._pastebinfile = tempfile.TemporaryFile('w+b')
|
||||
oldwrite = tr.writer.write
|
||||
oldwrite = tr._tw.write
|
||||
|
||||
def tee_write(s, **kwargs):
|
||||
oldwrite(s, **kwargs)
|
||||
|
@ -33,7 +33,7 @@ def pytest_configure(config):
|
|||
s = s.encode('utf-8')
|
||||
config._pastebinfile.write(s)
|
||||
|
||||
tr.writer.write = tee_write
|
||||
tr._tw.write = tee_write
|
||||
|
||||
|
||||
def pytest_unconfigure(config):
|
||||
|
@ -45,7 +45,7 @@ def pytest_unconfigure(config):
|
|||
del config._pastebinfile
|
||||
# undo our patching in the terminal reporter
|
||||
tr = config.pluginmanager.getplugin('terminalreporter')
|
||||
del tr.writer.__dict__['write']
|
||||
del tr._tw.__dict__['write']
|
||||
# write summary
|
||||
tr.write_sep("=", "Sending information to Paste Service")
|
||||
pastebinurl = create_new_paste(sessionlog)
|
||||
|
|
|
@ -308,9 +308,9 @@ def pytest_terminal_summary(terminalreporter):
|
|||
show_simple(terminalreporter, lines, 'passed', "PASSED %s")
|
||||
|
||||
if lines:
|
||||
tr.writer.sep("=", "short test summary info")
|
||||
tr._tw.sep("=", "short test summary info")
|
||||
for line in lines:
|
||||
tr.writer.line(line)
|
||||
tr._tw.line(line)
|
||||
|
||||
|
||||
def show_simple(terminalreporter, lines, stat, format):
|
||||
|
|
|
@ -8,7 +8,6 @@ import itertools
|
|||
import platform
|
||||
import sys
|
||||
import time
|
||||
import warnings
|
||||
|
||||
import pluggy
|
||||
import py
|
||||
|
@ -145,25 +144,15 @@ class TerminalReporter:
|
|||
self.startdir = py.path.local()
|
||||
if file is None:
|
||||
file = sys.stdout
|
||||
self._writer = _pytest.config.create_terminal_writer(config, file)
|
||||
self._screen_width = self.writer.fullwidth
|
||||
self._tw = _pytest.config.create_terminal_writer(config, file)
|
||||
self._screen_width = self._tw.fullwidth
|
||||
self.currentfspath = None
|
||||
self.reportchars = getreportopt(config)
|
||||
self.hasmarkup = self.writer.hasmarkup
|
||||
self.hasmarkup = self._tw.hasmarkup
|
||||
self.isatty = file.isatty()
|
||||
self._progress_items_reported = 0
|
||||
self._show_progress_info = self.config.getini('console_output_style') == 'progress'
|
||||
|
||||
@property
|
||||
def writer(self):
|
||||
return self._writer
|
||||
|
||||
@property
|
||||
def _tw(self):
|
||||
warnings.warn(DeprecationWarning('TerminalReporter._tw is deprecated, use TerminalReporter.writer instead'),
|
||||
stacklevel=2)
|
||||
return self.writer
|
||||
|
||||
def hasopt(self, char):
|
||||
char = {'xfailed': 'x', 'skipped': 's'}.get(char, char)
|
||||
return char in self.reportchars
|
||||
|
@ -175,33 +164,33 @@ class TerminalReporter:
|
|||
self._write_progress_information_filling_space()
|
||||
self.currentfspath = fspath
|
||||
fspath = self.startdir.bestrelpath(fspath)
|
||||
self.writer.line()
|
||||
self.writer.write(fspath + " ")
|
||||
self.writer.write(res)
|
||||
self._tw.line()
|
||||
self._tw.write(fspath + " ")
|
||||
self._tw.write(res)
|
||||
|
||||
def write_ensure_prefix(self, prefix, extra="", **kwargs):
|
||||
if self.currentfspath != prefix:
|
||||
self.writer.line()
|
||||
self._tw.line()
|
||||
self.currentfspath = prefix
|
||||
self.writer.write(prefix)
|
||||
self._tw.write(prefix)
|
||||
if extra:
|
||||
self.writer.write(extra, **kwargs)
|
||||
self._tw.write(extra, **kwargs)
|
||||
self.currentfspath = -2
|
||||
self._write_progress_information_filling_space()
|
||||
|
||||
def ensure_newline(self):
|
||||
if self.currentfspath:
|
||||
self.writer.line()
|
||||
self._tw.line()
|
||||
self.currentfspath = None
|
||||
|
||||
def write(self, content, **markup):
|
||||
self.writer.write(content, **markup)
|
||||
self._tw.write(content, **markup)
|
||||
|
||||
def write_line(self, line, **markup):
|
||||
if not isinstance(line, six.text_type):
|
||||
line = six.text_type(line, errors="replace")
|
||||
self.ensure_newline()
|
||||
self.writer.line(line, **markup)
|
||||
self._tw.line(line, **markup)
|
||||
|
||||
def rewrite(self, line, **markup):
|
||||
"""
|
||||
|
@ -214,22 +203,22 @@ class TerminalReporter:
|
|||
"""
|
||||
erase = markup.pop('erase', False)
|
||||
if erase:
|
||||
fill_count = self.writer.fullwidth - len(line) - 1
|
||||
fill_count = self._tw.fullwidth - len(line) - 1
|
||||
fill = ' ' * fill_count
|
||||
else:
|
||||
fill = ''
|
||||
line = str(line)
|
||||
self.writer.write("\r" + line + fill, **markup)
|
||||
self._tw.write("\r" + line + fill, **markup)
|
||||
|
||||
def write_sep(self, sep, title=None, **markup):
|
||||
self.ensure_newline()
|
||||
self.writer.sep(sep, title, **markup)
|
||||
self._tw.sep(sep, title, **markup)
|
||||
|
||||
def section(self, title, sep="=", **kw):
|
||||
self.writer.sep(sep, title, **kw)
|
||||
self._tw.sep(sep, title, **kw)
|
||||
|
||||
def line(self, msg, **kw):
|
||||
self.writer.line(msg, **kw)
|
||||
self._tw.line(msg, **kw)
|
||||
|
||||
def pytest_internalerror(self, excrepr):
|
||||
for line in six.text_type(excrepr).split("\n"):
|
||||
|
@ -282,7 +271,7 @@ class TerminalReporter:
|
|||
if not running_xdist and self.showfspath:
|
||||
self.write_fspath_result(rep.nodeid, letter)
|
||||
else:
|
||||
self.writer.write(letter)
|
||||
self._tw.write(letter)
|
||||
self._write_progress_if_past_edge()
|
||||
else:
|
||||
if markup is None:
|
||||
|
@ -299,13 +288,13 @@ class TerminalReporter:
|
|||
self.write_ensure_prefix(line, word, **markup)
|
||||
else:
|
||||
self.ensure_newline()
|
||||
self.writer.write("[%s]" % rep.node.gateway.id)
|
||||
self._tw.write("[%s]" % rep.node.gateway.id)
|
||||
if self._show_progress_info:
|
||||
self.writer.write(self._get_progress_information_message() + " ", cyan=True)
|
||||
self._tw.write(self._get_progress_information_message() + " ", cyan=True)
|
||||
else:
|
||||
self.writer.write(' ')
|
||||
self.writer.write(word, **markup)
|
||||
self.writer.write(" " + line)
|
||||
self._tw.write(' ')
|
||||
self._tw.write(word, **markup)
|
||||
self._tw.write(" " + line)
|
||||
self.currentfspath = -2
|
||||
|
||||
def _write_progress_if_past_edge(self):
|
||||
|
@ -316,10 +305,10 @@ class TerminalReporter:
|
|||
self._write_progress_information_filling_space()
|
||||
return
|
||||
|
||||
past_edge = self.writer.chars_on_current_line + self._PROGRESS_LENGTH + 1 >= self._screen_width
|
||||
past_edge = self._tw.chars_on_current_line + self._PROGRESS_LENGTH + 1 >= self._screen_width
|
||||
if past_edge:
|
||||
msg = self._get_progress_information_message()
|
||||
self.writer.write(msg + '\n', cyan=True)
|
||||
self._tw.write(msg + '\n', cyan=True)
|
||||
|
||||
_PROGRESS_LENGTH = len(' [100%]')
|
||||
|
||||
|
@ -331,7 +320,7 @@ class TerminalReporter:
|
|||
if not self._show_progress_info:
|
||||
return
|
||||
msg = self._get_progress_information_message()
|
||||
fill = ' ' * (self.writer.fullwidth - self.writer.chars_on_current_line - len(msg) - 1)
|
||||
fill = ' ' * (self._tw.fullwidth - self._tw.chars_on_current_line - len(msg) - 1)
|
||||
self.write(fill + msg, cyan=True)
|
||||
|
||||
def pytest_collection(self):
|
||||
|
@ -418,9 +407,9 @@ class TerminalReporter:
|
|||
if self.config.option.collectonly:
|
||||
self._printcollecteditems(session.items)
|
||||
if self.stats.get('failed'):
|
||||
self.writer.sep("!", "collection failures")
|
||||
self._tw.sep("!", "collection failures")
|
||||
for rep in self.stats.get('failed'):
|
||||
rep.toterminal(self.writer)
|
||||
rep.toterminal(self._tw)
|
||||
return 1
|
||||
return 0
|
||||
lines = self.config.hook.pytest_report_collectionfinish(
|
||||
|
@ -438,12 +427,12 @@ class TerminalReporter:
|
|||
name = item.nodeid.split('::', 1)[0]
|
||||
counts[name] = counts.get(name, 0) + 1
|
||||
for name, count in sorted(counts.items()):
|
||||
self.writer.line("%s: %d" % (name, count))
|
||||
self._tw.line("%s: %d" % (name, count))
|
||||
else:
|
||||
for item in items:
|
||||
nodeid = item.nodeid
|
||||
nodeid = nodeid.replace("::()::", "::")
|
||||
self.writer.line(nodeid)
|
||||
self._tw.line(nodeid)
|
||||
return
|
||||
stack = []
|
||||
indent = ""
|
||||
|
@ -458,13 +447,13 @@ class TerminalReporter:
|
|||
# if col.name == "()":
|
||||
# continue
|
||||
indent = (len(stack) - 1) * " "
|
||||
self.writer.line("%s%s" % (indent, col))
|
||||
self._tw.line("%s%s" % (indent, col))
|
||||
|
||||
@pytest.hookimpl(hookwrapper=True)
|
||||
def pytest_sessionfinish(self, exitstatus):
|
||||
outcome = yield
|
||||
outcome.get_result()
|
||||
self.writer.line("")
|
||||
self._tw.line("")
|
||||
summary_exit_codes = (
|
||||
EXIT_OK, EXIT_TESTSFAILED, EXIT_INTERRUPTED, EXIT_USAGEERROR,
|
||||
EXIT_NOTESTSCOLLECTED)
|
||||
|
@ -494,10 +483,10 @@ class TerminalReporter:
|
|||
self.write_sep("!", msg)
|
||||
if "KeyboardInterrupt" in msg:
|
||||
if self.config.option.fulltrace:
|
||||
excrepr.toterminal(self.writer)
|
||||
excrepr.toterminal(self._tw)
|
||||
else:
|
||||
self.writer.line("to show a full traceback on KeyboardInterrupt use --fulltrace", yellow=True)
|
||||
excrepr.reprcrash.toterminal(self.writer)
|
||||
self._tw.line("to show a full traceback on KeyboardInterrupt use --fulltrace", yellow=True)
|
||||
excrepr.reprcrash.toterminal(self._tw)
|
||||
|
||||
def _locationline(self, nodeid, fspath, lineno, domain):
|
||||
def mkrel(nodeid):
|
||||
|
@ -554,13 +543,13 @@ class TerminalReporter:
|
|||
|
||||
self.write_sep("=", "warnings summary", yellow=True, bold=False)
|
||||
for location, warning_records in grouped:
|
||||
self.writer.line(str(location) or '<undetermined location>')
|
||||
self._tw.line(str(location) or '<undetermined location>')
|
||||
for w in warning_records:
|
||||
lines = w.message.splitlines()
|
||||
indented = '\n'.join(' ' + x for x in lines)
|
||||
self.writer.line(indented)
|
||||
self.writer.line()
|
||||
self.writer.line('-- Docs: http://doc.pytest.org/en/latest/warnings.html')
|
||||
self._tw.line(indented)
|
||||
self._tw.line()
|
||||
self._tw.line('-- Docs: http://doc.pytest.org/en/latest/warnings.html')
|
||||
|
||||
def summary_passes(self):
|
||||
if self.config.option.tbstyle != "no":
|
||||
|
@ -577,10 +566,10 @@ class TerminalReporter:
|
|||
def print_teardown_sections(self, rep):
|
||||
for secname, content in rep.sections:
|
||||
if 'teardown' in secname:
|
||||
self.writer.sep('-', secname)
|
||||
self._tw.sep('-', secname)
|
||||
if content[-1:] == "\n":
|
||||
content = content[:-1]
|
||||
self.writer.line(content)
|
||||
self._tw.line(content)
|
||||
|
||||
def summary_failures(self):
|
||||
if self.config.option.tbstyle != "no":
|
||||
|
@ -620,12 +609,12 @@ class TerminalReporter:
|
|||
self._outrep_summary(rep)
|
||||
|
||||
def _outrep_summary(self, rep):
|
||||
rep.toterminal(self.writer)
|
||||
rep.toterminal(self._tw)
|
||||
for secname, content in rep.sections:
|
||||
self.writer.sep("-", secname)
|
||||
self._tw.sep("-", secname)
|
||||
if content[-1:] == "\n":
|
||||
content = content[:-1]
|
||||
self.writer.line(content)
|
||||
self._tw.line(content)
|
||||
|
||||
def summary_stats(self):
|
||||
session_duration = time.time() - self._sessionstarttime
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
Resume output capturing after ``capsys/capfd.disabled()`` context manager.
|
|
@ -1 +0,0 @@
|
|||
``pytest_fixture_setup`` and ``pytest_fixture_post_finalizer`` hooks are now called for all ``conftest.py`` files.
|
|
@ -1 +0,0 @@
|
|||
``pytest_fixture_post_finalizer`` hook can now receive a ``request`` argument.
|
|
@ -1 +0,0 @@
|
|||
- Remove internal ``_preloadplugins()`` function. This removal is part of the ``pytest_namespace()`` hook deprecation.
|
|
@ -1,4 +0,0 @@
|
|||
Replace the old introspection code in compat.py that determines the
|
||||
available arguments of fixtures with inspect.signature on Python 3 and
|
||||
funcsigs.signature on Python 2. This should respect __signature__
|
||||
declarations on functions.
|
|
@ -1,4 +0,0 @@
|
|||
If an exception happens while loading a plugin, pytest no longer hides the original traceback.
|
||||
In python2 it will show the original traceback with a new message that explains in which plugin.
|
||||
In python3 it will show 2 canonized exceptions, the original exception while loading the plugin
|
||||
in addition to an exception that PyTest throws about loading a plugin.
|
|
@ -1 +0,0 @@
|
|||
Report only once tests with global ``pytestmark`` variable.
|
|
@ -1 +0,0 @@
|
|||
pytest now depends on `attrs <https://pypi.org/project/attrs/>`_ for internal structures to ease code maintainability.
|
|
@ -1 +0,0 @@
|
|||
Refactored internal Python 2/3 compatibility code to use ``six``.
|
|
@ -1 +0,0 @@
|
|||
Now pytest displays the total progress percentage while running tests. The previous output style can be set by setting the new ``console_output_style`` to ``classic``.
|
|
@ -1,2 +0,0 @@
|
|||
Internally change ``CallSpec2`` to have a list of marks instead of a broken mapping of keywords.
|
||||
This removes the keywords attribute of the internal ``CallSpec2`` class.
|
|
@ -1 +0,0 @@
|
|||
remove ParameterSet.deprecated_arg_dict - its not a public api and the lack of the underscore was a naming error.
|
|
@ -1 +0,0 @@
|
|||
Match ``warns`` signature to ``raises`` by adding ``match`` keyworkd.
|
|
@ -1 +0,0 @@
|
|||
``capsys`` and ``capfd`` can now be used by other fixtures.
|
|
@ -1 +0,0 @@
|
|||
Stop vendoring ``pluggy`` - we're missing out on it's latest changes for not much benefit
|
|
@ -1 +0,0 @@
|
|||
Internal refactor: simplify ascii string escaping by using the backslashreplace error handler in newer Python 3 versions.
|
|
@ -1 +0,0 @@
|
|||
Internal ``pytester`` plugin properly encodes ``bytes`` arguments to ``utf-8``.
|
|
@ -1 +0,0 @@
|
|||
``testdir`` now uses use the same method used by ``tmpdir`` to create its temporary directory. This changes the final structure of the ``testdir`` directory slightly, but should not affect usage in normal scenarios and avoids a number of potential problems.
|
|
@ -1 +0,0 @@
|
|||
Remove the internal multi-typed attribute ``Node._evalskip`` and replace it with the boolean ``Node._skipped_by_mark``.
|
|
@ -1 +0,0 @@
|
|||
* remove unnecessary mark evaluator in unittest plugin
|
|
@ -1,3 +0,0 @@
|
|||
Pytest now captures and displays output from the standard `logging` module. The user can control the logging level to be captured by specifying options in ``pytest.ini``, the command line and also during individual tests using markers. Also, a ``caplog`` fixture is available that enables users to test the captured log during specific tests (similar to ``capsys`` for example). For more information, please see the `docs <https://docs.pytest.org/en/latest/logging.html>`_.
|
||||
|
||||
This feature was introduced by merging the popular `pytest-catchlog <https://pypi.org/project/pytest-catchlog/>`_ plugin, thanks to `Thomas Hisch <https://github.com/thisch>`_. Be advised that during the merging the backward compatibility interface with the defunct ``pytest-capturelog`` has been dropped.
|
|
@ -1 +0,0 @@
|
|||
``TerminalReporter._tw`` has been deprecated in favor of ``TerminalReporter.writer`` and will be removed in a future version. Also, ``TerminalReporter.writer`` is now read-only.
|
|
@ -1 +0,0 @@
|
|||
Add ``allow_module_level`` kwarg to ``pytest.skip()``, enabling to skip the whole module.
|
|
@ -1 +0,0 @@
|
|||
Pytest no longer complains about warnings with unicode messages being non-ascii compatible even for ascii-compatible messages. As a result of this, warnings with unicode messages are converted first to an ascii representation for safety.
|
|
@ -1 +0,0 @@
|
|||
Pytest no longer supports Python **2.6** and **3.3**. Those Python versions are EOL for some time now and incurr maintanance and compatibility costs on the pytest core team, and following up with the rest of the community we decided that they will no longer be supported starting on this version. Users which still require those versions should pin pytest to ``<3.3``.
|
|
@ -1 +0,0 @@
|
|||
Allow setting ``file_or_dir``, ``-c``, and ``-o`` in PYTEST_ADDOPTS.
|
|
@ -1 +0,0 @@
|
|||
Match fixture paths against actual path segments in order to avoid matching folders which share a prefix.
|
|
@ -1 +0,0 @@
|
|||
Change return value of pytest command when ``--maxfail`` is reached from ``2`` (interrupted) to ``1`` (failed).
|
|
@ -1 +0,0 @@
|
|||
Calls to ``Metafunc.addcall`` now emit a deprecation warning. This function is scheduled to be removed in ``pytest-4.0``.
|
|
@ -1 +0,0 @@
|
|||
Internal move of the parameterset extraction to a more maintainable place.
|
|
@ -1 +0,0 @@
|
|||
Return stdout/stderr capture results as a ``namedtuple``, so ``out`` and ``err`` can be accessed by attribute.
|
|
@ -1 +0,0 @@
|
|||
Internal refactoring to simplify scope node lookup.
|
|
@ -1 +0,0 @@
|
|||
Configure ``pytest`` to prevent pip from installing pytest in unsupported Python versions.
|
|
@ -1,2 +0,0 @@
|
|||
Add ``capfdbinary`` a version of ``capfd`` which returns bytes from
|
||||
``readouterr()``.
|
|
@ -1,2 +0,0 @@
|
|||
Add ``capsysbinary`` a version of ``capsys`` which returns bytes from
|
||||
``readouterr()``.
|
|
@ -1 +0,0 @@
|
|||
Implement feature to skip ``setup.py`` files when ran with ``--doctest-modules``.
|
|
@ -6,6 +6,8 @@ Release announcements
|
|||
:maxdepth: 2
|
||||
|
||||
|
||||
release-3.3.0
|
||||
release-3.2.5
|
||||
release-3.2.4
|
||||
release-3.2.3
|
||||
release-3.2.2
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
pytest-3.2.5
|
||||
=======================================
|
||||
|
||||
pytest 3.2.5 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
|
||||
|
||||
|
||||
Happy testing,
|
||||
The pytest Development Team
|
|
@ -0,0 +1,50 @@
|
|||
pytest-3.3.0
|
||||
=======================================
|
||||
|
||||
The pytest team is proud to announce the 3.3.0 release!
|
||||
|
||||
pytest is a mature Python testing tool with more than a 1600 tests
|
||||
against itself, passing on many different interpreters and platforms.
|
||||
|
||||
This release contains a number of bugs fixes and improvements, so users are encouraged
|
||||
to take a look at the CHANGELOG:
|
||||
|
||||
http://doc.pytest.org/en/latest/changelog.html
|
||||
|
||||
For complete documentation, please visit:
|
||||
|
||||
http://docs.pytest.org
|
||||
|
||||
As usual, you can upgrade from pypi via:
|
||||
|
||||
pip install -U pytest
|
||||
|
||||
Thanks to all who contributed to this release, among them:
|
||||
|
||||
* Anthony Sottile
|
||||
* Bruno Oliveira
|
||||
* Ceridwen
|
||||
* Daniel Hahler
|
||||
* Dirk Thomas
|
||||
* Dmitry Malinovsky
|
||||
* Florian Bruhin
|
||||
* George Y. Kussumoto
|
||||
* Hugo
|
||||
* Jesús Espino
|
||||
* Joan Massich
|
||||
* Ofir
|
||||
* OfirOshir
|
||||
* Ronny Pfannschmidt
|
||||
* Samuel Dion-Girardeau
|
||||
* Srinivas Reddy Thatiparthy
|
||||
* Sviatoslav Abakumov
|
||||
* Tarcisio Fischer
|
||||
* Thomas Hisch
|
||||
* Tyler Goodlet
|
||||
* hugovk
|
||||
* je
|
||||
* prokaktus
|
||||
|
||||
|
||||
Happy testing,
|
||||
The Pytest Development Team
|
|
@ -10,3 +10,96 @@ With the pytest 3.0 release we introduced a clear communication scheme for when
|
|||
To communicate changes we are already issuing deprecation warnings, but they are not displayed by default. In pytest 3.0 we changed the default setting so that pytest deprecation warnings are displayed if not explicitly silenced (with ``--disable-pytest-warnings``).
|
||||
|
||||
We will only remove deprecated functionality in major releases (e.g. if we deprecate something in 3.0 we will remove it in 4.0), and keep it around for at least two minor releases (e.g. if we deprecate something in 3.9 and 4.0 is the next release, we will not remove it in 4.0 but in 5.0).
|
||||
|
||||
|
||||
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.
|
||||
|
||||
Following our deprecation policy, we should aim to keep features for *at least* two minor versions after it was considered deprecated.
|
||||
|
||||
|
||||
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.
|
|
@ -411,11 +411,8 @@ is to be run with different sets of arguments for its three arguments:
|
|||
Running it results in some skips if we don't have all the python interpreters installed and otherwise runs all combinations (5 interpreters times 5 interpreters times 3 objects to serialize/deserialize)::
|
||||
|
||||
. $ pytest -rs -q multipython.py
|
||||
ssssssssssssssssssssssss... [100%]
|
||||
========================= short test summary info ==========================
|
||||
SKIP [12] $REGENDOC_TMPDIR/CWD/multipython.py:24: 'python2.7' not found
|
||||
SKIP [12] $REGENDOC_TMPDIR/CWD/multipython.py:24: 'python3.4' not found
|
||||
3 passed, 24 skipped in 0.12 seconds
|
||||
........................... [100%]
|
||||
27 passed in 0.12 seconds
|
||||
|
||||
Indirect parametrization of optional implementations/imports
|
||||
--------------------------------------------------------------------
|
||||
|
|
2
setup.py
2
setup.py
|
@ -53,7 +53,7 @@ def main():
|
|||
# if _PYTEST_SETUP_SKIP_PLUGGY_DEP is set, skip installing pluggy;
|
||||
# used by tox.ini to test with pluggy master
|
||||
if '_PYTEST_SETUP_SKIP_PLUGGY_DEP' not in os.environ:
|
||||
install_requires.append('pluggy>=0.5,<0.6')
|
||||
install_requires.append('pluggy>=0.5,<0.7')
|
||||
if has_environment_marker_support():
|
||||
extras_require[':python_version<"3.0"'] = ['funcsigs']
|
||||
extras_require[':sys_platform=="win32"'] = ['colorama']
|
||||
|
|
|
@ -4,10 +4,9 @@ Invoke tasks to help with pytest development and release process.
|
|||
|
||||
import invoke
|
||||
|
||||
from . import generate, vendoring
|
||||
from . import generate
|
||||
|
||||
|
||||
ns = invoke.Collection(
|
||||
generate,
|
||||
vendoring
|
||||
)
|
||||
|
|
|
@ -99,3 +99,16 @@ def test_metafunc_addcall_deprecated(testdir):
|
|||
"*Metafunc.addcall is deprecated*",
|
||||
"*2 passed, 2 warnings*",
|
||||
])
|
||||
|
||||
|
||||
def test_pytest_catchlog_deprecated(testdir):
|
||||
testdir.makepyfile("""
|
||||
def test_func(pytestconfig):
|
||||
pytestconfig.pluginmanager.register(None, 'pytest_catchlog')
|
||||
""")
|
||||
res = testdir.runpytest()
|
||||
assert res.ret == 0
|
||||
res.stdout.fnmatch_lines([
|
||||
"*pytest-catchlog plugin has been merged into the core*",
|
||||
"*1 passed, 1 warnings*",
|
||||
])
|
||||
|
|
|
@ -129,6 +129,24 @@ class TestImportHookInstallation(object):
|
|||
result = testdir.runpytest_subprocess('--assert=rewrite')
|
||||
assert result.ret == 0
|
||||
|
||||
def test_pytest_plugins_rewrite_module_names_correctly(self, testdir):
|
||||
"""Test that we match files correctly when they are marked for rewriting (#2939)."""
|
||||
contents = {
|
||||
'conftest.py': """
|
||||
pytest_plugins = "ham"
|
||||
""",
|
||||
'ham.py': "",
|
||||
'hamster.py': "",
|
||||
'test_foo.py': """
|
||||
def test_foo(pytestconfig):
|
||||
assert pytestconfig.pluginmanager.rewrite_hook.find_module('ham') is not None
|
||||
assert pytestconfig.pluginmanager.rewrite_hook.find_module('hamster') is None
|
||||
""",
|
||||
}
|
||||
testdir.makepyfile(**contents)
|
||||
result = testdir.runpytest_subprocess('--assert=rewrite')
|
||||
assert result.ret == 0
|
||||
|
||||
@pytest.mark.parametrize('mode', ['plain', 'rewrite'])
|
||||
@pytest.mark.parametrize('plugin_state', ['development', 'installed'])
|
||||
def test_installed_plugin_rewrite(self, testdir, mode, plugin_state):
|
||||
|
|
|
@ -161,11 +161,13 @@ def test_markers_option(testdir):
|
|||
markers =
|
||||
a1: this is a webtest marker
|
||||
a1some: another marker
|
||||
nodescription
|
||||
""")
|
||||
result = testdir.runpytest("--markers", )
|
||||
result.stdout.fnmatch_lines([
|
||||
"*a1*this is a webtest*",
|
||||
"*a1some*another marker",
|
||||
"*nodescription*",
|
||||
])
|
||||
|
||||
|
||||
|
@ -186,6 +188,21 @@ def test_ini_markers_whitespace(testdir):
|
|||
rec.assertoutcome(passed=1)
|
||||
|
||||
|
||||
def test_marker_without_description(testdir):
|
||||
testdir.makefile(".cfg", setup="""
|
||||
[tool:pytest]
|
||||
markers=slow
|
||||
""")
|
||||
testdir.makeconftest("""
|
||||
import pytest
|
||||
pytest.mark.xfail('FAIL')
|
||||
""")
|
||||
ftdir = testdir.mkdir("ft1_dummy")
|
||||
testdir.tmpdir.join("conftest.py").move(ftdir.join("conftest.py"))
|
||||
rec = testdir.runpytest_subprocess("--strict")
|
||||
rec.assert_outcomes()
|
||||
|
||||
|
||||
def test_markers_option_with_plugin_in_current_dir(testdir):
|
||||
testdir.makeconftest('pytest_plugins = "flip_flop"')
|
||||
testdir.makepyfile(flip_flop="""\
|
||||
|
@ -576,7 +593,7 @@ class TestFunctional(object):
|
|||
request.applymarker(pytest.mark.hello)
|
||||
def pytest_terminal_summary(terminalreporter):
|
||||
values = terminalreporter.stats['passed']
|
||||
terminalreporter.writer.line("keyword: %s" % values[0].keywords)
|
||||
terminalreporter._tw.line("keyword: %s" % values[0].keywords)
|
||||
""")
|
||||
testdir.makepyfile("""
|
||||
def test_func(arg):
|
||||
|
|
|
@ -219,7 +219,7 @@ class TestTerminal(object):
|
|||
f = py.io.TextIO()
|
||||
monkeypatch.setattr(f, 'isatty', lambda *args: True)
|
||||
tr = TerminalReporter(config, f)
|
||||
tr.writer.fullwidth = 10
|
||||
tr._tw.fullwidth = 10
|
||||
tr.write('hello')
|
||||
tr.rewrite('hey', erase=True)
|
||||
assert f.getvalue() == 'hello' + '\r' + 'hey' + (6 * ' ')
|
||||
|
|
Loading…
Reference in New Issue