Compare commits

..

40 Commits
2.6.2 ... 2.6.3

Author SHA1 Message Date
holger krekel
b57545bd21 fix doc release version 2014-09-24 14:59:55 +02:00
holger krekel
2eef674615 regen and fix some docs (tox -e regen)
bump versions, depend on already released py-1.4.25
2014-09-24 14:46:56 +02:00
holger krekel
bf7c5ea32c add changelog: check xfail/skip also with non-python function test items. Thanks
Floris Bruynooghe.
2014-09-24 13:55:55 +02:00
Floris Bruynooghe
62b8712ca9 Let xfail work on non-python Items
For some reason xfail was only implemented on non-python Item
instances.  This removes this guard which means plugins creating new
items can raise pytest.xfail.Exception and it will work as expected.
2014-09-23 23:55:26 +01:00
holger krekel
68105b3ae4 mention Wolfang wrt pytest_enter_pdb 2014-09-23 15:43:46 +02:00
holger krekel
be503f1c43 Merged in wosc/pytest (pull request #204)
Introduce pytest_enter_pdb hook
2014-09-23 14:04:47 +02:00
holger krekel
5abca55412 Merged in nicoddemus/pytest (pull request #203)
fix issue575: xunit-xml reporting collection errors as failures
2014-09-22 19:25:34 +02:00
holger krekel
79d2edcbff Merged in flub/pytest (pull request #207)
Show both user assertion msg as explanation (issue549)
2014-09-22 19:16:10 +02:00
holger krekel
e2c6a77f06 Merged in davidszotten/pytest/stop_leaking_fds (pull request #206)
stop leaking file descriptors
2014-09-22 15:02:48 +02:00
David Szotten
35eec99d41 stop leaking file descriptors
tripps --lsof on os x but not on linux. there's possibly a bug in the leak
detector (not investigated here)

--HG--
branch : stop_leaking_fds
2014-09-22 13:56:07 +01:00
holger krekel
e4fde1048b Merged in davidszotten/pytest/dontreadfrominput-encoding (pull request #205)
add `encoding` attr to DontReadFromInput
2014-09-22 13:34:50 +02:00
David Szotten
bc4eecbbac add encoding attr to DontReadFromInput
required by https://docs.python.org/2/library/stdtypes.html#file.encoding

and used e.g. by ipdb at _import_ time

--HG--
branch : dontreadfrominput-encoding
2014-09-22 12:19:27 +01:00
Wolfgang Schnerring
1408c9f077 Introduce pytest_enter_pdb hook 2014-09-18 14:58:42 +02:00
Bruno Oliveira
418607846a fix issue575: xunit-xml reporting collection errors as failures 2014-09-15 22:04:46 -03:00
holger krekel
6aa5611ae5 fix issue584: fix py3 syntax errors for example/special.txt.
Thanks Bruno Oliveira.
2014-09-15 15:04:09 +02:00
holger krekel
c5c9fb93aa fix link to pylib 2014-09-15 14:04:31 +02:00
Anatoly Bubenkov
86961291e5 add badges to the readme 2014-09-15 11:07:28 +00:00
Anatoly Bubenkov
7c1dadee51 Merged in conftest-nodeid (pull request #202)
fix conftest related fixture visibility issue
2014-09-15 13:04:07 +02:00
Anatoly Bubenkov
b16553e34e Close branch conftest-nodeid
--HG--
branch : conftest-nodeid
2014-09-15 13:04:07 +02:00
holger krekel
b6dcfd4377 fix conftest related fixture visibility issue: when running with a
CWD outside a test package pytest would get fixture discovery wrong.
Thanks to Wolfgang Schnerring for figuring out a reproducable example.

--HG--
branch : conftest-nodeid
2014-09-15 12:44:16 +02:00
holger krekel
1a80487e71 fix issue589: fix bad interaction with numpy and others when showing
exceptions.  check for precise "maximum recursion depth exceed" exception
instead of presuming any RuntimeError is that one (implemented in py dep)
Thanks Charles Cloud for analysing the issue.
2014-09-14 17:24:27 +02:00
holger krekel
488720da8d fix a broken link 2014-09-10 09:57:12 +02:00
holger krekel
0264121c10 fix issue587: claim only python2.6 compat in README/pypi project page, thanks sscarwell 2014-09-09 11:22:39 +02:00
Floris Bruynooghe
d2f448ecee Improve pytest.raises examples
Fixes issue #586.
2014-09-08 14:26:31 +01:00
Floris Bruynooghe
c692a0ee9c Remove jython from tested python versions
After testing with the jython 2.7 beta it seems it will require some
work to get jython back working.  So for now remove it from this list
so it doesn't get picked up by normal test runs.
2014-09-06 18:44:18 +01:00
Floris Bruynooghe
4063b7f8e0 Mention PR #194 in the changelog 2014-09-06 00:00:43 +01:00
Floris Bruynooghe
a8dfe34bfb Merged in uweschmitt/pytest/default (pull request #194) 2014-09-05 23:57:18 +01:00
Floris Bruynooghe
7d9d502a01 Use py3k compatible .__getattr__() code
From the python-dev thread it seemed like using
object.__getattribute__(self, 'name') is the cleanest way of
implementing a class wich uses .__getattr__() and should be
pickelable.  That only works on new-style classes so this also turns
HookProxy into a new-style class on py2.

This also re-writes the test to not use cPickle so it runs on py3k.
2014-09-05 23:55:14 +01:00
holger krekel
09a44f4cac fix issue582: fix setuptools example, thanks Laszlo Papp and Ronny
Pfannschmidt.
2014-09-05 15:34:01 +02:00
holger krekel
b14b9515a5 mention XXX regendoc for release process 2014-09-05 13:55:58 +02:00
holger krekel
2a504a5bcd regen docs for 2.6.2 2014-09-05 13:55:00 +02:00
holger krekel
dfcdf644fe Added tag 2.6.2 for changeset a4f25c5e6498 2014-09-05 13:47:48 +02:00
Floris Bruynooghe
7760cf1881 Fix doctest tox run
The new failures in the failure demo apparently affect the
doctests tox run.
2014-08-23 19:01:26 +02:00
Floris Bruynooghe
37bd1e03cb Show user assertion messages and instrospection together
User provided messages, or any valid expression given as second
argument to the assert statement, are now shown in addition to the
py.test introspection details.  Formerly any user provided message
would entirely replace the introspection details.

Fixes issue549.
2014-08-23 18:14:25 +02:00
uweschmitt
d1bde69c1e added smoke test for bug fixed in 3716:dc080608b6d1 2014-08-19 12:57:37 +02:00
uweschmitt
224b3a2eda hopefully final fix for strange infinite recursion bug 2014-08-11 12:57:47 +02:00
uweschmitt
5d024c7433 hopefully final fix for strange infinite recursion bug 2014-08-11 12:42:36 +02:00
uweschmitt
c0d1f3f7ef even better fix as replacement for last commit which was wrong 2014-08-07 17:17:05 +02:00
uweschmitt
9597d3dafe better fix as replacement for last commit 2014-08-07 16:56:45 +02:00
uweschmitt
f7282b84bd fixed strange infinite recursion bug 2014-08-07 16:13:12 +02:00
46 changed files with 1149 additions and 293 deletions

View File

@@ -70,3 +70,4 @@ a064ad64d167508a8e9e73766b1a4e6bd10c85db 2.5.0
60725b17a9d1af4100abb8be3f9f4ddf6262bf34 2.6.0
88af949b9611494e2c65d528f9e565b00fb7e8ca 2.6.0
a4f9639702baa3eb4f3b16e162f74f7b69f3f9e1 2.6.1
a4f25c5e649892b5cc746d21be971e4773478af9 2.6.2

View File

@@ -1,3 +1,30 @@
2.6.3
-----------
- fix issue575: xunit-xml was reporting collection errors as failures
instead of errors, thanks Oleg Sinyavskiy.
- fix issue582: fix setuptools example, thanks Laszlo Papp and Ronny
Pfannschmidt.
- Fix infinite recursion bug when pickling capture.EncodedFile, thanks
Uwe Schmitt.
- fix issue589: fix bad interaction with numpy and others when showing
exceptions. Check for precise "maximum recursion depth exceed" exception
instead of presuming any RuntimeError is that one (implemented in py
dep). Thanks Charles Cloud for analysing the issue.
- fix conftest related fixture visibility issue: when running with a
CWD outside a test package pytest would get fixture discovery wrong.
Thanks to Wolfgang Schnerring for figuring out a reproducable example.
- Introduce pytest_enter_pdb hook (needed e.g. by pytest_timeout to cancel the
timeout when interactively entering pdb). Thanks Wolfgang Schnerring.
- check xfail/skip also with non-python function test items. Thanks
Floris Bruynooghe.
2.6.2
-----------
@@ -23,6 +50,10 @@
other builds due to the extra argparse dependency. Fixes issue566.
Thanks sontek.
- Implement issue549: user-provided assertion messages now no longer
replace the py.test instrospection message but are shown in addition
to them.
2.6.1
-----------------------------------

View File

@@ -25,18 +25,21 @@ How to release pytest (draft)
which is ok (tox does not support skipping on
per-platform basis yet).
7. go to "doc/en" and upload docs with "make install"
7. XXX "regen docs" (not easy to do currently as it requires
a development version of the regendoc tool from ronny)
8. go to "doc/en" and upload docs with "make install"
(the latter requires ssh-login permissions on pytest.org
because it uses rsync). Note that the "install" target of
doc/en/Makefile defines where the rsync goes to, typically
to the "latest" section of pytest.org.
8. publish to pypi "devpi push pytest-2.6.2 pypi:NAME" where NAME
9. publish to pypi "devpi push pytest-2.6.2 pypi:NAME" where NAME
is the name of pypi.python.org as configured in your
~/.pypirc file -- it's the same you would use with
"setup.py upload -r NAME"
9. send release announcement to mailing lists:
10. send release announcement to mailing lists:
pytest-dev
testing-in-python

View File

@@ -1,3 +1,7 @@
.. image:: https://drone.io/bitbucket.org/hpk42/pytest/status.png
:target: https://drone.io/bitbucket.org/hpk42/pytest/latest
.. image:: https://pypip.in/v/pytest/badge.png
:target: https://crate.io/packages/pytest/
Documentation: http://pytest.org/latest/
@@ -19,8 +23,9 @@ scales to support complex functional testing. It provides
- multi-paradigm support: you can use ``pytest`` to run test suites based
on `unittest <http://pytest.org/latest/unittest.html>`_ (or trial),
`nose <http://pytest.org/latest/nose.html>`_
- single-source compatibility to Python2.5 all the way up to Python3.4,
PyPy-2.3 and Jython-2.5.1.
- single-source compatibility from Python2.6 all the way up to
Python3.4, PyPy-2.3, (jython-2.5 untested)
- many `external plugins <http://pytest.org/latest/plugins.html#installing-external-plugins-searching>`_.

View File

@@ -1,2 +1,2 @@
#
__version__ = '2.6.2'
__version__ = '2.6.3'

View File

@@ -57,7 +57,7 @@ class View(object):
def __getattr__(self, attr):
# attributes not found in the normal hierarchy rooted on View
# are looked up in the object's real class
return getattr(self.__obj__, attr)
return getattr(object.__getattribute__(self, '__obj__'), attr)
def __viewkey__(self):
return self.__obj__.__class__

View File

@@ -351,6 +351,33 @@ def _saferepr(obj):
from _pytest.assertion.util import format_explanation as _format_explanation # noqa
def _format_assertmsg(obj):
"""Format the custom assertion message given.
For strings this simply replaces newlines with '\n~' so that
util.format_explanation() will preserve them instead of escaping
newlines. For other objects py.io.saferepr() is used first.
"""
# reprlib appears to have a bug which means that if a string
# contains a newline it gets escaped, however if an object has a
# .__repr__() which contains newlines it does not get escaped.
# However in either case we want to preserve the newline.
if py.builtin._istext(obj) or py.builtin._isbytes(obj):
s = obj
is_repr = False
else:
s = py.io.saferepr(obj)
is_repr = True
if py.builtin._istext(s):
t = py.builtin.text
else:
t = py.builtin.bytes
s = s.replace(t("\n"), t("\n~"))
if is_repr:
s = s.replace(t("\\n"), t("\n~"))
return s
def _should_repr_global_name(obj):
return not hasattr(obj, "__name__") and not py.builtin.callable(obj)
@@ -419,6 +446,56 @@ def set_location(node, lineno, col_offset):
class AssertionRewriter(ast.NodeVisitor):
"""Assertion rewriting implementation.
The main entrypoint is to call .run() with an ast.Module instance,
this will then find all the assert statements and re-write them to
provide intermediate values and a detailed assertion error. See
http://pybites.blogspot.be/2011/07/behind-scenes-of-pytests-new-assertion.html
for an overview of how this works.
The entry point here is .run() which will iterate over all the
statenemts in an ast.Module and for each ast.Assert statement it
finds call .visit() with it. Then .visit_Assert() takes over and
is responsible for creating new ast statements to replace the
original assert statement: it re-writes the test of an assertion
to provide intermediate values and replace it with an if statement
which raises an assertion error with a detailed explanation in
case the expression is false.
For this .visit_Assert() uses the visitor pattern to visit all the
AST nodes of the ast.Assert.test field, each visit call returning
an AST node and the corresponding explanation string. During this
state is kept in several instance attributes:
:statements: All the AST statements which will replace the assert
statement.
:variables: This is populated by .variable() with each variable
used by the statements so that they can all be set to None at
the end of the statements.
:variable_counter: Counter to create new unique variables needed
by statements. Variables are created using .variable() and
have the form of "@py_assert0".
:on_failure: The AST statements which will be executed if the
assertion test fails. This is the code which will construct
the failure message and raises the AssertionError.
:explanation_specifiers: A dict filled by .explanation_param()
with %-formatting placeholders and their corresponding
expressions to use in the building of an assertion message.
This is used by .pop_format_context() to build a message.
:stack: A stack of the explanation_specifiers dicts maintained by
.push_format_context() and .pop_format_context() which allows
to build another %-formatted string while already building one.
This state is reset on every new assert statement visited and used
by the other visitors.
"""
def run(self, mod):
"""Find all assert statements in *mod* and rewrite them."""
@@ -500,15 +577,41 @@ class AssertionRewriter(ast.NodeVisitor):
return ast.Attribute(builtin_name, name, ast.Load())
def explanation_param(self, expr):
"""Return a new named %-formatting placeholder for expr.
This creates a %-formatting placeholder for expr in the
current formatting context, e.g. ``%(py0)s``. The placeholder
and expr are placed in the current format context so that it
can be used on the next call to .pop_format_context().
"""
specifier = "py" + str(next(self.variable_counter))
self.explanation_specifiers[specifier] = expr
return "%(" + specifier + ")s"
def push_format_context(self):
"""Create a new formatting context.
The format context is used for when an explanation wants to
have a variable value formatted in the assertion message. In
this case the value required can be added using
.explanation_param(). Finally .pop_format_context() is used
to format a string of %-formatted values as added by
.explanation_param().
"""
self.explanation_specifiers = {}
self.stack.append(self.explanation_specifiers)
def pop_format_context(self, expl_expr):
"""Format the %-formatted string with current format context.
The expl_expr should be an ast.Str instance constructed from
the %-placeholders created by .explanation_param(). This will
add the required code to format said string to .on_failure and
return the ast.Name instance of the formatted string.
"""
current = self.stack.pop()
if self.stack:
self.explanation_specifiers = self.stack[-1]
@@ -526,11 +629,15 @@ class AssertionRewriter(ast.NodeVisitor):
return res, self.explanation_param(self.display(res))
def visit_Assert(self, assert_):
if assert_.msg:
# There's already a message. Don't mess with it.
return [assert_]
"""Return the AST statements to replace the ast.Assert instance.
This re-writes the test of an assertion to provide
intermediate values and replace it with an if statement which
raises an assertion error with a detailed explanation in case
the expression is false.
"""
self.statements = []
self.cond_chain = ()
self.variables = []
self.variable_counter = itertools.count()
self.stack = []
@@ -542,8 +649,13 @@ class AssertionRewriter(ast.NodeVisitor):
body = self.on_failure
negation = ast.UnaryOp(ast.Not(), top_condition)
self.statements.append(ast.If(negation, body, []))
explanation = "assert " + explanation
template = ast.Str(explanation)
if assert_.msg:
assertmsg = self.helper('format_assertmsg', assert_.msg)
explanation = "\n>assert " + explanation
else:
assertmsg = ast.Str("")
explanation = "assert " + explanation
template = ast.BinOp(assertmsg, ast.Add(), ast.Str(explanation))
msg = self.pop_format_context(template)
fmt = self.helper("format_explanation", msg)
err_name = ast.Name("AssertionError", ast.Load())

View File

@@ -73,7 +73,7 @@ def _split_explanation(explanation):
raw_lines = (explanation or u('')).split('\n')
lines = [raw_lines[0]]
for l in raw_lines[1:]:
if l.startswith('{') or l.startswith('}') or l.startswith('~'):
if l and l[0] in ['{', '}', '~', '>']:
lines.append(l)
else:
lines[-1] += '\\n' + l
@@ -103,13 +103,14 @@ def _format_lines(lines):
stackcnt.append(0)
result.append(u(' +') + u(' ')*(len(stack)-1) + s + line[1:])
elif line.startswith('}'):
assert line.startswith('}')
stack.pop()
stackcnt.pop()
result[stack[-1]] += line[1:]
else:
assert line.startswith('~')
result.append(u(' ')*len(stack) + line[1:])
assert line[0] in ['~', '>']
stack[-1] += 1
indent = len(stack) if line.startswith('~') else len(stack) - 1
result.append(u(' ')*indent + line[1:])
assert len(stack) == 1
return result

View File

@@ -238,7 +238,7 @@ class EncodedFile(object):
self.write(data)
def __getattr__(self, name):
return getattr(self.buffer, name)
return getattr(object.__getattribute__(self, "buffer"), name)
class MultiCapture(object):
@@ -428,6 +428,9 @@ class DontReadFromInput:
because in automated test runs it is better to crash than
hang indefinitely.
"""
encoding = None
def read(self, *args):
raise IOError("reading from stdin while output is captured")
readline = read

View File

@@ -262,3 +262,5 @@ def pytest_exception_interact(node, call, report):
that is not an internal exception like "skip.Exception".
"""
def pytest_enter_pdb():
""" called upon pdb.set_trace()"""

View File

@@ -129,10 +129,10 @@ class LogXML(object):
self.failed += 1
self._write_captured_output(report)
def append_collect_failure(self, report):
def append_collect_error(self, report):
#msg = str(report.longrepr.reprtraceback.extraline)
self.append(Junit.failure(bin_xml_escape(report.longrepr),
message="collection failure"))
self.append(Junit.error(bin_xml_escape(report.longrepr),
message="collection failure"))
self.errors += 1
def append_collect_skipped(self, report):
@@ -181,7 +181,7 @@ class LogXML(object):
if not report.passed:
self._opentestcase(report)
if report.failed:
self.append_collect_failure(report)
self.append_collect_error(report)
else:
self.append_collect_skipped(report)

View File

@@ -153,13 +153,14 @@ def pytest_ignore_collect(path, config):
ignore_paths.extend([py.path.local(x) for x in excludeopt])
return path in ignore_paths
class HookProxy:
class HookProxy(object):
def __init__(self, fspath, config):
self.fspath = fspath
self.config = config
def __getattr__(self, name):
hookmethod = getattr(self.config.hook, name)
config = object.__getattribute__(self, "config")
hookmethod = getattr(config.hook, name)
def call_matching_hooks(**kwargs):
plugins = self.config._getmatchingplugins(self.fspath)

View File

@@ -42,6 +42,7 @@ class pytestPDB:
tw = py.io.TerminalWriter()
tw.line()
tw.sep(">", "PDB set_trace (IO-capturing turned off)")
self._pluginmanager.hook.pytest_enter_pdb()
pdb.Pdb().set_trace(frame)

View File

@@ -1611,10 +1611,15 @@ class FixtureManager:
except AttributeError:
pass
else:
# construct the base nodeid which is later used to check
# what fixtures are visible for particular tests (as denoted
# by their test id)
if p.basename.startswith("conftest.py"):
nodeid = p.dirpath().relto(self.session.fspath)
nodeid = self.session.fspath.bestrelpath(p.dirpath())
if p.sep != "/":
nodeid = nodeid.replace(p.sep, "/")
if nodeid == ".":
nodeid = ""
self.parsefactories(plugin, nodeid)
self._seenplugins.add(plugin)

View File

@@ -58,6 +58,7 @@ class MarkEvaluator:
@property
def holder(self):
return self.item.keywords.get(self.name, None)
def __bool__(self):
return bool(self.holder)
__nonzero__ = __bool__
@@ -136,8 +137,6 @@ class MarkEvaluator:
@pytest.mark.tryfirst
def pytest_runtest_setup(item):
if not isinstance(item, pytest.Function):
return
evalskip = MarkEvaluator(item, 'skipif')
if evalskip.istrue():
pytest.skip(evalskip.getexplanation())
@@ -155,8 +154,6 @@ def check_xfail_no_run(item):
pytest.xfail("[NOTRUN] " + evalxfail.getexplanation())
def pytest_runtest_makereport(__multicall__, item, call):
if not isinstance(item, pytest.Function):
return
# unitttest special case, see setting of _unexpectedsuccess
if hasattr(item, '_unexpectedsuccess'):
rep = __multicall__.execute()

View File

@@ -0,0 +1,52 @@
pytest-2.6.3: fixes and little improvements
===========================================================================
pytest is a mature Python testing tool with more than a 1100 tests
against itself, passing on many different interpreters and platforms.
This release is drop-in compatible to 2.5.2 and 2.6.X.
See below for the changes and see docs at:
http://pytest.org
As usual, you can upgrade from pypi via::
pip install -U pytest
Thanks to all who contributed, among them:
Floris Bruynooghe
Oleg Sinyavskiy
Uwe Schmitt
Charles Cloud
Wolfgang Schnerring
have fun,
holger krekel
Changes 2.6.3
======================
- fix issue575: xunit-xml was reporting collection errors as failures
instead of errors, thanks Oleg Sinyavskiy.
- fix issue582: fix setuptools example, thanks Laszlo Papp and Ronny
Pfannschmidt.
- Fix infinite recursion bug when pickling capture.EncodedFile, thanks
Uwe Schmitt.
- fix issue589: fix bad interaction with numpy and others when showing
exceptions. Check for precise "maximum recursion depth exceed" exception
instead of presuming any RuntimeError is that one (implemented in py
dep). Thanks Charles Cloud for analysing the issue.
- fix conftest related fixture visibility issue: when running with a
CWD outside a test package pytest would get fixture discovery wrong.
Thanks to Wolfgang Schnerring for figuring out a reproducable example.
- Introduce pytest_enter_pdb hook (needed e.g. by pytest_timeout to cancel the
timeout when interactively entering pdb). Thanks Wolfgang Schnerring.
- check xfail/skip also with non-python function test items. Thanks
Floris Bruynooghe.

View File

@@ -26,7 +26,7 @@ you will see the return value of the function call::
$ py.test test_assert1.py
=========================== test session starts ============================
platform linux -- Python 3.4.0 -- py-1.4.23 -- pytest-2.6.1
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
collected 1 items
test_assert1.py F
@@ -66,20 +66,23 @@ In order to write assertions about raised exceptions, you can use
``pytest.raises`` as a context manager like this::
import pytest
with pytest.raises(ZeroDivisionError):
1 / 0
def test_zero_division():
with pytest.raises(ZeroDivisionError):
1 / 0
and if you need to have access to the actual exception info you may use::
with pytest.raises(RuntimeError) as excinfo:
def f():
def test_recursion_depth():
with pytest.raises(RuntimeError) as excinfo:
def f():
f()
f()
f()
# do checks related to excinfo.type, excinfo.value, excinfo.traceback
assert 'maximum recursion' in str(excinfo.value)
``excinfo`` is a `py.code.ExceptionInfo`_ instance, which is a wrapper around
the actual exception raised.
the actual exception raised. The main attributes of interest are
``.type``, ``.value`` and ``.traceback``.
.. _py.code.ExceptionInfo:
http://pylib.readthedocs.org/en/latest/code.html#py-code-exceptioninfo
@@ -132,7 +135,7 @@ if you run this module::
$ py.test test_assert2.py
=========================== test session starts ============================
platform linux -- Python 3.4.0 -- py-1.4.23 -- pytest-2.6.1
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
collected 1 items
test_assert2.py F

View File

@@ -64,7 +64,7 @@ of the failing function and hide the other one::
$ py.test
=========================== test session starts ============================
platform linux -- Python 3.4.0 -- py-1.4.23 -- pytest-2.6.1
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
collected 2 items
test_module.py .F
@@ -78,7 +78,7 @@ of the failing function and hide the other one::
test_module.py:9: AssertionError
-------------------------- Captured stdout setup ---------------------------
setting up <function test_func2 at 0x2b5d6a81c9d8>
setting up <function test_func2 at 0x2b3173d7fbf8>
==================== 1 failed, 1 passed in 0.01 seconds ====================
Accessing captured output from a test function

View File

@@ -18,7 +18,7 @@
# The full version, including alpha/beta/rc tags.
# The short X.Y version.
version = "2.6"
release = "2.6.2"
release = "2.6.3"
import sys, os

View File

@@ -44,12 +44,12 @@ then you can just invoke ``py.test`` without command line options::
$ py.test
=========================== test session starts ============================
platform linux -- Python 3.4.0 -- py-1.4.23 -- pytest-2.6.1
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
collected 1 items
mymodule.py .
========================= 1 passed in 0.06 seconds =========================
========================= 1 passed in 0.05 seconds =========================
It is possible to use fixtures using the ``getfixture`` helper::

View File

@@ -211,3 +211,27 @@ class TestMoreErrors:
finally:
x = 0
class TestCustomAssertMsg:
def test_single_line(self):
class A:
a = 1
b = 2
assert A.a == b, "A.a appears not to be b"
def test_multiline(self):
class A:
a = 1
b = 2
assert A.a == b, "A.a appears not to be b\n" \
"or does not appear to be b\none of those"
def test_custom_repr(self):
class JSON:
a = 1
def __repr__(self):
return "This is JSON\n{\n 'foo': 'bar'\n}"
a = JSON()
b = 2
assert a.a == b, a

View File

@@ -9,6 +9,6 @@ def test_failure_demo_fails_properly(testdir):
failure_demo.copy(testdir.tmpdir.join(failure_demo.basename))
result = testdir.runpytest(target)
result.stdout.fnmatch_lines([
"*39 failed*"
"*42 failed*"
])
assert result.ret != 0

View File

@@ -31,7 +31,7 @@ You can then restrict a test run to only run tests marked with ``webtest``::
$ py.test -v -m webtest
=========================== test session starts ============================
platform linux -- Python 3.4.0 -- py-1.4.23 -- pytest-2.6.1 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4
collecting ... collected 4 items
test_server.py::test_send_http PASSED
@@ -43,7 +43,7 @@ Or the inverse, running all tests except the webtest ones::
$ py.test -v -m "not webtest"
=========================== test session starts ============================
platform linux -- Python 3.4.0 -- py-1.4.23 -- pytest-2.6.1 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4
collecting ... collected 4 items
test_server.py::test_something_quick PASSED
@@ -62,7 +62,7 @@ tests based on their module, class, method, or function name::
$ py.test -v test_server.py::TestClass::test_method
=========================== test session starts ============================
platform linux -- Python 3.4.0 -- py-1.4.23 -- pytest-2.6.1 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4
collecting ... collected 5 items
test_server.py::TestClass::test_method PASSED
@@ -73,7 +73,7 @@ You can also select on the class::
$ py.test -v test_server.py::TestClass
=========================== test session starts ============================
platform linux -- Python 3.4.0 -- py-1.4.23 -- pytest-2.6.1 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4
collecting ... collected 4 items
test_server.py::TestClass::test_method PASSED
@@ -84,7 +84,7 @@ Or select multiple nodes::
$ py.test -v test_server.py::TestClass test_server.py::test_send_http
=========================== test session starts ============================
platform linux -- Python 3.4.0 -- py-1.4.23 -- pytest-2.6.1 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4
collecting ... collected 8 items
test_server.py::TestClass::test_method PASSED
@@ -120,7 +120,7 @@ select tests based on their names::
$ py.test -v -k http # running with the above defined example module
=========================== test session starts ============================
platform linux -- Python 3.4.0 -- py-1.4.23 -- pytest-2.6.1 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4
collecting ... collected 4 items
test_server.py::test_send_http PASSED
@@ -132,7 +132,7 @@ And you can also run all tests except the ones that match the keyword::
$ py.test -k "not send_http" -v
=========================== test session starts ============================
platform linux -- Python 3.4.0 -- py-1.4.23 -- pytest-2.6.1 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4
collecting ... collected 4 items
test_server.py::test_something_quick PASSED
@@ -140,13 +140,13 @@ And you can also run all tests except the ones that match the keyword::
test_server.py::TestClass::test_method PASSED
================= 1 tests deselected by '-knot send_http' ==================
================== 3 passed, 1 deselected in 0.01 seconds ==================
================== 3 passed, 1 deselected in 0.02 seconds ==================
Or to select "http" and "quick" tests::
$ py.test -k "http or quick" -v
=========================== test session starts ============================
platform linux -- Python 3.4.0 -- py-1.4.23 -- pytest-2.6.1 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4
collecting ... collected 4 items
test_server.py::test_send_http PASSED
@@ -326,7 +326,7 @@ the test needs::
$ py.test -E stage2
=========================== test session starts ============================
platform linux -- Python 3.4.0 -- py-1.4.23 -- pytest-2.6.1
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
collected 1 items
test_someenv.py s
@@ -337,7 +337,7 @@ and here is one that specifies exactly the environment needed::
$ py.test -E stage1
=========================== test session starts ============================
platform linux -- Python 3.4.0 -- py-1.4.23 -- pytest-2.6.1
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
collected 1 items
test_someenv.py .
@@ -455,12 +455,12 @@ then you will see two test skipped and two executed tests as expected::
$ py.test -rs # this option reports skip reasons
=========================== test session starts ============================
platform linux -- Python 3.4.0 -- py-1.4.23 -- pytest-2.6.1
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
collected 4 items
test_plat.py sss.
========================= short test summary info ==========================
SKIP [3] /tmp/doc-exec-238/conftest.py:12: cannot run on platform linux
SKIP [3] /tmp/doc-exec-224/conftest.py:12: cannot run on platform linux
=================== 1 passed, 3 skipped in 0.01 seconds ====================
@@ -468,7 +468,7 @@ Note that if you specify a platform via the marker-command line option like this
$ py.test -m linux2
=========================== test session starts ============================
platform linux -- Python 3.4.0 -- py-1.4.23 -- pytest-2.6.1
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
collected 4 items
test_plat.py s
@@ -519,7 +519,7 @@ We can now use the ``-m option`` to select one set::
$ py.test -m interface --tb=short
=========================== test session starts ============================
platform linux -- Python 3.4.0 -- py-1.4.23 -- pytest-2.6.1
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
collected 4 items
test_module.py FF
@@ -540,7 +540,7 @@ or to select both "event" and "interface" tests::
$ py.test -m "interface or event" --tb=short
=========================== test session starts ============================
platform linux -- Python 3.4.0 -- py-1.4.23 -- pytest-2.6.1
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
collected 4 items
test_module.py FFF

View File

@@ -27,7 +27,7 @@ now execute the test specification::
nonpython $ py.test test_simple.yml
=========================== test session starts ============================
platform linux -- Python 3.4.0 -- py-1.4.23 -- pytest-2.6.1
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
collected 2 items
test_simple.yml .F
@@ -56,7 +56,7 @@ consulted when reporting in ``verbose`` mode::
nonpython $ py.test -v
=========================== test session starts ============================
platform linux -- Python 3.4.0 -- py-1.4.23 -- pytest-2.6.1 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4
collecting ... collected 2 items
test_simple.yml::usecase: ok PASSED
@@ -74,7 +74,7 @@ interesting to just look at the collection tree::
nonpython $ py.test --collect-only
=========================== test session starts ============================
platform linux -- Python 3.4.0 -- py-1.4.23 -- pytest-2.6.1
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
collected 2 items
<YamlFile 'test_simple.yml'>
<YamlItem 'ok'>

View File

@@ -106,7 +106,7 @@ this is a fully self-contained example which you can run with::
$ py.test test_scenarios.py
=========================== test session starts ============================
platform linux -- Python 3.4.0 -- py-1.4.23 -- pytest-2.6.1
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
collected 4 items
test_scenarios.py ....
@@ -118,7 +118,7 @@ If you just collect tests you'll also nicely see 'advanced' and 'basic' as varia
$ py.test --collect-only test_scenarios.py
=========================== test session starts ============================
platform linux -- Python 3.4.0 -- py-1.4.23 -- pytest-2.6.1
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
collected 4 items
<Module 'test_scenarios.py'>
<Class 'TestSampleWithScenarios'>
@@ -182,7 +182,7 @@ Let's first see how it looks like at collection time::
$ py.test test_backends.py --collect-only
=========================== test session starts ============================
platform linux -- Python 3.4.0 -- py-1.4.23 -- pytest-2.6.1
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
collected 2 items
<Module 'test_backends.py'>
<Function 'test_db_initialized[d1]'>
@@ -197,7 +197,7 @@ And then when we run the test::
================================= FAILURES =================================
_________________________ test_db_initialized[d2] __________________________
db = <conftest.DB2 object at 0x2b83684b5eb8>
db = <conftest.DB2 object at 0x2b24a8545390>
def test_db_initialized(db):
# a dummy test
@@ -206,7 +206,7 @@ And then when we run the test::
E Failed: deliberately failing for demo purposes
test_backends.py:6: Failed
1 failed, 1 passed in 0.01 seconds
1 failed, 1 passed in 0.02 seconds
The first invocation with ``db == "DB1"`` passed while the second with ``db == "DB2"`` failed. Our ``db`` fixture function has instantiated each of the DB values during the setup phase while the ``pytest_generate_tests`` generated two according calls to the ``test_db_initialized`` during the collection phase.
@@ -251,16 +251,16 @@ argument sets to use for each test function. Let's run it::
$ py.test -q
F..
================================= FAILURES =================================
________________________ TestClass.test_equals[2-1] ________________________
________________________ TestClass.test_equals[1-2] ________________________
self = <test_parametrize.TestClass object at 0x2ae94130e390>, a = 1, b = 2
self = <test_parametrize.TestClass object at 0x2b0ed5d8cdd8>, a = 1, b = 2
def test_equals(self, a, b):
> assert a == b
E assert 1 == 2
test_parametrize.py:18: AssertionError
1 failed, 2 passed in 0.01 seconds
1 failed, 2 passed in 0.02 seconds
Indirect parametrization with multiple fixtures
--------------------------------------------------------------
@@ -279,12 +279,345 @@ 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)::
. $ py.test -rs -q multipython.py
ssssssssssssssssssssssssssssssssssss......sssssssss......ssssssssssssssssss
========================= short test summary info ==========================
SKIP [21] /home/hpk/p/pytest/doc/en/example/multipython.py:22: 'python2.5' not found
SKIP [21] /home/hpk/p/pytest/doc/en/example/multipython.py:22: 'python2.8' not found
SKIP [21] /home/hpk/p/pytest/doc/en/example/multipython.py:22: 'python2.4' not found
12 passed, 63 skipped in 0.65 seconds
..................FFFFFF...
================================= FAILURES =================================
________________ test_basic_objects[python3.4-python2.6-42] ________________
python1 = <multipython.Python object at 0x2b02a1bc79b0>
python2 = <multipython.Python object at 0x2b02a1bc7630>, obj = 42
@pytest.mark.parametrize("obj", [42, {}, {1:3},])
def test_basic_objects(python1, python2, obj):
python1.dumps(obj)
> python2.load_and_is_true("obj == %s" % obj)
multipython.py:51:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
multipython.py:46: in load_and_is_true
py.process.cmdexec("%s %s" %(self.pythonpath, loadfile))
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
cmd = '/home/hpk/bin/python2.6 /tmp/pytest-21/test_basic_objects_python3_4_p0/load.py'
def cmdexec(cmd):
""" return unicode output of executing 'cmd' in a separate process.
raise cmdexec.Error exeception if the command failed.
the exception will provide an 'err' attribute containing
the error-output from the command.
if the subprocess module does not provide a proper encoding/unicode strings
sys.getdefaultencoding() will be used, if that does not exist, 'UTF-8'.
"""
process = subprocess.Popen(cmd, shell=True,
universal_newlines=True,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = process.communicate()
if sys.version_info[0] < 3: # on py3 we get unicode strings, on py2 not
try:
default_encoding = sys.getdefaultencoding() # jython may not have it
except AttributeError:
default_encoding = sys.stdout.encoding or 'UTF-8'
out = unicode(out, process.stdout.encoding or default_encoding)
err = unicode(err, process.stderr.encoding or default_encoding)
status = process.poll()
if status:
> raise ExecutionFailed(status, status, cmd, out, err)
E py.process.cmdexec.Error: ExecutionFailed: 1 /home/hpk/bin/python2.6 /tmp/pytest-21/test_basic_objects_python3_4_p0/load.py
E Traceback (most recent call last):
E File "/tmp/pytest-21/test_basic_objects_python3_4_p0/load.py", line 4, in <module>
E obj = pickle.load(f)
E File "/usr/lib/python2.6/pickle.py", line 1370, in load
E return Unpickler(file).load()
E File "/usr/lib/python2.6/pickle.py", line 858, in load
E dispatch[key](self)
E File "/usr/lib/python2.6/pickle.py", line 886, in load_proto
E raise ValueError, "unsupported pickle protocol: %d" % proto
E ValueError: unsupported pickle protocol: 3
../../../.tox/regen/lib/python3.4/site-packages/py/_process/cmdexec.py:28: Error
--------------------------- Captured stdout call ---------------------------
/tmp/pytest-21/test_basic_objects_python3_4_p0/load.py
_______________ test_basic_objects[python3.4-python2.6-obj1] _______________
python1 = <multipython.Python object at 0x2b02a1b66f28>
python2 = <multipython.Python object at 0x2b02a1b66198>, obj = {}
@pytest.mark.parametrize("obj", [42, {}, {1:3},])
def test_basic_objects(python1, python2, obj):
python1.dumps(obj)
> python2.load_and_is_true("obj == %s" % obj)
multipython.py:51:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
multipython.py:46: in load_and_is_true
py.process.cmdexec("%s %s" %(self.pythonpath, loadfile))
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
cmd = '/home/hpk/bin/python2.6 /tmp/pytest-21/test_basic_objects_python3_4_p1/load.py'
def cmdexec(cmd):
""" return unicode output of executing 'cmd' in a separate process.
raise cmdexec.Error exeception if the command failed.
the exception will provide an 'err' attribute containing
the error-output from the command.
if the subprocess module does not provide a proper encoding/unicode strings
sys.getdefaultencoding() will be used, if that does not exist, 'UTF-8'.
"""
process = subprocess.Popen(cmd, shell=True,
universal_newlines=True,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = process.communicate()
if sys.version_info[0] < 3: # on py3 we get unicode strings, on py2 not
try:
default_encoding = sys.getdefaultencoding() # jython may not have it
except AttributeError:
default_encoding = sys.stdout.encoding or 'UTF-8'
out = unicode(out, process.stdout.encoding or default_encoding)
err = unicode(err, process.stderr.encoding or default_encoding)
status = process.poll()
if status:
> raise ExecutionFailed(status, status, cmd, out, err)
E py.process.cmdexec.Error: ExecutionFailed: 1 /home/hpk/bin/python2.6 /tmp/pytest-21/test_basic_objects_python3_4_p1/load.py
E Traceback (most recent call last):
E File "/tmp/pytest-21/test_basic_objects_python3_4_p1/load.py", line 4, in <module>
E obj = pickle.load(f)
E File "/usr/lib/python2.6/pickle.py", line 1370, in load
E return Unpickler(file).load()
E File "/usr/lib/python2.6/pickle.py", line 858, in load
E dispatch[key](self)
E File "/usr/lib/python2.6/pickle.py", line 886, in load_proto
E raise ValueError, "unsupported pickle protocol: %d" % proto
E ValueError: unsupported pickle protocol: 3
../../../.tox/regen/lib/python3.4/site-packages/py/_process/cmdexec.py:28: Error
--------------------------- Captured stdout call ---------------------------
/tmp/pytest-21/test_basic_objects_python3_4_p1/load.py
_______________ test_basic_objects[python3.4-python2.6-obj2] _______________
python1 = <multipython.Python object at 0x2b02a1bcd320>
python2 = <multipython.Python object at 0x2b02a1bcd358>, obj = {1: 3}
@pytest.mark.parametrize("obj", [42, {}, {1:3},])
def test_basic_objects(python1, python2, obj):
python1.dumps(obj)
> python2.load_and_is_true("obj == %s" % obj)
multipython.py:51:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
multipython.py:46: in load_and_is_true
py.process.cmdexec("%s %s" %(self.pythonpath, loadfile))
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
cmd = '/home/hpk/bin/python2.6 /tmp/pytest-21/test_basic_objects_python3_4_p2/load.py'
def cmdexec(cmd):
""" return unicode output of executing 'cmd' in a separate process.
raise cmdexec.Error exeception if the command failed.
the exception will provide an 'err' attribute containing
the error-output from the command.
if the subprocess module does not provide a proper encoding/unicode strings
sys.getdefaultencoding() will be used, if that does not exist, 'UTF-8'.
"""
process = subprocess.Popen(cmd, shell=True,
universal_newlines=True,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = process.communicate()
if sys.version_info[0] < 3: # on py3 we get unicode strings, on py2 not
try:
default_encoding = sys.getdefaultencoding() # jython may not have it
except AttributeError:
default_encoding = sys.stdout.encoding or 'UTF-8'
out = unicode(out, process.stdout.encoding or default_encoding)
err = unicode(err, process.stderr.encoding or default_encoding)
status = process.poll()
if status:
> raise ExecutionFailed(status, status, cmd, out, err)
E py.process.cmdexec.Error: ExecutionFailed: 1 /home/hpk/bin/python2.6 /tmp/pytest-21/test_basic_objects_python3_4_p2/load.py
E Traceback (most recent call last):
E File "/tmp/pytest-21/test_basic_objects_python3_4_p2/load.py", line 4, in <module>
E obj = pickle.load(f)
E File "/usr/lib/python2.6/pickle.py", line 1370, in load
E return Unpickler(file).load()
E File "/usr/lib/python2.6/pickle.py", line 858, in load
E dispatch[key](self)
E File "/usr/lib/python2.6/pickle.py", line 886, in load_proto
E raise ValueError, "unsupported pickle protocol: %d" % proto
E ValueError: unsupported pickle protocol: 3
../../../.tox/regen/lib/python3.4/site-packages/py/_process/cmdexec.py:28: Error
--------------------------- Captured stdout call ---------------------------
/tmp/pytest-21/test_basic_objects_python3_4_p2/load.py
________________ test_basic_objects[python3.4-python2.7-42] ________________
python1 = <multipython.Python object at 0x2b02a1bc78d0>
python2 = <multipython.Python object at 0x2b02a1bc7128>, obj = 42
@pytest.mark.parametrize("obj", [42, {}, {1:3},])
def test_basic_objects(python1, python2, obj):
python1.dumps(obj)
> python2.load_and_is_true("obj == %s" % obj)
multipython.py:51:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
multipython.py:46: in load_and_is_true
py.process.cmdexec("%s %s" %(self.pythonpath, loadfile))
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
cmd = '/home/hpk/bin/python2.7 /tmp/pytest-21/test_basic_objects_python3_4_p3/load.py'
def cmdexec(cmd):
""" return unicode output of executing 'cmd' in a separate process.
raise cmdexec.Error exeception if the command failed.
the exception will provide an 'err' attribute containing
the error-output from the command.
if the subprocess module does not provide a proper encoding/unicode strings
sys.getdefaultencoding() will be used, if that does not exist, 'UTF-8'.
"""
process = subprocess.Popen(cmd, shell=True,
universal_newlines=True,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = process.communicate()
if sys.version_info[0] < 3: # on py3 we get unicode strings, on py2 not
try:
default_encoding = sys.getdefaultencoding() # jython may not have it
except AttributeError:
default_encoding = sys.stdout.encoding or 'UTF-8'
out = unicode(out, process.stdout.encoding or default_encoding)
err = unicode(err, process.stderr.encoding or default_encoding)
status = process.poll()
if status:
> raise ExecutionFailed(status, status, cmd, out, err)
E py.process.cmdexec.Error: ExecutionFailed: 1 /home/hpk/bin/python2.7 /tmp/pytest-21/test_basic_objects_python3_4_p3/load.py
E Traceback (most recent call last):
E File "/tmp/pytest-21/test_basic_objects_python3_4_p3/load.py", line 4, in <module>
E obj = pickle.load(f)
E File "/usr/lib/python2.7/pickle.py", line 1378, in load
E return Unpickler(file).load()
E File "/usr/lib/python2.7/pickle.py", line 858, in load
E dispatch[key](self)
E File "/usr/lib/python2.7/pickle.py", line 886, in load_proto
E raise ValueError, "unsupported pickle protocol: %d" % proto
E ValueError: unsupported pickle protocol: 3
../../../.tox/regen/lib/python3.4/site-packages/py/_process/cmdexec.py:28: Error
--------------------------- Captured stdout call ---------------------------
/tmp/pytest-21/test_basic_objects_python3_4_p3/load.py
_______________ test_basic_objects[python3.4-python2.7-obj1] _______________
python1 = <multipython.Python object at 0x2b02a1bd2550>
python2 = <multipython.Python object at 0x2b02a1bd23c8>, obj = {}
@pytest.mark.parametrize("obj", [42, {}, {1:3},])
def test_basic_objects(python1, python2, obj):
python1.dumps(obj)
> python2.load_and_is_true("obj == %s" % obj)
multipython.py:51:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
multipython.py:46: in load_and_is_true
py.process.cmdexec("%s %s" %(self.pythonpath, loadfile))
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
cmd = '/home/hpk/bin/python2.7 /tmp/pytest-21/test_basic_objects_python3_4_p4/load.py'
def cmdexec(cmd):
""" return unicode output of executing 'cmd' in a separate process.
raise cmdexec.Error exeception if the command failed.
the exception will provide an 'err' attribute containing
the error-output from the command.
if the subprocess module does not provide a proper encoding/unicode strings
sys.getdefaultencoding() will be used, if that does not exist, 'UTF-8'.
"""
process = subprocess.Popen(cmd, shell=True,
universal_newlines=True,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = process.communicate()
if sys.version_info[0] < 3: # on py3 we get unicode strings, on py2 not
try:
default_encoding = sys.getdefaultencoding() # jython may not have it
except AttributeError:
default_encoding = sys.stdout.encoding or 'UTF-8'
out = unicode(out, process.stdout.encoding or default_encoding)
err = unicode(err, process.stderr.encoding or default_encoding)
status = process.poll()
if status:
> raise ExecutionFailed(status, status, cmd, out, err)
E py.process.cmdexec.Error: ExecutionFailed: 1 /home/hpk/bin/python2.7 /tmp/pytest-21/test_basic_objects_python3_4_p4/load.py
E Traceback (most recent call last):
E File "/tmp/pytest-21/test_basic_objects_python3_4_p4/load.py", line 4, in <module>
E obj = pickle.load(f)
E File "/usr/lib/python2.7/pickle.py", line 1378, in load
E return Unpickler(file).load()
E File "/usr/lib/python2.7/pickle.py", line 858, in load
E dispatch[key](self)
E File "/usr/lib/python2.7/pickle.py", line 886, in load_proto
E raise ValueError, "unsupported pickle protocol: %d" % proto
E ValueError: unsupported pickle protocol: 3
../../../.tox/regen/lib/python3.4/site-packages/py/_process/cmdexec.py:28: Error
--------------------------- Captured stdout call ---------------------------
/tmp/pytest-21/test_basic_objects_python3_4_p4/load.py
_______________ test_basic_objects[python3.4-python2.7-obj2] _______________
python1 = <multipython.Python object at 0x2b02a1bcdeb8>
python2 = <multipython.Python object at 0x2b02a1bcdf98>, obj = {1: 3}
@pytest.mark.parametrize("obj", [42, {}, {1:3},])
def test_basic_objects(python1, python2, obj):
python1.dumps(obj)
> python2.load_and_is_true("obj == %s" % obj)
multipython.py:51:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
multipython.py:46: in load_and_is_true
py.process.cmdexec("%s %s" %(self.pythonpath, loadfile))
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
cmd = '/home/hpk/bin/python2.7 /tmp/pytest-21/test_basic_objects_python3_4_p5/load.py'
def cmdexec(cmd):
""" return unicode output of executing 'cmd' in a separate process.
raise cmdexec.Error exeception if the command failed.
the exception will provide an 'err' attribute containing
the error-output from the command.
if the subprocess module does not provide a proper encoding/unicode strings
sys.getdefaultencoding() will be used, if that does not exist, 'UTF-8'.
"""
process = subprocess.Popen(cmd, shell=True,
universal_newlines=True,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = process.communicate()
if sys.version_info[0] < 3: # on py3 we get unicode strings, on py2 not
try:
default_encoding = sys.getdefaultencoding() # jython may not have it
except AttributeError:
default_encoding = sys.stdout.encoding or 'UTF-8'
out = unicode(out, process.stdout.encoding or default_encoding)
err = unicode(err, process.stderr.encoding or default_encoding)
status = process.poll()
if status:
> raise ExecutionFailed(status, status, cmd, out, err)
E py.process.cmdexec.Error: ExecutionFailed: 1 /home/hpk/bin/python2.7 /tmp/pytest-21/test_basic_objects_python3_4_p5/load.py
E Traceback (most recent call last):
E File "/tmp/pytest-21/test_basic_objects_python3_4_p5/load.py", line 4, in <module>
E obj = pickle.load(f)
E File "/usr/lib/python2.7/pickle.py", line 1378, in load
E return Unpickler(file).load()
E File "/usr/lib/python2.7/pickle.py", line 858, in load
E dispatch[key](self)
E File "/usr/lib/python2.7/pickle.py", line 886, in load_proto
E raise ValueError, "unsupported pickle protocol: %d" % proto
E ValueError: unsupported pickle protocol: 3
../../../.tox/regen/lib/python3.4/site-packages/py/_process/cmdexec.py:28: Error
--------------------------- Captured stdout call ---------------------------
/tmp/pytest-21/test_basic_objects_python3_4_p5/load.py
6 failed, 21 passed in 1.36 seconds
Indirect parametrization of optional implementations/imports
--------------------------------------------------------------------
@@ -331,12 +664,12 @@ If you run this with reporting for skips enabled::
$ py.test -rs test_module.py
=========================== test session starts ============================
platform linux -- Python 3.4.0 -- py-1.4.23 -- pytest-2.6.1
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
collected 2 items
test_module.py .s
========================= short test summary info ==========================
SKIP [1] /tmp/doc-exec-240/conftest.py:10: could not import 'opt2'
SKIP [1] /tmp/doc-exec-226/conftest.py:10: could not import 'opt2'
=================== 1 passed, 1 skipped in 0.01 seconds ====================

View File

@@ -43,7 +43,7 @@ then the test collection looks like this::
$ py.test --collect-only
=========================== test session starts ============================
platform linux -- Python 3.4.0 -- py-1.4.23 -- pytest-2.6.1
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
collected 2 items
<Module 'check_myapp.py'>
<Class 'CheckMyApp'>
@@ -88,7 +88,7 @@ You can always peek at the collection tree without running tests like this::
. $ py.test --collect-only pythoncollection.py
=========================== test session starts ============================
platform linux -- Python 3.4.0 -- py-1.4.23 -- pytest-2.6.1
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
collected 3 items
<Module 'pythoncollection.py'>
<Function 'test_function'>
@@ -141,7 +141,7 @@ interpreters and will leave out the setup.py file::
$ py.test --collect-only
=========================== test session starts ============================
platform linux -- Python 3.4.0 -- py-1.4.23 -- pytest-2.6.1
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
collected 0 items
============================= in 0.01 seconds =============================

View File

@@ -13,10 +13,10 @@ get on the terminal - we are working on that):
assertion $ py.test failure_demo.py
=========================== test session starts ============================
platform linux -- Python 3.4.0 -- py-1.4.23 -- pytest-2.6.1
collected 39 items
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
collected 42 items
failure_demo.py FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
failure_demo.py FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
================================= FAILURES =================================
____________________________ test_generative[0] ____________________________
@@ -30,7 +30,7 @@ get on the terminal - we are working on that):
failure_demo.py:15: AssertionError
_________________________ TestFailing.test_simple __________________________
self = <failure_demo.TestFailing object at 0x2aec3e52d470>
self = <failure_demo.TestFailing object at 0x2adb9885cfd0>
def test_simple(self):
def f():
@@ -40,13 +40,13 @@ get on the terminal - we are working on that):
> assert f() == g()
E assert 42 == 43
E + where 42 = <function TestFailing.test_simple.<locals>.f at 0x2aec3e47b158>()
E + and 43 = <function TestFailing.test_simple.<locals>.g at 0x2aec3e47b268>()
E + where 42 = <function TestFailing.test_simple.<locals>.f at 0x2adb9887e6a8>()
E + and 43 = <function TestFailing.test_simple.<locals>.g at 0x2adb9887e598>()
failure_demo.py:28: AssertionError
____________________ TestFailing.test_simple_multiline _____________________
self = <failure_demo.TestFailing object at 0x2aec3e474ac8>
self = <failure_demo.TestFailing object at 0x2adb98841518>
def test_simple_multiline(self):
otherfunc_multi(
@@ -66,19 +66,19 @@ get on the terminal - we are working on that):
failure_demo.py:11: AssertionError
___________________________ TestFailing.test_not ___________________________
self = <failure_demo.TestFailing object at 0x2aec3e5156a0>
self = <failure_demo.TestFailing object at 0x2adb98813278>
def test_not(self):
def f():
return 42
> assert not f()
E assert not 42
E + where 42 = <function TestFailing.test_not.<locals>.f at 0x2aec3e47e620>()
E + where 42 = <function TestFailing.test_not.<locals>.f at 0x2adb9887e840>()
failure_demo.py:38: AssertionError
_________________ TestSpecialisedExplanations.test_eq_text _________________
self = <failure_demo.TestSpecialisedExplanations object at 0x2aec3e50cba8>
self = <failure_demo.TestSpecialisedExplanations object at 0x2adb987a9588>
def test_eq_text(self):
> assert 'spam' == 'eggs'
@@ -89,7 +89,7 @@ get on the terminal - we are working on that):
failure_demo.py:42: AssertionError
_____________ TestSpecialisedExplanations.test_eq_similar_text _____________
self = <failure_demo.TestSpecialisedExplanations object at 0x2aec3e4e24e0>
self = <failure_demo.TestSpecialisedExplanations object at 0x2adb9881fe80>
def test_eq_similar_text(self):
> assert 'foo 1 bar' == 'foo 2 bar'
@@ -102,7 +102,7 @@ get on the terminal - we are working on that):
failure_demo.py:45: AssertionError
____________ TestSpecialisedExplanations.test_eq_multiline_text ____________
self = <failure_demo.TestSpecialisedExplanations object at 0x2aec3e4cc6d8>
self = <failure_demo.TestSpecialisedExplanations object at 0x2adb98894b38>
def test_eq_multiline_text(self):
> assert 'foo\nspam\nbar' == 'foo\neggs\nbar'
@@ -115,7 +115,7 @@ get on the terminal - we are working on that):
failure_demo.py:48: AssertionError
______________ TestSpecialisedExplanations.test_eq_long_text _______________
self = <failure_demo.TestSpecialisedExplanations object at 0x2aec3e501908>
self = <failure_demo.TestSpecialisedExplanations object at 0x2adb98812fd0>
def test_eq_long_text(self):
a = '1'*100 + 'a' + '2'*100
@@ -132,7 +132,7 @@ get on the terminal - we are working on that):
failure_demo.py:53: AssertionError
_________ TestSpecialisedExplanations.test_eq_long_text_multiline __________
self = <failure_demo.TestSpecialisedExplanations object at 0x2aec3e3af048>
self = <failure_demo.TestSpecialisedExplanations object at 0x2adb987ce240>
def test_eq_long_text_multiline(self):
a = '1\n'*100 + 'a' + '2\n'*100
@@ -156,7 +156,7 @@ get on the terminal - we are working on that):
failure_demo.py:58: AssertionError
_________________ TestSpecialisedExplanations.test_eq_list _________________
self = <failure_demo.TestSpecialisedExplanations object at 0x2aec3e474c50>
self = <failure_demo.TestSpecialisedExplanations object at 0x2adb98841a58>
def test_eq_list(self):
> assert [0, 1, 2] == [0, 1, 3]
@@ -166,7 +166,7 @@ get on the terminal - we are working on that):
failure_demo.py:61: AssertionError
______________ TestSpecialisedExplanations.test_eq_list_long _______________
self = <failure_demo.TestSpecialisedExplanations object at 0x2aec3e515dd8>
self = <failure_demo.TestSpecialisedExplanations object at 0x2adb987e4e48>
def test_eq_list_long(self):
a = [0]*100 + [1] + [3]*100
@@ -178,7 +178,7 @@ get on the terminal - we are working on that):
failure_demo.py:66: AssertionError
_________________ TestSpecialisedExplanations.test_eq_dict _________________
self = <failure_demo.TestSpecialisedExplanations object at 0x2aec3e4a5ef0>
self = <failure_demo.TestSpecialisedExplanations object at 0x2adb98843d30>
def test_eq_dict(self):
> assert {'a': 0, 'b': 1, 'c': 0} == {'a': 0, 'b': 2, 'd': 0}
@@ -194,7 +194,7 @@ get on the terminal - we are working on that):
failure_demo.py:69: AssertionError
_________________ TestSpecialisedExplanations.test_eq_set __________________
self = <failure_demo.TestSpecialisedExplanations object at 0x2aec3e4a2e48>
self = <failure_demo.TestSpecialisedExplanations object at 0x2adb98822b38>
def test_eq_set(self):
> assert set([0, 10, 11, 12]) == set([0, 20, 21])
@@ -210,7 +210,7 @@ get on the terminal - we are working on that):
failure_demo.py:72: AssertionError
_____________ TestSpecialisedExplanations.test_eq_longer_list ______________
self = <failure_demo.TestSpecialisedExplanations object at 0x2aec3e4e0c50>
self = <failure_demo.TestSpecialisedExplanations object at 0x2adb987a96d8>
def test_eq_longer_list(self):
> assert [1,2] == [1,2,3]
@@ -220,7 +220,7 @@ get on the terminal - we are working on that):
failure_demo.py:75: AssertionError
_________________ TestSpecialisedExplanations.test_in_list _________________
self = <failure_demo.TestSpecialisedExplanations object at 0x2aec3e4950f0>
self = <failure_demo.TestSpecialisedExplanations object at 0x2adb987b72e8>
def test_in_list(self):
> assert 1 in [0, 2, 3, 4, 5]
@@ -229,7 +229,7 @@ get on the terminal - we are working on that):
failure_demo.py:78: AssertionError
__________ TestSpecialisedExplanations.test_not_in_text_multiline __________
self = <failure_demo.TestSpecialisedExplanations object at 0x2aec3e474f98>
self = <failure_demo.TestSpecialisedExplanations object at 0x2adb98894908>
def test_not_in_text_multiline(self):
text = 'some multiline\ntext\nwhich\nincludes foo\nand a\ntail'
@@ -247,7 +247,7 @@ get on the terminal - we are working on that):
failure_demo.py:82: AssertionError
___________ TestSpecialisedExplanations.test_not_in_text_single ____________
self = <failure_demo.TestSpecialisedExplanations object at 0x2aec3e5333c8>
self = <failure_demo.TestSpecialisedExplanations object at 0x2adb9885c898>
def test_not_in_text_single(self):
text = 'single foo line'
@@ -260,7 +260,7 @@ get on the terminal - we are working on that):
failure_demo.py:86: AssertionError
_________ TestSpecialisedExplanations.test_not_in_text_single_long _________
self = <failure_demo.TestSpecialisedExplanations object at 0x2aec3e4ccb70>
self = <failure_demo.TestSpecialisedExplanations object at 0x2adb987cc9e8>
def test_not_in_text_single_long(self):
text = 'head ' * 50 + 'foo ' + 'tail ' * 20
@@ -273,7 +273,7 @@ get on the terminal - we are working on that):
failure_demo.py:90: AssertionError
______ TestSpecialisedExplanations.test_not_in_text_single_long_term _______
self = <failure_demo.TestSpecialisedExplanations object at 0x2aec3e502080>
self = <failure_demo.TestSpecialisedExplanations object at 0x2adb987d2748>
def test_not_in_text_single_long_term(self):
text = 'head ' * 50 + 'f'*70 + 'tail ' * 20
@@ -292,7 +292,7 @@ get on the terminal - we are working on that):
i = Foo()
> assert i.b == 2
E assert 1 == 2
E + where 1 = <failure_demo.test_attribute.<locals>.Foo object at 0x2aec3e519c18>.b
E + where 1 = <failure_demo.test_attribute.<locals>.Foo object at 0x2adb987b5470>.b
failure_demo.py:101: AssertionError
_________________________ test_attribute_instance __________________________
@@ -302,8 +302,8 @@ get on the terminal - we are working on that):
b = 1
> assert Foo().b == 2
E assert 1 == 2
E + where 1 = <failure_demo.test_attribute_instance.<locals>.Foo object at 0x2aec3e52d898>.b
E + where <failure_demo.test_attribute_instance.<locals>.Foo object at 0x2aec3e52d898> = <class 'failure_demo.test_attribute_instance.<locals>.Foo'>()
E + where 1 = <failure_demo.test_attribute_instance.<locals>.Foo object at 0x2adb987d0390>.b
E + where <failure_demo.test_attribute_instance.<locals>.Foo object at 0x2adb987d0390> = <class 'failure_demo.test_attribute_instance.<locals>.Foo'>()
failure_demo.py:107: AssertionError
__________________________ test_attribute_failure __________________________
@@ -319,7 +319,7 @@ get on the terminal - we are working on that):
failure_demo.py:116:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <failure_demo.test_attribute_failure.<locals>.Foo object at 0x2aec3e4e0b38>
self = <failure_demo.test_attribute_failure.<locals>.Foo object at 0x2adb98822cf8>
def _get_b(self):
> raise Exception('Failed to get attrib')
@@ -335,15 +335,15 @@ get on the terminal - we are working on that):
b = 2
> assert Foo().b == Bar().b
E assert 1 == 2
E + where 1 = <failure_demo.test_attribute_multiple.<locals>.Foo object at 0x2aec3e4a5748>.b
E + where <failure_demo.test_attribute_multiple.<locals>.Foo object at 0x2aec3e4a5748> = <class 'failure_demo.test_attribute_multiple.<locals>.Foo'>()
E + and 2 = <failure_demo.test_attribute_multiple.<locals>.Bar object at 0x2aec3e4a51d0>.b
E + where <failure_demo.test_attribute_multiple.<locals>.Bar object at 0x2aec3e4a51d0> = <class 'failure_demo.test_attribute_multiple.<locals>.Bar'>()
E + where 1 = <failure_demo.test_attribute_multiple.<locals>.Foo object at 0x2adb98841dd8>.b
E + where <failure_demo.test_attribute_multiple.<locals>.Foo object at 0x2adb98841dd8> = <class 'failure_demo.test_attribute_multiple.<locals>.Foo'>()
E + and 2 = <failure_demo.test_attribute_multiple.<locals>.Bar object at 0x2adb98841a90>.b
E + where <failure_demo.test_attribute_multiple.<locals>.Bar object at 0x2adb98841a90> = <class 'failure_demo.test_attribute_multiple.<locals>.Bar'>()
failure_demo.py:124: AssertionError
__________________________ TestRaises.test_raises __________________________
self = <failure_demo.TestRaises object at 0x2aec3e4a2d68>
self = <failure_demo.TestRaises object at 0x2adb98854668>
def test_raises(self):
s = 'qwe'
@@ -358,7 +358,7 @@ get on the terminal - we are working on that):
<0-codegen /home/hpk/p/pytest/.tox/regen/lib/python3.4/site-packages/_pytest/python.py:1028>:1: ValueError
______________________ TestRaises.test_raises_doesnt _______________________
self = <failure_demo.TestRaises object at 0x2aec3e4e2198>
self = <failure_demo.TestRaises object at 0x2adb988818d0>
def test_raises_doesnt(self):
> raises(IOError, "int('3')")
@@ -367,7 +367,7 @@ get on the terminal - we are working on that):
failure_demo.py:136: Failed
__________________________ TestRaises.test_raise ___________________________
self = <failure_demo.TestRaises object at 0x2aec3e5017b8>
self = <failure_demo.TestRaises object at 0x2adb9885cc50>
def test_raise(self):
> raise ValueError("demo error")
@@ -376,7 +376,7 @@ get on the terminal - we are working on that):
failure_demo.py:139: ValueError
________________________ TestRaises.test_tupleerror ________________________
self = <failure_demo.TestRaises object at 0x2aec3e533160>
self = <failure_demo.TestRaises object at 0x2adb988430b8>
def test_tupleerror(self):
> a,b = [1]
@@ -385,7 +385,7 @@ get on the terminal - we are working on that):
failure_demo.py:142: ValueError
______ TestRaises.test_reinterpret_fails_with_print_for_the_fun_of_it ______
self = <failure_demo.TestRaises object at 0x2aec3e4cc438>
self = <failure_demo.TestRaises object at 0x2adb9881fa20>
def test_reinterpret_fails_with_print_for_the_fun_of_it(self):
l = [1,2,3]
@@ -398,7 +398,7 @@ get on the terminal - we are working on that):
l is [1, 2, 3]
________________________ TestRaises.test_some_error ________________________
self = <failure_demo.TestRaises object at 0x2aec3e5199e8>
self = <failure_demo.TestRaises object at 0x2adb98894a90>
def test_some_error(self):
> if namenotexi:
@@ -426,7 +426,7 @@ get on the terminal - we are working on that):
<2-codegen 'abc-123' /home/hpk/p/pytest/doc/en/example/assertion/failure_demo.py:162>:2: AssertionError
____________________ TestMoreErrors.test_complex_error _____________________
self = <failure_demo.TestMoreErrors object at 0x2aec3e515cf8>
self = <failure_demo.TestMoreErrors object at 0x2adb98812da0>
def test_complex_error(self):
def f():
@@ -450,7 +450,7 @@ get on the terminal - we are working on that):
failure_demo.py:5: AssertionError
___________________ TestMoreErrors.test_z1_unpack_error ____________________
self = <failure_demo.TestMoreErrors object at 0x2aec3e4f7a58>
self = <failure_demo.TestMoreErrors object at 0x2adb9884d4a8>
def test_z1_unpack_error(self):
l = []
@@ -460,7 +460,7 @@ get on the terminal - we are working on that):
failure_demo.py:179: ValueError
____________________ TestMoreErrors.test_z2_type_error _____________________
self = <failure_demo.TestMoreErrors object at 0x2aec3e52db38>
self = <failure_demo.TestMoreErrors object at 0x2adb987b52b0>
def test_z2_type_error(self):
l = 3
@@ -470,19 +470,19 @@ get on the terminal - we are working on that):
failure_demo.py:183: TypeError
______________________ TestMoreErrors.test_startswith ______________________
self = <failure_demo.TestMoreErrors object at 0x2aec3e538a58>
self = <failure_demo.TestMoreErrors object at 0x2adb988224e0>
def test_startswith(self):
s = "123"
g = "456"
> assert s.startswith(g)
E assert <built-in method startswith of str object at 0x2aec3e501420>('456')
E + where <built-in method startswith of str object at 0x2aec3e501420> = '123'.startswith
E assert <built-in method startswith of str object at 0x2adb987a9ca8>('456')
E + where <built-in method startswith of str object at 0x2adb987a9ca8> = '123'.startswith
failure_demo.py:188: AssertionError
__________________ TestMoreErrors.test_startswith_nested ___________________
self = <failure_demo.TestMoreErrors object at 0x2aec3e4f1b00>
self = <failure_demo.TestMoreErrors object at 0x2adb98836898>
def test_startswith_nested(self):
def f():
@@ -490,15 +490,15 @@ get on the terminal - we are working on that):
def g():
return "456"
> assert f().startswith(g())
E assert <built-in method startswith of str object at 0x2aec3e501420>('456')
E + where <built-in method startswith of str object at 0x2aec3e501420> = '123'.startswith
E + where '123' = <function TestMoreErrors.test_startswith_nested.<locals>.f at 0x2aec3e5572f0>()
E + and '456' = <function TestMoreErrors.test_startswith_nested.<locals>.g at 0x2aec3e557268>()
E assert <built-in method startswith of str object at 0x2adb987a9ca8>('456')
E + where <built-in method startswith of str object at 0x2adb987a9ca8> = '123'.startswith
E + where '123' = <function TestMoreErrors.test_startswith_nested.<locals>.f at 0x2adb9887e9d8>()
E + and '456' = <function TestMoreErrors.test_startswith_nested.<locals>.g at 0x2adb9887e7b8>()
failure_demo.py:195: AssertionError
_____________________ TestMoreErrors.test_global_func ______________________
self = <failure_demo.TestMoreErrors object at 0x2aec3e495438>
self = <failure_demo.TestMoreErrors object at 0x2adb987b77f0>
def test_global_func(self):
> assert isinstance(globf(42), float)
@@ -508,18 +508,18 @@ get on the terminal - we are working on that):
failure_demo.py:198: AssertionError
_______________________ TestMoreErrors.test_instance _______________________
self = <failure_demo.TestMoreErrors object at 0x2aec3e567240>
self = <failure_demo.TestMoreErrors object at 0x2adb988729b0>
def test_instance(self):
self.x = 6*7
> assert self.x != 42
E assert 42 != 42
E + where 42 = <failure_demo.TestMoreErrors object at 0x2aec3e567240>.x
E + where 42 = <failure_demo.TestMoreErrors object at 0x2adb988729b0>.x
failure_demo.py:202: AssertionError
_______________________ TestMoreErrors.test_compare ________________________
self = <failure_demo.TestMoreErrors object at 0x2aec3e502cc0>
self = <failure_demo.TestMoreErrors object at 0x2adb98812f98>
def test_compare(self):
> assert globf(10) < 5
@@ -529,7 +529,7 @@ get on the terminal - we are working on that):
failure_demo.py:205: AssertionError
_____________________ TestMoreErrors.test_try_finally ______________________
self = <failure_demo.TestMoreErrors object at 0x2aec3e5197f0>
self = <failure_demo.TestMoreErrors object at 0x2adb987d0198>
def test_try_finally(self):
x = 1
@@ -538,4 +538,55 @@ get on the terminal - we are working on that):
E assert 1 == 0
failure_demo.py:210: AssertionError
======================== 39 failed in 0.22 seconds =========================
___________________ TestCustomAssertMsg.test_single_line ___________________
self = <failure_demo.TestCustomAssertMsg object at 0x2adb98894cc0>
def test_single_line(self):
class A:
a = 1
b = 2
> assert A.a == b, "A.a appears not to be b"
E AssertionError: A.a appears not to be b
E assert 1 == 2
E + where 1 = <class 'failure_demo.TestCustomAssertMsg.test_single_line.<locals>.A'>.a
failure_demo.py:221: AssertionError
____________________ TestCustomAssertMsg.test_multiline ____________________
self = <failure_demo.TestCustomAssertMsg object at 0x2adb988414e0>
def test_multiline(self):
class A:
a = 1
b = 2
> assert A.a == b, "A.a appears not to be b\n" \
"or does not appear to be b\none of those"
E AssertionError: A.a appears not to be b
E or does not appear to be b
E one of those
E assert 1 == 2
E + where 1 = <class 'failure_demo.TestCustomAssertMsg.test_multiline.<locals>.A'>.a
failure_demo.py:227: AssertionError
___________________ TestCustomAssertMsg.test_custom_repr ___________________
self = <failure_demo.TestCustomAssertMsg object at 0x2adb9885c668>
def test_custom_repr(self):
class JSON:
a = 1
def __repr__(self):
return "This is JSON\n{\n 'foo': 'bar'\n}"
a = JSON()
b = 2
> assert a.a == b, a
E AssertionError: This is JSON
E {
E 'foo': 'bar'
E }
E assert 1 == 2
E + where 1 = This is JSON\n{\n 'foo': 'bar'\n}.a
failure_demo.py:237: AssertionError
======================== 42 failed in 0.29 seconds =========================

View File

@@ -55,7 +55,7 @@ Let's run this without supplying our new option::
test_sample.py:6: AssertionError
--------------------------- Captured stdout call ---------------------------
first
1 failed in 0.01 seconds
1 failed in 0.02 seconds
And now with supplying a command line option::
@@ -63,9 +63,9 @@ And now with supplying a command line option::
F
================================= FAILURES =================================
_______________________________ test_answer ________________________________
cmdopt = 'type2'
def test_answer(cmdopt):
if cmdopt == "type1":
print ("first")
@@ -73,7 +73,7 @@ And now with supplying a command line option::
print ("second")
> assert 0 # to see what was printed
E assert 0
test_sample.py:6: AssertionError
--------------------------- Captured stdout call ---------------------------
second
@@ -108,9 +108,9 @@ directory with the above conftest.py::
$ py.test
=========================== test session starts ============================
platform linux -- Python 3.4.0 -- py-1.4.23 -- pytest-2.6.1
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
collected 0 items
============================= in 0.00 seconds =============================
.. _`excontrolskip`:
@@ -152,12 +152,12 @@ and when running it will see a skipped "slow" test::
$ py.test -rs # "-rs" means report details on the little 's'
=========================== test session starts ============================
platform linux -- Python 3.4.0 -- py-1.4.23 -- pytest-2.6.1
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
collected 2 items
test_module.py .s
========================= short test summary info ==========================
SKIP [1] /tmp/doc-exec-243/conftest.py:9: need --runslow option to run
SKIP [1] /tmp/doc-exec-229/conftest.py:9: need --runslow option to run
=================== 1 passed, 1 skipped in 0.01 seconds ====================
@@ -165,11 +165,11 @@ Or run it including the ``slow`` marked test::
$ py.test --runslow
=========================== test session starts ============================
platform linux -- Python 3.4.0 -- py-1.4.23 -- pytest-2.6.1
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
collected 2 items
test_module.py ..
========================= 2 passed in 0.01 seconds =========================
Writing well integrated assertion helpers
@@ -256,10 +256,10 @@ which will add the string to the test header accordingly::
$ py.test
=========================== test session starts ============================
platform linux -- Python 3.4.0 -- py-1.4.23 -- pytest-2.6.1
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
project deps: mylib-1.1
collected 0 items
============================= in 0.00 seconds =============================
.. regendoc:wipe
@@ -279,20 +279,20 @@ which will add info only when run with "--v"::
$ py.test -v
=========================== test session starts ============================
platform linux -- Python 3.4.0 -- py-1.4.23 -- pytest-2.6.1 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4
info1: did you know that ...
did you?
collecting ... collected 0 items
============================= in 0.00 seconds =============================
and nothing when run plainly::
$ py.test
=========================== test session starts ============================
platform linux -- Python 3.4.0 -- py-1.4.23 -- pytest-2.6.1
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
collected 0 items
============================= in 0.00 seconds =============================
profiling test duration
@@ -322,7 +322,7 @@ Now we can profile which test functions execute the slowest::
$ py.test --durations=3
=========================== test session starts ============================
platform linux -- Python 3.4.0 -- py-1.4.23 -- pytest-2.6.1
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
collected 3 items
test_some_are_slow.py ...
@@ -330,8 +330,8 @@ Now we can profile which test functions execute the slowest::
========================= slowest 3 test durations =========================
0.20s call test_some_are_slow.py::test_funcslow2
0.10s call test_some_are_slow.py::test_funcslow1
0.00s setup test_some_are_slow.py::test_funcslow2
========================= 3 passed in 0.31 seconds =========================
0.00s teardown test_some_are_slow.py::test_funcslow1
========================= 3 passed in 0.32 seconds =========================
incremental testing - test steps
---------------------------------------------------
@@ -383,7 +383,7 @@ If we run this::
$ py.test -rx
=========================== test session starts ============================
platform linux -- Python 3.4.0 -- py-1.4.23 -- pytest-2.6.1
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
collected 4 items
test_step.py .Fx.
@@ -391,7 +391,7 @@ If we run this::
================================= FAILURES =================================
____________________ TestUserHandling.test_modification ____________________
self = <test_step.TestUserHandling object at 0x2b2ef2a4feb8>
self = <test_step.TestUserHandling object at 0x2af9f0d94470>
def test_modification(self):
> assert 0
@@ -453,7 +453,7 @@ We can run this::
$ py.test
=========================== test session starts ============================
platform linux -- Python 3.4.0 -- py-1.4.23 -- pytest-2.6.1
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
collected 7 items
test_step.py .Fx.
@@ -463,17 +463,17 @@ We can run this::
================================== ERRORS ==================================
_______________________ ERROR at setup of test_root ________________________
file /tmp/doc-exec-243/b/test_error.py, line 1
file /tmp/doc-exec-229/b/test_error.py, line 1
def test_root(db): # no db here, will error out
fixture 'db' not found
available fixtures: tmpdir, monkeypatch, capsys, capfd, pytestconfig, recwarn
available fixtures: capsys, pytestconfig, monkeypatch, tmpdir, recwarn, capfd
use 'py.test --fixtures [testpath]' for help on them.
/tmp/doc-exec-243/b/test_error.py:1
/tmp/doc-exec-229/b/test_error.py:1
================================= FAILURES =================================
____________________ TestUserHandling.test_modification ____________________
self = <test_step.TestUserHandling object at 0x2b63a7aec710>
self = <test_step.TestUserHandling object at 0x2b0f0e2ff0b8>
def test_modification(self):
> assert 0
@@ -482,23 +482,25 @@ We can run this::
test_step.py:9: AssertionError
_________________________________ test_a1 __________________________________
db = <conftest.DB object at 0x2b63a7b04470>
db = <conftest.DB object at 0x2b0f0e2ff630>
def test_a1(db):
> assert 0, db # to show value
E AssertionError: <conftest.DB object at 0x2b63a7b04470>
E AssertionError: <conftest.DB object at 0x2b0f0e2ff630>
E assert 0
a/test_db.py:2: AssertionError
_________________________________ test_a2 __________________________________
db = <conftest.DB object at 0x2b63a7b04470>
db = <conftest.DB object at 0x2b0f0e2ff630>
def test_a2(db):
> assert 0, db # to show value
E AssertionError: <conftest.DB object at 0x2b63a7b04470>
E AssertionError: <conftest.DB object at 0x2b0f0e2ff630>
E assert 0
a/test_db2.py:2: AssertionError
========== 3 failed, 2 passed, 1 xfailed, 1 error in 0.03 seconds ==========
========== 3 failed, 2 passed, 1 xfailed, 1 error in 0.04 seconds ==========
The two test modules in the ``a`` directory see the same ``db`` fixture instance
while the one test in the sister-directory ``b`` doesn't see it. We could of course
@@ -553,7 +555,7 @@ and run them::
$ py.test test_module.py
=========================== test session starts ============================
platform linux -- Python 3.4.0 -- py-1.4.23 -- pytest-2.6.1
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
collected 2 items
test_module.py FF
@@ -561,7 +563,7 @@ and run them::
================================= FAILURES =================================
________________________________ test_fail1 ________________________________
tmpdir = local('/tmp/pytest-509/test_fail10')
tmpdir = local('/tmp/pytest-22/test_fail10')
def test_fail1(tmpdir):
> assert 0
@@ -575,12 +577,12 @@ and run them::
E assert 0
test_module.py:4: AssertionError
========================= 2 failed in 0.02 seconds =========================
========================= 2 failed in 0.01 seconds =========================
you will have a "failures" file which contains the failing test ids::
$ cat failures
test_module.py::test_fail1 (/tmp/pytest-509/test_fail10)
test_module.py::test_fail1 (/tmp/pytest-22/test_fail10)
test_module.py::test_fail2
Making test result information available in fixtures
@@ -613,10 +615,10 @@ here is a little example implemented via a local plugin::
# request.node is an "item" because we use the default
# "function" scope
if request.node.rep_setup.failed:
print "setting up a test failed!", request.node.nodeid
print ("setting up a test failed!", request.node.nodeid)
elif request.node.rep_setup.passed:
if request.node.rep_call.failed:
print "executing test failed", request.node.nodeid
print ("executing test failed", request.node.nodeid)
request.addfinalizer(fin)
@@ -642,29 +644,41 @@ if you then have failing tests::
and run it::
$ py.test -s test_module.py
Traceback (most recent call last):
File "/home/hpk/p/pytest/.tox/regen/lib/python3.4/site-packages/_pytest/config.py", line 513, in getconftestmodules
return self._path2confmods[path]
KeyError: local('/tmp/doc-exec-243/test_module.py')
=========================== test session starts ============================
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
collected 3 items
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/hpk/p/pytest/.tox/regen/lib/python3.4/site-packages/_pytest/config.py", line 537, in importconftest
return self._conftestpath2mod[conftestpath]
KeyError: local('/tmp/doc-exec-243/conftest.py')
test_module.py Esetting up a test failed! test_module.py::test_setup_fails
Fexecuting test failed test_module.py::test_call_fails
F
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/hpk/p/pytest/.tox/regen/lib/python3.4/site-packages/_pytest/config.py", line 543, in importconftest
mod = conftestpath.pyimport()
File "/home/hpk/p/pytest/.tox/regen/lib/python3.4/site-packages/py/_path/local.py", line 620, in pyimport
__import__(modname)
File "/tmp/doc-exec-243/conftest.py", line 22
print "setting up a test failed!", request.node.nodeid
^
SyntaxError: invalid syntax
ERROR: could not load /tmp/doc-exec-243/conftest.py
================================== ERRORS ==================================
____________________ ERROR at setup of test_setup_fails ____________________
@pytest.fixture
def other():
> assert 0
E assert 0
test_module.py:6: AssertionError
================================= FAILURES =================================
_____________________________ test_call_fails ______________________________
something = None
def test_call_fails(something):
> assert 0
E assert 0
test_module.py:12: AssertionError
________________________________ test_fail2 ________________________________
def test_fail2():
> assert 0
E assert 0
test_module.py:15: AssertionError
==================== 2 failed, 1 error in 0.01 seconds =====================
You'll see that the fixture finalizers could use the precise reporting
information.
@@ -719,3 +733,4 @@ This makes it convenient to execute your tests from within your frozen
application, using standard ``py.test`` command-line options::
$ ./app_main --pytest --verbose --tb=long --junit-xml=results.xml test-suite/
/bin/sh: 1: ./app_main: not found

View File

@@ -1,7 +1,7 @@
A session-fixture which can look at all collected tests
----------------------------------------------------------------
A session-scoped fixture effectively has access to all
A session-scoped fixture effectively has access to all
collected test items. Here is an example of a fixture
function which walks all collected tests and looks
if their test class defines a ``callme`` method and
@@ -13,7 +13,7 @@ calls it::
@pytest.fixture(scope="session", autouse=True)
def callattr_ahead_of_alltests(request):
print "callattr_ahead_of_alltests called"
print ("callattr_ahead_of_alltests called")
seen = set([None])
session = request.node
for item in session.items:
@@ -31,55 +31,42 @@ will be called ahead of running any tests::
class TestHello:
@classmethod
def callme(cls):
print "callme called!"
print ("callme called!")
def test_method1(self):
print "test_method1 called"
print ("test_method1 called")
def test_method2(self):
print "test_method1 called"
print ("test_method1 called")
class TestOther:
@classmethod
def callme(cls):
print "callme other called"
print ("callme other called")
def test_other(self):
print "test other"
print ("test other")
# works with unittest as well ...
import unittest
class SomeTest(unittest.TestCase):
@classmethod
def callme(self):
print "SomeTest callme called"
print ("SomeTest callme called")
def test_unit1(self):
print "test_unit1 method called"
print ("test_unit1 method called")
If you run this without output capturing::
$ py.test -q -s test_module.py
Traceback (most recent call last):
File "/home/hpk/p/pytest/.tox/regen/lib/python3.4/site-packages/_pytest/config.py", line 513, in getconftestmodules
return self._path2confmods[path]
KeyError: local('/tmp/doc-exec-244/test_module.py')
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/hpk/p/pytest/.tox/regen/lib/python3.4/site-packages/_pytest/config.py", line 537, in importconftest
return self._conftestpath2mod[conftestpath]
KeyError: local('/tmp/doc-exec-244/conftest.py')
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/hpk/p/pytest/.tox/regen/lib/python3.4/site-packages/_pytest/config.py", line 543, in importconftest
mod = conftestpath.pyimport()
File "/home/hpk/p/pytest/.tox/regen/lib/python3.4/site-packages/py/_path/local.py", line 620, in pyimport
__import__(modname)
File "/tmp/doc-exec-244/conftest.py", line 6
print "callattr_ahead_of_alltests called"
^
SyntaxError: invalid syntax
ERROR: could not load /tmp/doc-exec-244/conftest.py
$ py.test -q -s test_module.py
callattr_ahead_of_alltests called
callme called!
callme other called
SomeTest callme called
test_method1 called
.test_method1 called
.test other
.test_unit1 method called
.
4 passed in 0.05 seconds

View File

@@ -76,7 +76,7 @@ marked ``smtp`` fixture function. Running the test looks like this::
$ py.test test_smtpsimple.py
=========================== test session starts ============================
platform linux -- Python 3.4.0 -- py-1.4.23 -- pytest-2.6.2.dev1
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
collected 1 items
test_smtpsimple.py F
@@ -84,7 +84,7 @@ marked ``smtp`` fixture function. Running the test looks like this::
================================= FAILURES =================================
________________________________ test_ehlo _________________________________
smtp = <smtplib.SMTP object at 0x2ade77b37e48>
smtp = <smtplib.SMTP object at 0x2b040fa62128>
def test_ehlo(smtp):
response, msg = smtp.ehlo()
@@ -93,7 +93,7 @@ marked ``smtp`` fixture function. Running the test looks like this::
E TypeError: Type str doesn't support the buffer API
test_smtpsimple.py:11: TypeError
========================= 1 failed in 0.18 seconds =========================
========================= 1 failed in 0.20 seconds =========================
In the failure traceback we see that the test function was called with a
``smtp`` argument, the ``smtplib.SMTP()`` instance created by the fixture
@@ -193,7 +193,7 @@ inspect what is going on and can now run the tests::
$ py.test test_module.py
=========================== test session starts ============================
platform linux -- Python 3.4.0 -- py-1.4.23 -- pytest-2.6.2.dev1
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
collected 2 items
test_module.py FF
@@ -201,7 +201,7 @@ inspect what is going on and can now run the tests::
================================= FAILURES =================================
________________________________ test_ehlo _________________________________
smtp = <smtplib.SMTP object at 0x2b4b07e38e48>
smtp = <smtplib.SMTP object at 0x2abe3c757208>
def test_ehlo(smtp):
response = smtp.ehlo()
@@ -212,7 +212,7 @@ inspect what is going on and can now run the tests::
test_module.py:5: TypeError
________________________________ test_noop _________________________________
smtp = <smtplib.SMTP object at 0x2b4b07e38e48>
smtp = <smtplib.SMTP object at 0x2abe3c757208>
def test_noop(smtp):
response = smtp.noop()
@@ -221,7 +221,7 @@ inspect what is going on and can now run the tests::
E assert 0
test_module.py:11: AssertionError
========================= 2 failed in 0.18 seconds =========================
========================= 2 failed in 0.17 seconds =========================
You see the two ``assert 0`` failing and more importantly you can also see
that the same (module-scoped) ``smtp`` object was passed into the two
@@ -310,7 +310,7 @@ again, nothing much has changed::
$ py.test -s -q --tb=no
FF
2 failed in 0.17 seconds
2 failed in 0.16 seconds
Let's quickly create another test module that actually sets the
server URL in its module namespace::
@@ -331,6 +331,7 @@ Running it::
test_anothersmtp.py:5: in test_showhelo
assert 0, smtp.helo()
E AssertionError: (250, b'mail.python.org')
E assert 0
voila! The ``smtp`` fixture function picked up our mail server name
from the module namespace.
@@ -377,7 +378,7 @@ So let's just do another run::
================================= FAILURES =================================
__________________________ test_ehlo[merlinux.eu] __________________________
smtp = <smtplib.SMTP object at 0x2b824acf3e80>
smtp = <smtplib.SMTP object at 0x2afbf4496828>
def test_ehlo(smtp):
response = smtp.ehlo()
@@ -388,7 +389,7 @@ So let's just do another run::
test_module.py:5: TypeError
__________________________ test_noop[merlinux.eu] __________________________
smtp = <smtplib.SMTP object at 0x2b824acf3e80>
smtp = <smtplib.SMTP object at 0x2afbf4496828>
def test_noop(smtp):
response = smtp.noop()
@@ -399,7 +400,7 @@ So let's just do another run::
test_module.py:11: AssertionError
________________________ test_ehlo[mail.python.org] ________________________
smtp = <smtplib.SMTP object at 0x2b824b19fb38>
smtp = <smtplib.SMTP object at 0x2afbf4496d68>
def test_ehlo(smtp):
response = smtp.ehlo()
@@ -409,10 +410,10 @@ So let's just do another run::
test_module.py:5: TypeError
-------------------------- Captured stdout setup ---------------------------
finalizing <smtplib.SMTP object at 0x2b824acf3e80>
finalizing <smtplib.SMTP object at 0x2afbf4496828>
________________________ test_noop[mail.python.org] ________________________
smtp = <smtplib.SMTP object at 0x2b824b19fb38>
smtp = <smtplib.SMTP object at 0x2afbf4496d68>
def test_noop(smtp):
response = smtp.noop()
@@ -421,7 +422,7 @@ So let's just do another run::
E assert 0
test_module.py:11: AssertionError
4 failed in 6.37 seconds
4 failed in 6.02 seconds
We see that our two test functions each ran twice, against the different
``smtp`` instances. Note also, that with the ``mail.python.org``
@@ -461,13 +462,13 @@ Here we declare an ``app`` fixture which receives the previously defined
$ py.test -v test_appsetup.py
=========================== test session starts ============================
platform linux -- Python 3.4.0 -- py-1.4.23 -- pytest-2.6.2.dev1 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4
collecting ... collected 2 items
test_appsetup.py::test_smtp_exists[merlinux.eu] PASSED
test_appsetup.py::test_smtp_exists[mail.python.org] PASSED
========================= 2 passed in 6.11 seconds =========================
========================= 2 passed in 5.45 seconds =========================
Due to the parametrization of ``smtp`` the test will run twice with two
different ``App`` instances and respective smtp servers. There is no
@@ -525,7 +526,7 @@ Let's run the tests in verbose mode and with looking at the print-output::
$ py.test -v -s test_module.py
=========================== test session starts ============================
platform linux -- Python 3.4.0 -- py-1.4.23 -- pytest-2.6.2.dev1 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4
collecting ... collected 8 items
test_module.py::test_0[1] test0 1

View File

@@ -27,7 +27,7 @@ Installation options::
To check your installation has installed the correct version::
$ py.test --version
This is pytest version 2.6.1, imported from /home/hpk/p/pytest/.tox/regen/lib/python3.4/site-packages/pytest.py
This is pytest version 2.6.3, imported from /home/hpk/p/pytest/.tox/regen/lib/python3.4/site-packages/pytest.py
If you get an error checkout :ref:`installation issues`.
@@ -49,19 +49,19 @@ That's it. You can execute the test function now::
$ py.test
=========================== test session starts ============================
platform linux -- Python 3.4.0 -- py-1.4.23 -- pytest-2.6.1
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
collected 1 items
test_sample.py F
================================= FAILURES =================================
_______________________________ test_answer ________________________________
def test_answer():
> assert func(3) == 5
E assert 4 == 5
E + where 4 = func(3)
test_sample.py:5: AssertionError
========================= 1 failed in 0.01 seconds =========================
@@ -126,14 +126,14 @@ run the module by passing its filename::
.F
================================= FAILURES =================================
____________________________ TestClass.test_two ____________________________
self = <test_class.TestClass object at 0x2ad4b005b710>
self = <test_class.TestClass object at 0x2b39478f7438>
def test_two(self):
x = "hello"
> assert hasattr(x, 'check')
E assert hasattr('hello', 'check')
test_class.py:8: AssertionError
1 failed, 1 passed in 0.01 seconds
@@ -159,18 +159,21 @@ We list the name ``tmpdir`` in the test function signature and
before performing the test function call. Let's just run it::
$ py.test -q test_tmpdir.py
================================== ERRORS ==================================
_____________________ ERROR collecting test_tmpdir.py ______________________
/home/hpk/p/pytest/.tox/regen/lib/python3.4/site-packages/_pytest/python.py:463: in _importtestmodule
mod = self.fspath.pyimport(ensuresyspath=True)
/home/hpk/p/pytest/.tox/regen/lib/python3.4/site-packages/py/_path/local.py:620: in pyimport
__import__(modname)
E File "/tmp/doc-exec-187/test_tmpdir.py", line 2
E print tmpdir
E ^
E SyntaxError: invalid syntax
1 error in 0.03 seconds
F
================================= FAILURES =================================
_____________________________ test_needsfiles ______________________________
tmpdir = local('/tmp/pytest-18/test_needsfiles0')
def test_needsfiles(tmpdir):
print (tmpdir)
> assert 0
E assert 0
test_tmpdir.py:3: AssertionError
--------------------------- Captured stdout call ---------------------------
/tmp/pytest-18/test_needsfiles0
1 failed in 0.01 seconds
Before the test runs, a unique-per-test-invocation temporary directory
was created. More info at :ref:`tmpdir handling`.

View File

@@ -233,7 +233,7 @@ get started with setuptools integration::
def initialize_options(self):
TestCommand.initialize_options(self)
self.pytest_args = None
self.pytest_args = []
def finalize_options(self):
TestCommand.finalize_options(self)
@@ -276,7 +276,7 @@ Conventions for Python test discovery
* collection starts from the initial command line arguments
which may be directories, filenames or test ids.
* recurse into directories, unless they match :confval:`norecursedirs`
* ``test_*.py`` or ``*_test.py`` files, imported by their `package name`_.
* ``test_*.py`` or ``*_test.py`` files, imported by their `test package name`_.
* ``Test`` prefixed test classes (without an ``__init__`` method)
* ``test_`` prefixed test functions or methods are test items

View File

@@ -18,4 +18,4 @@
.. _hudson: http://hudson-ci.org/
.. _jenkins: http://jenkins-ci.org/
.. _tox: http://testrun.org/tox
.. _pylib: http://pylib.org
.. _pylib: http://py.readthedocs.org/en/latest/

View File

@@ -53,7 +53,7 @@ them in turn::
$ py.test
=========================== test session starts ============================
platform linux -- Python 3.4.0 -- py-1.4.23 -- pytest-2.6.1
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
collected 3 items
test_expectation.py ..F
@@ -100,12 +100,12 @@ Let's run this::
$ py.test
=========================== test session starts ============================
platform linux -- Python 3.4.0 -- py-1.4.23 -- pytest-2.6.1
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
collected 3 items
test_expectation.py ..x
=================== 2 passed, 1 xfailed in 0.01 seconds ====================
=================== 2 passed, 1 xfailed in 0.02 seconds ====================
The one parameter set which caused a failure previously now
shows up as an "xfailed (expected to fail)" test.
@@ -170,8 +170,8 @@ Let's also run with a stringinput that will lead to a failing test::
def test_valid_string(stringinput):
> assert stringinput.isalpha()
E assert <built-in method isalpha of str object at 0x2ab7463a6b58>()
E + where <built-in method isalpha of str object at 0x2ab7463a6b58> = '!'.isalpha
E assert <built-in method isalpha of str object at 0x2b1c6de5bb20>()
E + where <built-in method isalpha of str object at 0x2b1c6de5bb20> = '!'.isalpha
test_strings.py:3: AssertionError
1 failed in 0.01 seconds
@@ -185,7 +185,7 @@ listlist::
$ py.test -q -rs test_strings.py
s
========================= short test summary info ==========================
SKIP [1] /home/hpk/p/pytest/.tox/regen/lib/python3.4/site-packages/_pytest/python.py:1139: got empty parameter set, function test_valid_string at /tmp/doc-exec-195/test_strings.py:1
SKIP [1] /home/hpk/p/pytest/.tox/regen/lib/python3.4/site-packages/_pytest/python.py:1139: got empty parameter set, function test_valid_string at /tmp/doc-exec-180/test_strings.py:1
1 skipped in 0.01 seconds
For further examples, you might want to look at :ref:`more

View File

@@ -164,7 +164,7 @@ Running it with the report-on-xfail option gives this output::
example $ py.test -rx xfail_demo.py
=========================== test session starts ============================
platform linux -- Python 3.4.0 -- py-1.4.23 -- pytest-2.6.1
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
collected 7 items
xfail_demo.py xxxxxxx

View File

@@ -29,7 +29,7 @@ Running this would result in a passed test except for the last
$ py.test test_tmpdir.py
=========================== test session starts ============================
platform linux -- Python 3.4.0 -- py-1.4.23 -- pytest-2.6.1
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
collected 1 items
test_tmpdir.py F
@@ -37,7 +37,7 @@ Running this would result in a passed test except for the last
================================= FAILURES =================================
_____________________________ test_create_file _____________________________
tmpdir = local('/tmp/pytest-506/test_create_file0')
tmpdir = local('/tmp/pytest-19/test_create_file0')
def test_create_file(tmpdir):
p = tmpdir.mkdir("sub").join("hello.txt")
@@ -48,7 +48,7 @@ Running this would result in a passed test except for the last
E assert 0
test_tmpdir.py:7: AssertionError
========================= 1 failed in 0.02 seconds =========================
========================= 1 failed in 0.01 seconds =========================
.. _`base temporary directory`:

View File

@@ -88,7 +88,7 @@ the ``self.db`` values in the traceback::
$ py.test test_unittest_db.py
=========================== test session starts ============================
platform linux -- Python 3.4.0 -- py-1.4.23 -- pytest-2.6.1
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
collected 2 items
test_unittest_db.py FF
@@ -101,7 +101,8 @@ the ``self.db`` values in the traceback::
def test_method1(self):
assert hasattr(self, "db")
> assert 0, self.db # fail for demo purposes
E AssertionError: <conftest.db_class.<locals>.DummyDB object at 0x2b12849f90b8>
E AssertionError: <conftest.db_class.<locals>.DummyDB object at 0x2b938b865208>
E assert 0
test_unittest_db.py:9: AssertionError
___________________________ MyTest.test_method2 ____________________________
@@ -110,7 +111,8 @@ the ``self.db`` values in the traceback::
def test_method2(self):
> assert 0, self.db # fail for demo purposes
E AssertionError: <conftest.db_class.<locals>.DummyDB object at 0x2b12849f90b8>
E AssertionError: <conftest.db_class.<locals>.DummyDB object at 0x2b938b865208>
E assert 0
test_unittest_db.py:12: AssertionError
========================= 2 failed in 0.05 seconds =========================

View File

@@ -17,7 +17,7 @@ long_description = open('README.rst').read()
def main():
install_requires = ['py>=1.4.24']
install_requires = ['py>=1.4.25']
if sys.version_info < (2, 7) or (3,) <= sys.version_info < (3, 2):
install_requires.append('argparse')
if sys.platform == 'win32':
@@ -27,7 +27,7 @@ def main():
name='pytest',
description='pytest: simple powerful testing with Python',
long_description=long_description,
version='2.6.2',
version='2.6.3',
url='http://pytest.org',
license='MIT license',
platforms=['unix', 'linux', 'osx', 'cygwin', 'win32'],

View File

@@ -103,7 +103,7 @@ def getexecutable(name, cache={}):
return executable
@pytest.fixture(params=['python2.6', 'python2.7', 'python3.3', "python3.4",
'pypy', 'pypy3', 'jython'])
'pypy', 'pypy3'])
def anypython(request):
name = request.param
executable = getexecutable(name)

View File

@@ -1001,6 +1001,40 @@ class TestFixtureManagerParseFactories:
reprec = testdir.inline_run("-s")
reprec.assertoutcome(passed=1)
def test_parsefactories_relative_node_ids(self, testdir):
# example mostly taken from:
# https://mail.python.org/pipermail/pytest-dev/2014-September/002617.html
runner = testdir.mkdir("runner")
package = testdir.mkdir("package")
package.join("conftest.py").write(dedent("""\
import pytest
@pytest.fixture
def one():
return 1
"""))
package.join("test_x.py").write(dedent("""\
def test_x(one):
assert one == 1
"""))
sub = package.mkdir("sub")
sub.join("__init__.py").ensure()
sub.join("conftest.py").write(dedent("""\
import pytest
@pytest.fixture
def one():
return 2
"""))
sub.join("test_y.py").write(dedent("""\
def test_x(one):
assert one == 2
"""))
reprec = testdir.inline_run()
reprec.assertoutcome(passed=2)
with runner.as_cwd():
reprec = testdir.inline_run("..")
reprec.assertoutcome(passed=2)
class TestAutouseDiscovery:
def pytest_funcarg__testdir(self, testdir):
testdir.makeconftest("""

View File

@@ -4,6 +4,7 @@ import sys
import py, pytest
import _pytest.assertion as plugin
from _pytest.assertion import reinterpret
from _pytest.assertion import util
needsnewassert = pytest.mark.skipif("sys.version_info < (2,6)")
@@ -201,7 +202,7 @@ class TestAssert_reprcompare:
class TestFormatExplanation:
def test_speical_chars_full(self, testdir):
def test_special_chars_full(self, testdir):
# Issue 453, for the bug this would raise IndexError
testdir.makepyfile("""
def test_foo():
@@ -213,6 +214,83 @@ class TestFormatExplanation:
"*AssertionError*",
])
def test_fmt_simple(self):
expl = 'assert foo'
assert util.format_explanation(expl) == 'assert foo'
def test_fmt_where(self):
expl = '\n'.join(['assert 1',
'{1 = foo',
'} == 2'])
res = '\n'.join(['assert 1 == 2',
' + where 1 = foo'])
assert util.format_explanation(expl) == res
def test_fmt_and(self):
expl = '\n'.join(['assert 1',
'{1 = foo',
'} == 2',
'{2 = bar',
'}'])
res = '\n'.join(['assert 1 == 2',
' + where 1 = foo',
' + and 2 = bar'])
assert util.format_explanation(expl) == res
def test_fmt_where_nested(self):
expl = '\n'.join(['assert 1',
'{1 = foo',
'{foo = bar',
'}',
'} == 2'])
res = '\n'.join(['assert 1 == 2',
' + where 1 = foo',
' + where foo = bar'])
assert util.format_explanation(expl) == res
def test_fmt_newline(self):
expl = '\n'.join(['assert "foo" == "bar"',
'~- foo',
'~+ bar'])
res = '\n'.join(['assert "foo" == "bar"',
' - foo',
' + bar'])
assert util.format_explanation(expl) == res
def test_fmt_newline_escaped(self):
expl = '\n'.join(['assert foo == bar',
'baz'])
res = 'assert foo == bar\\nbaz'
assert util.format_explanation(expl) == res
def test_fmt_newline_before_where(self):
expl = '\n'.join(['the assertion message here',
'>assert 1',
'{1 = foo',
'} == 2',
'{2 = bar',
'}'])
res = '\n'.join(['the assertion message here',
'assert 1 == 2',
' + where 1 = foo',
' + and 2 = bar'])
assert util.format_explanation(expl) == res
def test_fmt_multi_newline_before_where(self):
expl = '\n'.join(['the assertion',
'~message here',
'>assert 1',
'{1 = foo',
'} == 2',
'{2 = bar',
'}'])
res = '\n'.join(['the assertion',
' message here',
'assert 1 == 2',
' + where 1 = foo',
' + and 2 = bar'])
assert util.format_explanation(expl) == res
def test_python25_compile_issue257(testdir):
testdir.makepyfile("""

View File

@@ -121,7 +121,56 @@ class TestAssertionRewrite:
def test_assert_already_has_message(self):
def f():
assert False, "something bad!"
assert getmsg(f) == "AssertionError: something bad!"
assert getmsg(f) == "AssertionError: something bad!\nassert False"
def test_assertion_message(self, testdir):
testdir.makepyfile("""
def test_foo():
assert 1 == 2, "The failure message"
""")
result = testdir.runpytest()
assert result.ret == 1
result.stdout.fnmatch_lines([
"*AssertionError*The failure message*",
"*assert 1 == 2*",
])
def test_assertion_message_multiline(self, testdir):
testdir.makepyfile("""
def test_foo():
assert 1 == 2, "A multiline\\nfailure message"
""")
result = testdir.runpytest()
assert result.ret == 1
result.stdout.fnmatch_lines([
"*AssertionError*A multiline*",
"*failure message*",
"*assert 1 == 2*",
])
def test_assertion_message_tuple(self, testdir):
testdir.makepyfile("""
def test_foo():
assert 1 == 2, (1, 2)
""")
result = testdir.runpytest()
assert result.ret == 1
result.stdout.fnmatch_lines([
"*AssertionError*%s*" % repr((1, 2)),
"*assert 1 == 2*",
])
def test_assertion_message_expr(self, testdir):
testdir.makepyfile("""
def test_foo():
assert 1 == 2, 1 + 2
""")
result = testdir.runpytest()
assert result.ret == 1
result.stdout.fnmatch_lines([
"*AssertionError*3*",
"*assert 1 == 2*",
])
def test_boolop(self):
def f():

View File

@@ -1,6 +1,7 @@
# note: py.io capture tests where copied from
# pylib 1.4.20.dev2 (rev 13d9af95547e)
from __future__ import with_statement
import pickle
import os
import sys
import py
@@ -743,6 +744,7 @@ class TestFDCapture:
cap.done()
pytest.raises(AttributeError, cap.suspend)
@contextlib.contextmanager
def saved_fd(fd):
new_fd = os.dup(fd)
@@ -750,6 +752,7 @@ def saved_fd(fd):
yield
finally:
os.dup2(new_fd, fd)
os.close(new_fd)
class TestStdCapture:
@@ -1022,3 +1025,24 @@ def test_error_attribute_issue555(testdir):
""")
reprec = testdir.inline_run()
reprec.assertoutcome(passed=1)
def test_dontreadfrominput_has_encoding(testdir):
testdir.makepyfile("""
import sys
def test_capattr():
# should not raise AttributeError
assert sys.stdout.encoding
assert sys.stderr.encoding
""")
reprec = testdir.inline_run()
reprec.assertoutcome(passed=1)
def test_pickling_and_unpickling_enocded_file():
# See https://bitbucket.org/hpk42/pytest/pull-request/194
# pickle.loads() raises infinite recursion if
# EncodedFile.__getattr__ is not implemented properly
ef = capture.EncodedFile(None, None)
ef_as_str = pickle.dumps(ef)
pickle.loads(ef_as_str)

View File

@@ -252,7 +252,7 @@ class TestPython:
assert_attr(tnode,
#classname="test_collect_error",
name="test_collect_error")
fnode = tnode.getElementsByTagName("failure")[0]
fnode = tnode.getElementsByTagName("error")[0]
assert_attr(fnode, message="collection failure")
assert "SyntaxError" in fnode.toxml()
@@ -489,7 +489,7 @@ def test_unicode_issue368(testdir):
log.pytest_sessionstart()
log._opentestcase(report)
log.append_failure(report)
log.append_collect_failure(report)
log.append_collect_error(report)
log.append_collect_skipped(report)
log.append_error(report)
report.longrepr = "filename", 1, ustr

View File

@@ -267,3 +267,21 @@ class TestPDB:
"*NameError*xxx*",
"*1 error*",
])
def test_enter_pdb_hook_is_called(self, testdir):
testdir.makeconftest("""
def pytest_enter_pdb():
print 'enter_pdb_hook'
""")
p1 = testdir.makepyfile("""
import pytest
def test_foo():
pytest.set_trace()
""")
child = testdir.spawn_pytest(str(p1))
child.expect("enter_pdb_hook")
child.send('c\n')
child.sendeof()
if child.isalive():
child.wait()

View File

@@ -678,3 +678,23 @@ class TestBooleanCondition:
*True123*
*1 xfail*
""")
def test_xfail_item(testdir):
# Ensure pytest.xfail works with non-Python Item
testdir.makeconftest("""
import pytest
class MyItem(pytest.Item):
nodeid = 'foo'
def runtest(self):
pytest.xfail("Expected Failure")
def pytest_collect_file(path, parent):
return MyItem("foo", parent)
""")
result = testdir.inline_run()
passed, skipped, failed = result.listoutcomes()
assert not failed
xfailed = [r for r in skipped if hasattr(r, 'wasxfail')]
assert xfailed