Compare commits

..

37 Commits
2.2.1 ... 2.2.2

Author SHA1 Message Date
holger krekel
87b4cb283f regen docs / examples for 2.2.2 2012-02-05 18:33:04 -05:00
holger krekel
83505b790d preparing release 2.2.2 2012-02-05 17:32:01 -05:00
Ronny Pfannschmidt
2ca6d9f039 no longer check if indirect metafunc.parametrize params are funcarg names 2012-02-03 16:54:00 +01:00
Ronny Pfannschmidt
87b8769680 readd CHANGELOG, since i accidentially killed it with mq 2012-02-03 17:11:42 +01:00
Ronny Pfannschmidt
78e7d7aed0 more quit collectonly shows only files and the number of tests in them 2012-02-03 16:56:06 +01:00
Ronny Pfannschmidt
68b353be0d create session.items before preparse, so collectonly wont break on preparse fail, fixes #115 2012-02-03 16:33:32 +01:00
holger krekel
a756dc8106 fix issue118 - typo 2012-02-02 06:24:12 -05:00
holger krekel
604e27658c add CHANGELOG for last commit 2012-02-01 09:06:38 -05:00
holger krekel
dfa273dc25 fix issue177 - actually perform session scope finalization 2012-02-01 08:52:34 -05:00
Ronny Pfannschmidt
5263656df6 kwarg support for reports, so xdist can deserialized extended reports 2012-01-20 19:50:45 +01:00
holger krekel
d88fe07377 fix link to pdf from contents page 2012-01-19 20:53:21 +01:00
holger krekel
2e23057804 remove nonsennse part of commit related to "mp" shortcut.
I wonder if introducing "mp" as a shortcut to monkeypatch
is a good idea, actually :)
2012-01-06 20:40:14 +00:00
holger krekel
303f49a5ad bump version, mention "mp" also in the docs and changelog 2012-01-06 20:37:18 +00:00
Ralf Schmitt
adbbd164ff update documentation for the new monkeypatch.chdir method 2012-01-06 15:25:57 +01:00
Ralf Schmitt
93424b0f9c add monkeypatch.chdir method 2012-01-04 12:43:19 +01:00
Ralf Schmitt
fb7706d4c7 make sure calling undo a second time doesn't change sys.path 2012-01-04 12:42:23 +01:00
Ralf Schmitt
4131923c0f test that a second undo doesn't change sys.path
also use a 'mp' funcarg that restores sys.path and the current working
directory in preparation for the monkeypatch.chdir method.
2012-01-04 12:40:57 +01:00
holger krekel
7b95af2400 only run test_unittest.py for the twisted/trial config 2011-12-28 17:43:56 +00:00
holger krekel
eb6481c663 fix trial test failure and simplify todo->xfail conversion 2011-12-28 17:35:38 +00:00
holger krekel
c126cac98d fix unittest/marker integration 2011-12-28 16:47:08 +00:00
holger krekel
e3a8b1e062 bump version 2011-12-28 15:49:35 +00:00
holger krekel
fa6d5bd15b work around an apparent python2.4/python2.5 bug with subprocess.Popen,
causing jenkins failures.  Apparently "os.environ.popitem(name, None)"
is not the same as::

    try:
        del os.environ[name]
    except KeyError:
        pass
2011-12-28 15:49:13 +00:00
holger krekel
f2c8a837af fix issue106: allow parametrize to be applied per-class/per-module 2011-12-28 15:47:19 +00:00
holger krekel
ccc1b21ebd internally keep multiple applications of the same markers as separate
entities such that the new iter() API can iterate over pytest.mark
function attributes, getting all such applications.  See added example
for more info.
2011-12-28 15:47:18 +00:00
holger krekel
85f2a78005 fix wrongly committed line 2011-12-28 07:57:19 +00:00
holger krekel
e21202b730 fix Jenkins test failures 2011-12-27 21:03:15 +00:00
holger krekel
dc0535f7d5 fix typo, thanks jurko 2011-12-20 14:12:12 +00:00
holger krekel
f2791988f9 fix issue102: report more useful errors and hints for when a
test directory was renamed and some pyc/__pycache__ remain
2011-12-20 12:20:59 +00:00
Benjamin Peterson
8e83af1c33 fix spacing 2011-12-19 14:23:39 -05:00
Benjamin Peterson
268c051eba propogate current PYTHONPATH 2011-12-19 12:02:07 -05:00
Benjamin Peterson
03cb37b1eb use an exception more consistent across python versions 2011-12-19 11:56:22 -05:00
holger krekel
d5c3265763 fix issue101: wrong args to unittest.TestCase test function now
produce better output
2011-12-18 23:01:39 +00:00
holger krekel
13e0340350 use newer distribute_setup.py 2011-12-18 19:01:43 +00:00
holger krekel
5093d8b925 fix test to actually mean something useful (thanks Jurko) 2011-12-18 10:56:39 +00:00
holger krekel
40187ec9bb robustify monkeypatch 2011-12-16 22:41:23 +00:00
holger krekel
f5f8695587 add 2.2.1 announce to index 2011-12-16 12:12:23 +00:00
holger krekel
27f5213718 Added tag 2.2.1 for changeset 3da8cec6c532 2011-12-16 11:56:44 +00:00
42 changed files with 562 additions and 237 deletions

View File

@@ -45,3 +45,4 @@ e5e1746a197f0398356a43fbe2eebac9690f795d 2.1.0
5864412c6f3c903384243bd315639d101d7ebc67 2.1.2
12a05d59249f80276e25fd8b96e8e545b1332b7a 2.1.3
1522710369337d96bf9568569d5f0ca9b38a74e0 2.2.0
3da8cec6c5326ed27c144c9b6d7a64a648370005 2.2.1

View File

@@ -1,3 +1,23 @@
Changes between 2.2.1 and 2.2.2
----------------------------------------
- fix issue101: wrong args to unittest.TestCase test function now
produce better output
- fix issue102: report more useful errors and hints for when a
test directory was renamed and some pyc/__pycache__ remain
- fix issue106: allow parametrize to be applied multiple times
e.g. from module, class and at function level.
- fix issue107: actually perform session scope finalization
- don't check in parametrize if indirect parameters are funcarg names
- add chdir method to monkeypatch funcarg
- fix crash resulting from calling monkeypatch undo a second time
- fix issue115: make --collectonly robust against early failure
(missing files/directories)
- "-qq --collectonly" now shows only files and the number of tests in them
- "-q --collectonly" now shows test ids
- allow adding of attributes to test reports such that it also works
with distributed testing (no upgrade of pytest-xdist needed)
Changes between 2.2.0 and 2.2.1
----------------------------------------

View File

@@ -1,2 +1,2 @@
#
__version__ = '2.2.1'
__version__ = '2.2.2'

View File

@@ -410,6 +410,7 @@ class Session(FSCollector):
self._notfound = []
self._initialpaths = set()
self._initialparts = []
self.items = items = []
for arg in args:
parts = self._parsearg(arg)
self._initialparts.append(parts)
@@ -425,7 +426,6 @@ class Session(FSCollector):
if not genitems:
return rep.result
else:
self.items = items = []
if rep.passed:
for node in rep.result:
self.items.extend(self.genitems(node))

View File

@@ -191,8 +191,7 @@ class MarkDecorator:
holder = MarkInfo(self.markname, self.args, self.kwargs)
setattr(func, self.markname, holder)
else:
holder.kwargs.update(self.kwargs)
holder.args += self.args
holder.add(self.args, self.kwargs)
return func
kw = self.kwargs.copy()
kw.update(kwargs)
@@ -208,27 +207,20 @@ class MarkInfo:
self.args = args
#: keyword argument dictionary, empty if nothing specified
self.kwargs = kwargs
self._arglist = [(args, kwargs.copy())]
def __repr__(self):
return "<MarkInfo %r args=%r kwargs=%r>" % (
self.name, self.args, self.kwargs)
def pytest_itemcollected(item):
if not isinstance(item, pytest.Function):
return
try:
func = item.obj.__func__
except AttributeError:
func = getattr(item.obj, 'im_func', item.obj)
pyclasses = (pytest.Class, pytest.Module)
for node in item.listchain():
if isinstance(node, pyclasses):
marker = getattr(node.obj, 'pytestmark', None)
if marker is not None:
if isinstance(marker, list):
for mark in marker:
mark(func)
else:
marker(func)
node = node.parent
item.keywords.update(py.builtin._getfuncdict(func))
def add(self, args, kwargs):
""" add a MarkInfo with the given args and kwargs. """
self._arglist.append((args, kwargs))
self.args += args
self.kwargs.update(kwargs)
def __iter__(self):
""" yield MarkInfo objects each relating to a marking-call. """
for args, kwargs in self._arglist:
yield MarkInfo(self.name, args, kwargs)

View File

@@ -13,6 +13,7 @@ def pytest_funcarg__monkeypatch(request):
monkeypatch.setenv(name, value, prepend=False)
monkeypatch.delenv(name, value, raising=True)
monkeypatch.syspath_prepend(path)
monkeypatch.chdir(path)
All modifications will be undone after the requesting
test function has finished. The ``raising``
@@ -30,6 +31,7 @@ class monkeypatch:
def __init__(self):
self._setattr = []
self._setitem = []
self._cwd = None
def setattr(self, obj, name, value, raising=True):
""" set attribute ``name`` on ``obj`` to ``value``, by default
@@ -83,6 +85,17 @@ class monkeypatch:
self._savesyspath = sys.path[:]
sys.path.insert(0, str(path))
def chdir(self, path):
""" change the current working directory to the specified path
path can be a string or a py.path.local object
"""
if self._cwd is None:
self._cwd = os.getcwd()
if hasattr(path, "chdir"):
path.chdir()
else:
os.chdir(path)
def undo(self):
""" undo previous changes. This call consumes the
undo stack. Calling it a second time has no effect unless
@@ -95,9 +108,17 @@ class monkeypatch:
self._setattr[:] = []
for dictionary, name, value in self._setitem:
if value is notset:
del dictionary[name]
try:
del dictionary[name]
except KeyError:
pass # was already deleted, so we have the desired state
else:
dictionary[name] = value
self._setitem[:] = []
if hasattr(self, '_savesyspath'):
sys.path[:] = self._savesyspath
del self._savesyspath
if self._cwd is not None:
os.chdir(self._cwd)
self._cwd = None

View File

@@ -33,7 +33,8 @@ def pytest_generate_tests(metafunc):
param = metafunc.function.parametrize
except AttributeError:
return
metafunc.parametrize(*param.args, **param.kwargs)
for p in param:
metafunc.parametrize(*p.args, **p.kwargs)
def pytest_configure(config):
config.addinivalue_line("markers",
@@ -220,6 +221,7 @@ class PyCollectorMixin(PyobjMixin, pytest.Collector):
module = self.getparent(Module).obj
clscol = self.getparent(Class)
cls = clscol and clscol.obj or None
transfer_markers(funcobj, cls, module)
metafunc = Metafunc(funcobj, config=self.config,
cls=cls, module=module)
gentesthook = self.config.hook.pytest_generate_tests
@@ -239,6 +241,19 @@ class PyCollectorMixin(PyobjMixin, pytest.Collector):
l.append(function)
return l
def transfer_markers(funcobj, cls, mod):
# XXX this should rather be code in the mark plugin or the mark
# plugin should merge with the python plugin.
for holder in (cls, mod):
try:
pytestmark = holder.pytestmark
except AttributeError:
continue
if isinstance(pytestmark, list):
for mark in pytestmark:
mark(funcobj)
else:
pytestmark(funcobj)
class Module(pytest.File, PyCollectorMixin):
def _getobj(self):
@@ -259,7 +274,8 @@ class Module(pytest.File, PyCollectorMixin):
" %s\n"
"which is not the same as the test file we want to collect:\n"
" %s\n"
"HINT: use a unique basename for your test file modules"
"HINT: remove __pycache__ / .pyc files and/or use a "
"unique basename for your test file modules"
% e.args
)
#print "imported test module", mod
@@ -558,7 +574,7 @@ class CallSpec2(object):
@property
def id(self):
return "-".join(filter(None, self._idlist))
return "-".join(map(str, filter(None, self._idlist)))
def setmulti(self, valtype, argnames, valset, id):
for arg,val in zip(argnames, valset):
@@ -613,9 +629,11 @@ class Metafunc:
if not isinstance(argnames, (tuple, list)):
argnames = (argnames,)
argvalues = [(val,) for val in argvalues]
for arg in argnames:
if arg not in self.funcargnames:
raise ValueError("%r has no argument %r" %(self.function, arg))
if not indirect:
#XXX should we also check for the opposite case?
for arg in argnames:
if arg not in self.funcargnames:
raise ValueError("%r has no argument %r" %(self.function, arg))
valtype = indirect and "params" or "funcargs"
if not ids:
idmaker = IDMaker()

View File

@@ -47,6 +47,8 @@ def pytest_terminal_summary(terminalreporter):
def pytest_sessionstart(session):
session._setupstate = SetupState()
def pytest_sessionfinish(session):
session._setupstate.teardown_all()
class NodeInfo:
def __init__(self, location):
@@ -141,6 +143,10 @@ def getslaveinfoline(node):
return s
class BaseReport(object):
def __init__(self, **kw):
self.__dict__.update(kw)
def toterminal(self, out):
longrepr = self.longrepr
if hasattr(self, 'node'):
@@ -190,7 +196,7 @@ class TestReport(BaseReport):
they fail).
"""
def __init__(self, nodeid, location,
keywords, outcome, longrepr, when, sections=(), duration=0):
keywords, outcome, longrepr, when, sections=(), duration=0, **extra):
#: normalized collection node id
self.nodeid = nodeid
@@ -219,6 +225,8 @@ class TestReport(BaseReport):
#: time it took to run just the test
self.duration = duration
self.__dict__.update(extra)
def __repr__(self):
return "<TestReport %r when=%r outcome=%r>" % (
self.nodeid, self.when, self.outcome)
@@ -226,9 +234,10 @@ class TestReport(BaseReport):
class TeardownErrorReport(BaseReport):
outcome = "failed"
when = "teardown"
def __init__(self, longrepr):
def __init__(self, longrepr, **extra):
self.longrepr = longrepr
self.sections = []
self.__dict__.update(extra)
def pytest_make_collect_report(collector):
call = CallInfo(collector._memocollect, "memocollect")
@@ -250,12 +259,13 @@ def pytest_make_collect_report(collector):
getattr(call, 'result', None))
class CollectReport(BaseReport):
def __init__(self, nodeid, outcome, longrepr, result, sections=()):
def __init__(self, nodeid, outcome, longrepr, result, sections=(), **extra):
self.nodeid = nodeid
self.outcome = outcome
self.longrepr = longrepr
self.result = result or []
self.sections = list(sections)
self.__dict__.update(extra)
@property
def location(self):

View File

@@ -282,10 +282,18 @@ class TerminalReporter:
# we take care to leave out Instances aka ()
# because later versions are going to get rid of them anyway
if self.config.option.verbose < 0:
for item in items:
nodeid = item.nodeid
nodeid = nodeid.replace("::()::", "::")
self._tw.line(nodeid)
if self.config.option.verbose < -1:
counts = {}
for item in items:
name = item.nodeid.split('::', 1)[0]
counts[name] = counts.get(name, 0) + 1
for name, count in sorted(counts.items()):
self._tw.line("%s: %d" % (name, count))
else:
for item in items:
nodeid = item.nodeid
nodeid = nodeid.replace("::()::", "::")
self._tw.line(nodeid)
return
stack = []
indent = ""

View File

@@ -2,6 +2,9 @@
import pytest, py
import sys, pdb
# for transfering markers
from _pytest.python import transfer_markers
def pytest_pycollect_makeitem(collector, name, obj):
unittest = sys.modules.get('unittest')
if unittest is None:
@@ -19,7 +22,14 @@ def pytest_pycollect_makeitem(collector, name, obj):
class UnitTestCase(pytest.Class):
def collect(self):
loader = py.std.unittest.TestLoader()
module = self.getparent(pytest.Module).obj
cls = self.obj
for name in loader.getTestCaseNames(self.obj):
x = getattr(self.obj, name)
funcobj = getattr(x, 'im_func', x)
transfer_markers(funcobj, cls, module)
if hasattr(funcobj, 'todo'):
pytest.mark.xfail(reason=str(funcobj.todo))(funcobj)
yield TestCaseFunction(name, parent=self)
def setup(self):
@@ -37,12 +47,6 @@ class UnitTestCase(pytest.Class):
class TestCaseFunction(pytest.Function):
_excinfo = None
def __init__(self, name, parent):
super(TestCaseFunction, self).__init__(name, parent)
if hasattr(self._obj, 'todo'):
getattr(self._obj, 'im_func', self._obj).xfail = \
pytest.mark.xfail(reason=str(self._obj.todo))
def setup(self):
self._testcase = self.parent.obj(self.name)
self._obj = getattr(self._testcase, self.name)
@@ -108,7 +112,10 @@ class TestCaseFunction(pytest.Function):
def _prunetraceback(self, excinfo):
pytest.Function._prunetraceback(self, excinfo)
excinfo.traceback = excinfo.traceback.filter(lambda x:not x.frame.f_globals.get('__unittest'))
traceback = excinfo.traceback.filter(
lambda x:not x.frame.f_globals.get('__unittest'))
if traceback:
excinfo.traceback = traceback
@pytest.mark.tryfirst
def pytest_runtest_makereport(item, call):

View File

@@ -46,7 +46,7 @@ except ImportError:
args = [quote(arg) for arg in args]
return os.spawnl(os.P_WAIT, sys.executable, *args) == 0
DEFAULT_VERSION = "0.6.19"
DEFAULT_VERSION = "0.6.24"
DEFAULT_URL = "http://pypi.python.org/packages/source/d/distribute/"
SETUPTOOLS_FAKED_VERSION = "0.6c11"

View File

@@ -5,6 +5,8 @@ Release announcements
.. toctree::
:maxdepth: 2
release-2.2.2
release-2.2.1
release-2.2.0
release-2.1.3
release-2.1.2

View File

@@ -0,0 +1,42 @@
pytest-2.2.2: bug fixes
===========================================================================
pytest-2.2.2 is a minor backward-compatible release of the versatile py.test
testing tool. It contains bug fixes and a few refinements particularly
to reporting with "--collectonly", see below for betails.
For general information see here:
http://pytest.org/
To install or upgrade pytest:
pip install -U pytest # or
easy_install -U pytest
Special thanks for helping on this release to Ronny Pfannschmidt
and Ralf Schmitt and the contributors of issues.
best,
holger krekel
Changes between 2.2.1 and 2.2.2
----------------------------------------
- fix issue101: wrong args to unittest.TestCase test function now
produce better output
- fix issue102: report more useful errors and hints for when a
test directory was renamed and some pyc/__pycache__ remain
- fix issue106: allow parametrize to be applied multiple times
e.g. from module, class and at function level.
- fix issue107: actually perform session scope finalization
- don't check in parametrize if indirect parameters are funcarg names
- add chdir method to monkeypatch funcarg
- fix crash resulting from calling monkeypatch undo a second time
- fix issue115: make --collectonly robust against early failure
(missing files/directories)
- "-qq --collectonly" now shows only files and the number of tests in them
- "-q --collectonly" now shows test ids
- allow adding of attributes to test reports such that it also works
with distributed testing (no upgrade of pytest-xdist needed)

View File

@@ -23,7 +23,7 @@ you will see the return value of the function call::
$ py.test test_assert1.py
=========================== test session starts ============================
platform darwin -- Python 2.7.1 -- pytest-2.2.1
platform darwin -- Python 2.7.1 -- pytest-2.2.2
collecting ... collected 1 items
test_assert1.py F
@@ -105,7 +105,7 @@ if you run this module::
$ py.test test_assert2.py
=========================== test session starts ============================
platform darwin -- Python 2.7.1 -- pytest-2.2.1
platform darwin -- Python 2.7.1 -- pytest-2.2.2
collecting ... collected 1 items
test_assert2.py F
@@ -124,7 +124,7 @@ if you run this module::
E '5'
test_assert2.py:5: AssertionError
========================= 1 failed in 0.02 seconds =========================
========================= 1 failed in 0.03 seconds =========================
Special comparisons are done for a number of cases:

View File

@@ -28,7 +28,7 @@ You can ask for available builtin or project-custom
$ py.test --funcargs
=========================== test session starts ============================
platform darwin -- Python 2.7.1 -- pytest-2.2.1
platform darwin -- Python 2.7.1 -- pytest-2.2.2
collected 0 items
pytestconfig
the pytest config object with access to command line opts.
@@ -60,6 +60,7 @@ You can ask for available builtin or project-custom
monkeypatch.setenv(name, value, prepend=False)
monkeypatch.delenv(name, value, raising=True)
monkeypatch.syspath_prepend(path)
monkeypatch.chdir(path)
All modifications will be undone after the requesting
test function has finished. The ``raising``
@@ -75,5 +76,7 @@ You can ask for available builtin or project-custom
See http://docs.python.org/library/warnings.html for information
on warning categories.
cov
A pytest funcarg that provides access to the underlying coverage object.
============================= in 0.00 seconds =============================
============================= in 0.01 seconds =============================

View File

@@ -64,7 +64,7 @@ of the failing function and hide the other one::
$ py.test
=========================== test session starts ============================
platform darwin -- Python 2.7.1 -- pytest-2.2.1
platform darwin -- Python 2.7.1 -- pytest-2.2.2
collecting ... 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 ------------------------------
setting up <function test_func2 at 0x101314c80>
setting up <function test_func2 at 0x1013230c8>
==================== 1 failed, 1 passed in 0.03 seconds ====================
Accessing captured output from a test function

View File

@@ -1,10 +1,10 @@
.. _toc:
Full pytest documenation
========================
Full pytest documentation
===========================
`Download latest version as PDF <http://media.readthedocs.org/pdf/pytest/latest/pytest.pdf>`_
`Download latest version as PDF <pytest.pdf>`_
.. `Download latest version as EPUB <http://media.readthedocs.org/epub/pytest/latest/pytest.epub>`_

View File

@@ -94,7 +94,7 @@ Builtin configuration file options
[seq] matches any character in seq
[!seq] matches any char not in seq
Default patterns are ``.* _* CVS {args}``. Setting a ``norecurse``
Default patterns are ``.* _* CVS {args}``. Setting a ``norecursedir``
replaces the default. Here is an example of how to avoid
certain directories::

View File

@@ -44,10 +44,10 @@ then you can just invoke ``py.test`` without command line options::
$ py.test
=========================== test session starts ============================
platform darwin -- Python 2.7.1 -- pytest-2.2.1
platform darwin -- Python 2.7.1 -- pytest-2.2.2
collecting ... collected 1 items
mymodule.py .
========================= 1 passed in 0.05 seconds =========================
========================= 1 passed in 0.51 seconds =========================
[?1034h

View File

@@ -26,7 +26,7 @@ You can then restrict a test run to only run tests marked with ``webtest``::
$ py.test -v -m webtest
=========================== test session starts ============================
platform darwin -- Python 2.7.1 -- pytest-2.2.1 -- /Users/hpk/venv/1/bin/python
platform darwin -- Python 2.7.1 -- pytest-2.2.2 -- /Users/hpk/venv/0/bin/python
collecting ... collected 2 items
test_server.py:3: test_send_http PASSED
@@ -38,13 +38,13 @@ Or the inverse, running all tests except the webtest ones::
$ py.test -v -m "not webtest"
=========================== test session starts ============================
platform darwin -- Python 2.7.1 -- pytest-2.2.1 -- /Users/hpk/venv/1/bin/python
platform darwin -- Python 2.7.1 -- pytest-2.2.2 -- /Users/hpk/venv/0/bin/python
collecting ... collected 2 items
test_server.py:6: test_something_quick PASSED
================= 1 tests deselected by "-m 'not webtest'" =================
================== 1 passed, 1 deselected in 0.01 seconds ==================
================== 1 passed, 1 deselected in 0.02 seconds ==================
Registering markers
-------------------------------------
@@ -134,6 +134,7 @@ You can also set a module level marker::
in which case it will be applied to all functions and
methods defined in the module.
Using ``-k TEXT`` to select tests
----------------------------------------------------
@@ -142,7 +143,7 @@ the given argument::
$ py.test -k send_http # running with the above defined examples
=========================== test session starts ============================
platform darwin -- Python 2.7.1 -- pytest-2.2.1
platform darwin -- Python 2.7.1 -- pytest-2.2.2
collecting ... collected 4 items
test_server.py .
@@ -154,7 +155,7 @@ And you can also run all tests except the ones that match the keyword::
$ py.test -k-send_http
=========================== test session starts ============================
platform darwin -- Python 2.7.1 -- pytest-2.2.1
platform darwin -- Python 2.7.1 -- pytest-2.2.2
collecting ... collected 4 items
test_mark_classlevel.py ..
@@ -167,13 +168,13 @@ Or to only select the class::
$ py.test -kTestClass
=========================== test session starts ============================
platform darwin -- Python 2.7.1 -- pytest-2.2.1
platform darwin -- Python 2.7.1 -- pytest-2.2.2
collecting ... collected 4 items
test_mark_classlevel.py ..
=================== 2 tests deselected by '-kTestClass' ====================
================== 2 passed, 2 deselected in 0.02 seconds ==================
================== 2 passed, 2 deselected in 0.03 seconds ==================
.. _`adding a custom marker from a plugin`:
@@ -222,7 +223,7 @@ the test needs::
$ py.test -E stage2
=========================== test session starts ============================
platform darwin -- Python 2.7.1 -- pytest-2.2.1
platform darwin -- Python 2.7.1 -- pytest-2.2.2
collecting ... collected 1 items
test_someenv.py s
@@ -233,12 +234,12 @@ and here is one that specifies exactly the environment needed::
$ py.test -E stage1
=========================== test session starts ============================
platform darwin -- Python 2.7.1 -- pytest-2.2.1
platform darwin -- Python 2.7.1 -- pytest-2.2.2
collecting ... collected 1 items
test_someenv.py .
========================= 1 passed in 0.01 seconds =========================
========================= 1 passed in 0.02 seconds =========================
The ``--markers`` option always gives you a list of available markers::
@@ -254,4 +255,43 @@ The ``--markers`` option always gives you a list of available markers::
@pytest.mark.tryfirst: mark a hook implementation function such that the plugin machinery will try to call it first/as early as possible.
@pytest.mark.trylast: mark a hook implementation function such that the plugin machinery will try to call it last/as late as possible.
Reading markers which were set from multiple places
----------------------------------------------------
.. versionadded: 2.2.2
If you are heavily using markers in your test suite you may encounter the case where a marker is applied several times to a test function. From plugin
code you can read over all such settings. Example::
# content of test_mark_three_times.py
import pytest
pytestmark = pytest.mark.glob("module", x=1)
@pytest.mark.glob("class", x=2)
class TestClass:
@pytest.mark.glob("function", x=3)
def test_something(self):
pass
Here we have the marker "glob" applied three times to the same
test function. From a conftest file we can read it like this::
# content of conftest.py
def pytest_runtest_setup(item):
g = getattr(item.obj, 'glob', None)
if g is not None:
for info in g:
print ("glob args=%s kwargs=%s" %(info.args, info.kwargs))
Let's run this without capturing output and see what we get::
$ py.test -q -s
collecting ... collected 2 items
..
2 passed in 0.02 seconds
glob args=('function',) kwargs={'x': 3}
glob args=('class',) kwargs={'x': 2}
glob args=('module',) kwargs={'x': 1}

View File

@@ -49,7 +49,7 @@ You can now run the test::
$ py.test test_sample.py
=========================== test session starts ============================
platform darwin -- Python 2.7.1 -- pytest-2.2.1
platform darwin -- Python 2.7.1 -- pytest-2.2.2
collecting ... collected 1 items
test_sample.py F
@@ -57,7 +57,7 @@ You can now run the test::
================================= FAILURES =================================
_______________________________ test_answer ________________________________
mysetup = <conftest.MySetup instance at 0x10131c098>
mysetup = <conftest.MySetup instance at 0x101322fc8>
def test_answer(mysetup):
app = mysetup.myapp()
@@ -66,7 +66,7 @@ You can now run the test::
E assert 54 == 42
test_sample.py:4: AssertionError
========================= 1 failed in 0.02 seconds =========================
========================= 1 failed in 0.72 seconds =========================
This means that our ``mysetup`` object was successfully instantiated
and ``mysetup.app()`` returned an initialized ``MyApp`` instance.
@@ -122,12 +122,12 @@ Running it yields::
$ py.test test_ssh.py -rs
=========================== test session starts ============================
platform darwin -- Python 2.7.1 -- pytest-2.2.1
platform darwin -- Python 2.7.1 -- pytest-2.2.2
collecting ... collected 1 items
test_ssh.py s
========================= short test summary info ==========================
SKIP [1] /Users/hpk/tmp/doc-exec-44/conftest.py:22: specify ssh host with --ssh
SKIP [1] /Users/hpk/tmp/doc-exec-153/conftest.py:22: specify ssh host with --ssh
======================== 1 skipped in 0.02 seconds =========================

View File

@@ -27,7 +27,7 @@ now execute the test specification::
nonpython $ py.test test_simple.yml
=========================== test session starts ============================
platform darwin -- Python 2.7.1 -- pytest-2.2.1
platform darwin -- Python 2.7.1 -- pytest-2.2.2
collecting ... collected 2 items
test_simple.yml .F
@@ -37,7 +37,7 @@ now execute the test specification::
usecase execution failed
spec failed: 'some': 'other'
no further details known at this point.
==================== 1 failed, 1 passed in 0.09 seconds ====================
==================== 1 failed, 1 passed in 0.48 seconds ====================
You get one dot for the passing ``sub1: sub1`` check and one failure.
Obviously in the above ``conftest.py`` you'll want to implement a more
@@ -56,7 +56,7 @@ consulted when reporting in ``verbose`` mode::
nonpython $ py.test -v
=========================== test session starts ============================
platform darwin -- Python 2.7.1 -- pytest-2.2.1 -- /Users/hpk/venv/1/bin/python
platform darwin -- Python 2.7.1 -- pytest-2.2.2 -- /Users/hpk/venv/0/bin/python
collecting ... collected 2 items
test_simple.yml:1: usecase: ok PASSED
@@ -67,17 +67,17 @@ consulted when reporting in ``verbose`` mode::
usecase execution failed
spec failed: 'some': 'other'
no further details known at this point.
==================== 1 failed, 1 passed in 0.09 seconds ====================
==================== 1 failed, 1 passed in 0.10 seconds ====================
While developing your custom test collection and execution it's also
interesting to just look at the collection tree::
nonpython $ py.test --collectonly
=========================== test session starts ============================
platform darwin -- Python 2.7.1 -- pytest-2.2.1
platform darwin -- Python 2.7.1 -- pytest-2.2.2
collecting ... collected 2 items
<YamlFile 'test_simple.yml'>
<YamlItem 'ok'>
<YamlItem 'hello'>
============================= in 0.08 seconds =============================
============================= in 0.18 seconds =============================

View File

@@ -96,7 +96,7 @@ This means that we only run 2 tests if we do not pass ``--all``::
$ py.test -q test_compute.py
collecting ... collected 2 items
..
2 passed in 0.02 seconds
2 passed in 0.03 seconds
We run only two computations, so we see two dots.
let's run the full monty::
@@ -114,7 +114,7 @@ let's run the full monty::
E assert 4 < 4
test_compute.py:3: AssertionError
1 failed, 4 passed in 0.03 seconds
1 failed, 4 passed in 0.05 seconds
As expected when running the full range of ``param1`` values
we'll get an error on the last one.
@@ -154,7 +154,7 @@ this is a fully self-contained example which you can run with::
$ py.test test_scenarios.py
=========================== test session starts ============================
platform darwin -- Python 2.7.1 -- pytest-2.2.1
platform darwin -- Python 2.7.1 -- pytest-2.2.2
collecting ... collected 2 items
test_scenarios.py ..
@@ -166,7 +166,7 @@ If you just collect tests you'll also nicely see 'advanced' and 'basic' as varia
$ py.test --collectonly test_scenarios.py
=========================== test session starts ============================
platform darwin -- Python 2.7.1 -- pytest-2.2.1
platform darwin -- Python 2.7.1 -- pytest-2.2.2
collecting ... collected 2 items
<Module 'test_scenarios.py'>
<Class 'TestSampleWithScenarios'>
@@ -174,7 +174,7 @@ If you just collect tests you'll also nicely see 'advanced' and 'basic' as varia
<Function 'test_demo[basic]'>
<Function 'test_demo[advanced]'>
============================= in 0.01 seconds =============================
============================= in 0.05 seconds =============================
Deferring the setup of parametrized resources
---------------------------------------------------
@@ -222,7 +222,7 @@ Let's first see how it looks like at collection time::
$ py.test test_backends.py --collectonly
=========================== test session starts ============================
platform darwin -- Python 2.7.1 -- pytest-2.2.1
platform darwin -- Python 2.7.1 -- pytest-2.2.2
collecting ... collected 2 items
<Module 'test_backends.py'>
<Function 'test_db_initialized[d1]'>
@@ -238,7 +238,7 @@ And then when we run the test::
================================= FAILURES =================================
_________________________ test_db_initialized[d2] __________________________
db = <conftest.DB2 instance at 0x10131c6c8>
db = <conftest.DB2 instance at 0x101323710>
def test_db_initialized(db):
# a dummy test
@@ -247,7 +247,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.02 seconds
1 failed, 1 passed in 0.03 seconds
The first invocation with ``db == "DB1"`` passed while the second with ``db == "DB2"`` failed. Our ``pytest_funcarg__db`` factory 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.
@@ -295,7 +295,7 @@ argument sets to use for each test function. Let's run it::
================================= FAILURES =================================
________________________ TestClass.test_equals[1-2] ________________________
self = <test_parametrize.TestClass instance at 0x101320200>, a = 1, b = 2
self = <test_parametrize.TestClass instance at 0x101326368>, a = 1, b = 2
def test_equals(self, a, b):
> assert a == b
@@ -326,4 +326,4 @@ Running it results in some skips if we don't have all the python interpreters in
========================= short test summary info ==========================
SKIP [24] /Users/hpk/p/pytest/doc/example/multipython.py:36: 'python2.8' not found
SKIP [24] /Users/hpk/p/pytest/doc/example/multipython.py:36: 'python2.4' not found
27 passed, 48 skipped in 3.01 seconds
27 passed, 48 skipped in 7.76 seconds

View File

@@ -43,7 +43,7 @@ then the test collection looks like this::
$ py.test --collectonly
=========================== test session starts ============================
platform darwin -- Python 2.7.1 -- pytest-2.2.1
platform darwin -- Python 2.7.1 -- pytest-2.2.2
collecting ... collected 2 items
<Module 'check_myapp.py'>
<Class 'CheckMyApp'>
@@ -82,7 +82,7 @@ You can always peek at the collection tree without running tests like this::
. $ py.test --collectonly pythoncollection.py
=========================== test session starts ============================
platform darwin -- Python 2.7.1 -- pytest-2.2.1
platform darwin -- Python 2.7.1 -- pytest-2.2.2
collecting ... collected 3 items
<Module 'pythoncollection.py'>
<Function 'test_function'>

View File

@@ -13,7 +13,7 @@ get on the terminal - we are working on that):
assertion $ py.test failure_demo.py
=========================== test session starts ============================
platform darwin -- Python 2.7.1 -- pytest-2.2.1
platform darwin -- Python 2.7.1 -- pytest-2.2.2
collecting ... collected 39 items
failure_demo.py FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
@@ -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 0x101356250>
self = <failure_demo.TestFailing object at 0x101490690>
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 f at 0x101328848>()
E + and 43 = <function g at 0x1013288c0>()
E + where 42 = <function f at 0x101462b90>()
E + and 43 = <function g at 0x101462c08>()
failure_demo.py:28: AssertionError
____________________ TestFailing.test_simple_multiline _____________________
self = <failure_demo.TestFailing object at 0x101356810>
self = <failure_demo.TestFailing object at 0x101490b10>
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 0x101356a10>
self = <failure_demo.TestFailing object at 0x101490210>
def test_not(self):
def f():
return 42
> assert not f()
E assert not 42
E + where 42 = <function f at 0x101328758>()
E + where 42 = <function f at 0x101462aa0>()
failure_demo.py:38: AssertionError
_________________ TestSpecialisedExplanations.test_eq_text _________________
self = <failure_demo.TestSpecialisedExplanations object at 0x101356c50>
self = <failure_demo.TestSpecialisedExplanations object at 0x101490a10>
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 0x1013542d0>
self = <failure_demo.TestSpecialisedExplanations object at 0x10148d9d0>
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 0x101354590>
self = <failure_demo.TestSpecialisedExplanations object at 0x10148d590>
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 0x101354710>
self = <failure_demo.TestSpecialisedExplanations object at 0x10148dc90>
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 0x1013529d0>
self = <failure_demo.TestSpecialisedExplanations object at 0x10148d910>
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 0x101352750>
self = <failure_demo.TestSpecialisedExplanations object at 0x10148b9d0>
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 0x101352ad0>
self = <failure_demo.TestSpecialisedExplanations object at 0x10148b750>
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 0x101352b90>
self = <failure_demo.TestSpecialisedExplanations object at 0x10148bdd0>
def test_eq_dict(self):
> assert {'a': 0, 'b': 1} == {'a': 0, 'b': 2}
@@ -191,7 +191,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 0x101352fd0>
self = <failure_demo.TestSpecialisedExplanations object at 0x10148b1d0>
def test_eq_set(self):
> assert set([0, 10, 11, 12]) == set([0, 20, 21])
@@ -207,7 +207,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 0x101352b50>
self = <failure_demo.TestSpecialisedExplanations object at 0x10148bf10>
def test_eq_longer_list(self):
> assert [1,2] == [1,2,3]
@@ -217,7 +217,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 0x1013522d0>
self = <failure_demo.TestSpecialisedExplanations object at 0x10148b390>
def test_in_list(self):
> assert 1 in [0, 2, 3, 4, 5]
@@ -226,7 +226,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 0x101351390>
self = <failure_demo.TestSpecialisedExplanations object at 0x101483e50>
def test_not_in_text_multiline(self):
text = 'some multiline\ntext\nwhich\nincludes foo\nand a\ntail'
@@ -244,7 +244,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 0x101351410>
self = <failure_demo.TestSpecialisedExplanations object at 0x101483c10>
def test_not_in_text_single(self):
text = 'single foo line'
@@ -257,7 +257,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 0x101351510>
self = <failure_demo.TestSpecialisedExplanations object at 0x101483ed0>
def test_not_in_text_single_long(self):
text = 'head ' * 50 + 'foo ' + 'tail ' * 20
@@ -270,7 +270,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 0x101351a10>
self = <failure_demo.TestSpecialisedExplanations object at 0x101483310>
def test_not_in_text_single_long_term(self):
text = 'head ' * 50 + 'f'*70 + 'tail ' * 20
@@ -289,7 +289,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.Foo object at 0x101351b50>.b
E + where 1 = <failure_demo.Foo object at 0x101483f50>.b
failure_demo.py:101: AssertionError
_________________________ test_attribute_instance __________________________
@@ -299,8 +299,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.Foo object at 0x101351810>.b
E + where <failure_demo.Foo object at 0x101351810> = <class 'failure_demo.Foo'>()
E + where 1 = <failure_demo.Foo object at 0x101483210>.b
E + where <failure_demo.Foo object at 0x101483210> = <class 'failure_demo.Foo'>()
failure_demo.py:107: AssertionError
__________________________ test_attribute_failure __________________________
@@ -316,7 +316,7 @@ get on the terminal - we are working on that):
failure_demo.py:116:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <failure_demo.Foo object at 0x101351c50>
self = <failure_demo.Foo object at 0x101483450>
def _get_b(self):
> raise Exception('Failed to get attrib')
@@ -332,15 +332,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.Foo object at 0x101351f10>.b
E + where <failure_demo.Foo object at 0x101351f10> = <class 'failure_demo.Foo'>()
E + and 2 = <failure_demo.Bar object at 0x1013519d0>.b
E + where <failure_demo.Bar object at 0x1013519d0> = <class 'failure_demo.Bar'>()
E + where 1 = <failure_demo.Foo object at 0x101483150>.b
E + where <failure_demo.Foo object at 0x101483150> = <class 'failure_demo.Foo'>()
E + and 2 = <failure_demo.Bar object at 0x101483350>.b
E + where <failure_demo.Bar object at 0x101483350> = <class 'failure_demo.Bar'>()
failure_demo.py:124: AssertionError
__________________________ TestRaises.test_raises __________________________
self = <failure_demo.TestRaises instance at 0x101373710>
self = <failure_demo.TestRaises instance at 0x1014a6758>
def test_raises(self):
s = 'qwe'
@@ -352,10 +352,10 @@ get on the terminal - we are working on that):
> int(s)
E ValueError: invalid literal for int() with base 10: 'qwe'
<0-codegen /Users/hpk/p/pytest/_pytest/python.py:958>:1: ValueError
<0-codegen /Users/hpk/p/pytest/_pytest/python.py:976>:1: ValueError
______________________ TestRaises.test_raises_doesnt _______________________
self = <failure_demo.TestRaises instance at 0x101334f38>
self = <failure_demo.TestRaises instance at 0x1014b03f8>
def test_raises_doesnt(self):
> raises(IOError, "int('3')")
@@ -364,7 +364,7 @@ get on the terminal - we are working on that):
failure_demo.py:136: Failed
__________________________ TestRaises.test_raise ___________________________
self = <failure_demo.TestRaises instance at 0x10136d950>
self = <failure_demo.TestRaises instance at 0x1014a8998>
def test_raise(self):
> raise ValueError("demo error")
@@ -373,7 +373,7 @@ get on the terminal - we are working on that):
failure_demo.py:139: ValueError
________________________ TestRaises.test_tupleerror ________________________
self = <failure_demo.TestRaises instance at 0x101367758>
self = <failure_demo.TestRaises instance at 0x1014a27a0>
def test_tupleerror(self):
> a,b = [1]
@@ -382,7 +382,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 instance at 0x10136a4d0>
self = <failure_demo.TestRaises instance at 0x1014a5518>
def test_reinterpret_fails_with_print_for_the_fun_of_it(self):
l = [1,2,3]
@@ -395,7 +395,7 @@ get on the terminal - we are working on that):
l is [1, 2, 3]
________________________ TestRaises.test_some_error ________________________
self = <failure_demo.TestRaises instance at 0x1013692d8>
self = <failure_demo.TestRaises instance at 0x1014a1320>
def test_some_error(self):
> if namenotexi:
@@ -423,7 +423,7 @@ get on the terminal - we are working on that):
<2-codegen 'abc-123' /Users/hpk/p/pytest/doc/example/assertion/failure_demo.py:162>:2: AssertionError
____________________ TestMoreErrors.test_complex_error _____________________
self = <failure_demo.TestMoreErrors instance at 0x1013730e0>
self = <failure_demo.TestMoreErrors instance at 0x1014a6638>
def test_complex_error(self):
def f():
@@ -452,7 +452,7 @@ get on the terminal - we are working on that):
failure_demo.py:5: AssertionError
___________________ TestMoreErrors.test_z1_unpack_error ____________________
self = <failure_demo.TestMoreErrors instance at 0x101368290>
self = <failure_demo.TestMoreErrors instance at 0x1014a42d8>
def test_z1_unpack_error(self):
l = []
@@ -462,7 +462,7 @@ get on the terminal - we are working on that):
failure_demo.py:179: ValueError
____________________ TestMoreErrors.test_z2_type_error _____________________
self = <failure_demo.TestMoreErrors instance at 0x1013610e0>
self = <failure_demo.TestMoreErrors instance at 0x1014a0128>
def test_z2_type_error(self):
l = 3
@@ -472,19 +472,19 @@ get on the terminal - we are working on that):
failure_demo.py:183: TypeError
______________________ TestMoreErrors.test_startswith ______________________
self = <failure_demo.TestMoreErrors instance at 0x101361ea8>
self = <failure_demo.TestMoreErrors instance at 0x1014a0ef0>
def test_startswith(self):
s = "123"
g = "456"
> assert s.startswith(g)
E assert <built-in method startswith of str object at 0x101357a58>('456')
E + where <built-in method startswith of str object at 0x101357a58> = '123'.startswith
E assert <built-in method startswith of str object at 0x1014951c0>('456')
E + where <built-in method startswith of str object at 0x1014951c0> = '123'.startswith
failure_demo.py:188: AssertionError
__________________ TestMoreErrors.test_startswith_nested ___________________
self = <failure_demo.TestMoreErrors instance at 0x101368128>
self = <failure_demo.TestMoreErrors instance at 0x1014a4170>
def test_startswith_nested(self):
def f():
@@ -492,15 +492,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 0x101357a58>('456')
E + where <built-in method startswith of str object at 0x101357a58> = '123'.startswith
E + where '123' = <function f at 0x101339938>()
E + and '456' = <function g at 0x101339cf8>()
E assert <built-in method startswith of str object at 0x1014951c0>('456')
E + where <built-in method startswith of str object at 0x1014951c0> = '123'.startswith
E + where '123' = <function f at 0x1014aea28>()
E + and '456' = <function g at 0x101477c80>()
failure_demo.py:195: AssertionError
_____________________ TestMoreErrors.test_global_func ______________________
self = <failure_demo.TestMoreErrors instance at 0x101336758>
self = <failure_demo.TestMoreErrors instance at 0x1014b3ab8>
def test_global_func(self):
> assert isinstance(globf(42), float)
@@ -510,18 +510,18 @@ get on the terminal - we are working on that):
failure_demo.py:198: AssertionError
_______________________ TestMoreErrors.test_instance _______________________
self = <failure_demo.TestMoreErrors instance at 0x1013678c0>
self = <failure_demo.TestMoreErrors instance at 0x1014a2878>
def test_instance(self):
self.x = 6*7
> assert self.x != 42
E assert 42 != 42
E + where 42 = <failure_demo.TestMoreErrors instance at 0x1013678c0>.x
E + where 42 = <failure_demo.TestMoreErrors instance at 0x1014a2878>.x
failure_demo.py:202: AssertionError
_______________________ TestMoreErrors.test_compare ________________________
self = <failure_demo.TestMoreErrors instance at 0x101366a28>
self = <failure_demo.TestMoreErrors instance at 0x10149da70>
def test_compare(self):
> assert globf(10) < 5
@@ -531,7 +531,7 @@ get on the terminal - we are working on that):
failure_demo.py:205: AssertionError
_____________________ TestMoreErrors.test_try_finally ______________________
self = <failure_demo.TestMoreErrors instance at 0x1013628c0>
self = <failure_demo.TestMoreErrors instance at 0x101493908>
def test_try_finally(self):
x = 1
@@ -540,4 +540,4 @@ get on the terminal - we are working on that):
E assert 1 == 0
failure_demo.py:210: AssertionError
======================== 39 failed in 0.41 seconds =========================
======================== 39 failed in 1.05 seconds =========================

View File

@@ -53,7 +53,7 @@ Let's run this without supplying our new command line option::
test_sample.py:6: AssertionError
----------------------------- Captured stdout ------------------------------
first
1 failed in 0.02 seconds
1 failed in 0.50 seconds
And now with supplying a command line option::
@@ -109,13 +109,13 @@ directory with the above conftest.py::
$ py.test
=========================== test session starts ============================
platform darwin -- Python 2.7.1 -- pytest-2.2.1
platform darwin -- Python 2.7.1 -- pytest-2.2.2
gw0 I
gw0 [0]
scheduling tests via LoadScheduling
============================= in 0.54 seconds =============================
============================= in 5.12 seconds =============================
.. _`excontrolskip`:
@@ -156,20 +156,20 @@ 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 darwin -- Python 2.7.1 -- pytest-2.2.1
platform darwin -- Python 2.7.1 -- pytest-2.2.2
collecting ... collected 2 items
test_module.py .s
========================= short test summary info ==========================
SKIP [1] /Users/hpk/tmp/doc-exec-49/conftest.py:9: need --runslow option to run
SKIP [1] /Users/hpk/tmp/doc-exec-158/conftest.py:9: need --runslow option to run
=================== 1 passed, 1 skipped in 0.02 seconds ====================
=================== 1 passed, 1 skipped in 0.09 seconds ====================
Or run it including the ``slow`` marked test::
$ py.test --runslow
=========================== test session starts ============================
platform darwin -- Python 2.7.1 -- pytest-2.2.1
platform darwin -- Python 2.7.1 -- pytest-2.2.2
collecting ... collected 2 items
test_module.py ..
@@ -213,7 +213,7 @@ Let's run our little function::
E Failed: not configured: 42
test_checkconfig.py:8: Failed
1 failed in 0.02 seconds
1 failed in 0.07 seconds
Detect if running from within a py.test run
--------------------------------------------------------------
@@ -261,11 +261,11 @@ which will add the string to the test header accordingly::
$ py.test
=========================== test session starts ============================
platform darwin -- Python 2.7.1 -- pytest-2.2.1
platform darwin -- Python 2.7.1 -- pytest-2.2.2
project deps: mylib-1.1
collecting ... collected 0 items
============================= in 0.00 seconds =============================
============================= in 0.01 seconds =============================
.. regendoc:wipe
@@ -284,21 +284,21 @@ which will add info only when run with "--v"::
$ py.test -v
=========================== test session starts ============================
platform darwin -- Python 2.7.1 -- pytest-2.2.1 -- /Users/hpk/venv/1/bin/python
platform darwin -- Python 2.7.1 -- pytest-2.2.2 -- /Users/hpk/venv/0/bin/python
info1: did you know that ...
did you?
collecting ... collected 0 items
============================= in 0.00 seconds =============================
============================= in 0.03 seconds =============================
and nothing when run plainly::
$ py.test
=========================== test session starts ============================
platform darwin -- Python 2.7.1 -- pytest-2.2.1
platform darwin -- Python 2.7.1 -- pytest-2.2.2
collecting ... collected 0 items
============================= in 0.00 seconds =============================
============================= in 0.01 seconds =============================
profiling test duration
--------------------------
@@ -327,7 +327,7 @@ Now we can profile which test functions execute the slowest::
$ py.test --durations=3
=========================== test session starts ============================
platform darwin -- Python 2.7.1 -- pytest-2.2.1
platform darwin -- Python 2.7.1 -- pytest-2.2.2
collecting ... collected 3 items
test_some_are_slow.py ...
@@ -335,5 +335,5 @@ 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_funcfast
========================= 3 passed in 0.32 seconds =========================
0.00s call test_some_are_slow.py::test_funcfast
========================= 3 passed in 0.33 seconds =========================

View File

@@ -62,7 +62,7 @@ Running the test looks like this::
$ py.test test_simplefactory.py
=========================== test session starts ============================
platform darwin -- Python 2.7.1 -- pytest-2.2.1
platform darwin -- Python 2.7.1 -- pytest-2.2.2
collecting ... collected 1 items
test_simplefactory.py F
@@ -77,7 +77,7 @@ Running the test looks like this::
E assert 42 == 17
test_simplefactory.py:5: AssertionError
========================= 1 failed in 0.02 seconds =========================
========================= 1 failed in 0.03 seconds =========================
This means that indeed the test function was called with a ``myfuncarg``
argument value of ``42`` and the assert fails. Here is how py.test
@@ -167,7 +167,7 @@ Running this will generate ten invocations of ``test_func`` passing in each of t
$ py.test test_example.py
=========================== test session starts ============================
platform darwin -- Python 2.7.1 -- pytest-2.2.1
platform darwin -- Python 2.7.1 -- pytest-2.2.2
collecting ... collected 10 items
test_example.py .........F
@@ -182,7 +182,7 @@ Running this will generate ten invocations of ``test_func`` passing in each of t
E assert 9 < 9
test_example.py:6: AssertionError
==================== 1 failed, 9 passed in 0.05 seconds ====================
==================== 1 failed, 9 passed in 0.07 seconds ====================
Obviously, only when ``numiter`` has the value of ``9`` does the test fail. Note that the ``pytest_generate_tests(metafunc)`` hook is called during
the test collection phase which is separate from the actual test running.
@@ -190,7 +190,7 @@ Let's just look at what is collected::
$ py.test --collectonly test_example.py
=========================== test session starts ============================
platform darwin -- Python 2.7.1 -- pytest-2.2.1
platform darwin -- Python 2.7.1 -- pytest-2.2.2
collecting ... collected 10 items
<Module 'test_example.py'>
<Function 'test_func[0]'>
@@ -210,13 +210,13 @@ If you want to select only the run with the value ``7`` you could do::
$ py.test -v -k 7 test_example.py # or -k test_func[7]
=========================== test session starts ============================
platform darwin -- Python 2.7.1 -- pytest-2.2.1 -- /Users/hpk/venv/1/bin/python
platform darwin -- Python 2.7.1 -- pytest-2.2.2 -- /Users/hpk/venv/0/bin/python
collecting ... collected 10 items
test_example.py:5: test_func[7] PASSED
======================= 9 tests deselected by '-k7' ========================
================== 1 passed, 9 deselected in 0.02 seconds ==================
================== 1 passed, 9 deselected in 0.01 seconds ==================
You might want to look at :ref:`more parametrization examples <paramexamples>`.

View File

@@ -22,9 +22,10 @@ Installation options::
To check your installation has installed the correct version::
$ py.test --version
This is py.test version 2.2.1, imported from /Users/hpk/p/pytest/pytest.pyc
This is py.test version 2.2.2, imported from /Users/hpk/p/pytest/pytest.pyc
setuptools registered plugins:
pytest-xdist-1.8.dev2 at /Users/hpk/p/pytest-xdist/xdist/plugin.pyc
pytest-xdist-1.8 at /Users/hpk/p/pytest-xdist/xdist/plugin.pyc
pytest-cov-1.4 at /Users/hpk/venv/0/lib/python2.7/site-packages/pytest_cov.pyc
If you get an error checkout :ref:`installation issues`.
@@ -46,7 +47,7 @@ That's it. You can execute the test function now::
$ py.test
=========================== test session starts ============================
platform darwin -- Python 2.7.1 -- pytest-2.2.1
platform darwin -- Python 2.7.1 -- pytest-2.2.2
collecting ... collected 1 items
test_sample.py F
@@ -126,7 +127,7 @@ run the module by passing its filename::
================================= FAILURES =================================
____________________________ TestClass.test_two ____________________________
self = <test_class.TestClass instance at 0x10131a560>
self = <test_class.TestClass instance at 0x1013225a8>
def test_two(self):
x = "hello"
@@ -163,7 +164,7 @@ before performing the test function call. Let's just run it::
================================= FAILURES =================================
_____________________________ test_needsfiles ______________________________
tmpdir = local('/Users/hpk/tmp/pytest-679/test_needsfiles0')
tmpdir = local('/Users/hpk/tmp/pytest-20/test_needsfiles0')
def test_needsfiles(tmpdir):
print tmpdir
@@ -172,8 +173,8 @@ before performing the test function call. Let's just run it::
test_tmpdir.py:3: AssertionError
----------------------------- Captured stdout ------------------------------
/Users/hpk/tmp/pytest-679/test_needsfiles0
1 failed in 0.16 seconds
/Users/hpk/tmp/pytest-20/test_needsfiles0
1 failed in 0.11 seconds
Before the test runs, a unique-per-test-invocation temporary directory
was created. More info at :ref:`tmpdir handling`.

View File

@@ -14,14 +14,14 @@ and a discussion of its motivation.
.. _`monkeypatch blog post`: http://tetamap.wordpress.com/2009/03/03/monkeypatching-in-unit-tests-done-right/
Simple example: patching ``os.path.expanduser``
Simple example: monkeypatching functions
---------------------------------------------------
If, for instance, you want to pretend that ``os.expanduser`` returns a certain
If you want to pretend that ``os.expanduser`` returns a certain
directory, you can use the :py:meth:`monkeypatch.setattr` method to
patch this function before calling into a function which uses it::
# content of test_module.py
import os.path
def getssh(): # pseudo application code
return os.path.join(os.path.expanduser("~admin"), '.ssh')
@@ -33,22 +33,15 @@ patch this function before calling into a function which uses it::
x = getssh()
assert x == '/abc/.ssh'
After the test function finishes the ``os.path.expanduser`` modification
will be undone.
.. background check:
$ py.test
=========================== test session starts ============================
platform darwin -- Python 2.7.1 -- pytest-2.2.1
collecting ... collected 0 items
============================= in 0.00 seconds =============================
Here our test function monkeypatches ``os.path.expanduser`` and
then calls into an function that calls it. After the test function
finishes the ``os.path.expanduser`` modification will be undone.
Method reference of the monkeypatch function argument
-----------------------------------------------------
.. autoclass:: monkeypatch
:members: setattr, delattr, setitem, delitem, setenv, delenv, syspath_prepend, undo
:members: setattr, delattr, setitem, delitem, setenv, delenv, syspath_prepend, chdir, undo
``monkeypatch.setattr/delattr/delitem/delenv()`` all
by default raise an Exception if the target does not exist.

View File

@@ -130,7 +130,7 @@ Running it with the report-on-xfail option gives this output::
example $ py.test -rx xfail_demo.py
=========================== test session starts ============================
platform darwin -- Python 2.7.1 -- pytest-2.2.1
platform darwin -- Python 2.7.1 -- pytest-2.2.2
collecting ... collected 6 items
xfail_demo.py xxxxxx
@@ -147,7 +147,7 @@ Running it with the report-on-xfail option gives this output::
XFAIL xfail_demo.py::test_hello6
reason: reason
======================== 6 xfailed in 0.08 seconds =========================
======================== 6 xfailed in 0.16 seconds =========================
.. _`evaluation of skipif/xfail conditions`:

View File

@@ -28,7 +28,7 @@ Running this would result in a passed test except for the last
$ py.test test_tmpdir.py
=========================== test session starts ============================
platform darwin -- Python 2.7.1 -- pytest-2.2.1
platform darwin -- Python 2.7.1 -- pytest-2.2.2
collecting ... collected 1 items
test_tmpdir.py F
@@ -36,7 +36,7 @@ Running this would result in a passed test except for the last
================================= FAILURES =================================
_____________________________ test_create_file _____________________________
tmpdir = local('/Users/hpk/tmp/pytest-680/test_create_file0')
tmpdir = local('/Users/hpk/tmp/pytest-21/test_create_file0')
def test_create_file(tmpdir):
p = tmpdir.mkdir("sub").join("hello.txt")
@@ -47,7 +47,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.17 seconds =========================
========================= 1 failed in 0.07 seconds =========================
.. _`base temporary directory`:

View File

@@ -24,7 +24,7 @@ Running it yields::
$ py.test test_unittest.py
=========================== test session starts ============================
platform darwin -- Python 2.7.1 -- pytest-2.2.1
platform darwin -- Python 2.7.1 -- pytest-2.2.2
collecting ... collected 1 items
test_unittest.py F
@@ -42,7 +42,7 @@ Running it yields::
test_unittest.py:8: AssertionError
----------------------------- Captured stdout ------------------------------
hello
========================= 1 failed in 0.04 seconds =========================
========================= 1 failed in 0.15 seconds =========================
.. _`unittest.py style`: http://docs.python.org/library/unittest.html

View File

@@ -17,14 +17,14 @@ Bugs and issues: http://bitbucket.org/hpk42/pytest/issues/
Web page: http://pytest.org
(c) Holger Krekel and others, 2004-2011
(c) Holger Krekel and others, 2004-2012
"""
def main():
setup(
name='pytest',
description='py.test: simple powerful testing with Python',
long_description = long_description,
version='2.2.1',
version='2.2.2',
url='http://pytest.org',
license='MIT license',
platforms=['unix', 'linux', 'osx', 'cygwin', 'win32'],
@@ -32,7 +32,7 @@ def main():
author_email='holger at merlinux.eu',
entry_points= make_entry_points(),
# the following should be enabled for release
install_requires=['py>=1.4.6'],
install_requires=['py>=1.4.7.dev2'],
classifiers=['Development Status :: 6 - Mature',
'Intended Audience :: Developers',
'License :: OSI Approved :: MIT License',
@@ -70,4 +70,4 @@ def make_entry_points():
return {'console_scripts': l}
if __name__ == '__main__':
main()
main()

View File

@@ -410,15 +410,20 @@ class TestInvocationVariants:
"*1 passed*"
])
def join_pythonpath(what):
cur = py.std.os.environ.get('PYTHONPATH')
if cur:
return str(what) + ':' + cur
return what
empty_package = testdir.mkpydir("empty_package")
monkeypatch.setenv('PYTHONPATH', empty_package)
monkeypatch.setenv('PYTHONPATH', join_pythonpath(empty_package))
result = testdir.runpytest("--pyargs", ".")
assert result.ret == 0
result.stdout.fnmatch_lines([
"*2 passed*"
])
monkeypatch.setenv('PYTHONPATH', testdir)
monkeypatch.setenv('PYTHONPATH', join_pythonpath(testdir))
path.join('test_hello.py').remove()
result = testdir.runpytest("--pyargs", "tpkg.test_hello")
assert result.ret != 0

View File

@@ -28,17 +28,14 @@ def test_assert_with_explicit_message():
assert e.msg == 'hello'
def test_assert_within_finally():
class A:
def f():
pass
excinfo = py.test.raises(TypeError, """
excinfo = py.test.raises(ZeroDivisionError, """
try:
A().f()
1/0
finally:
i = 42
""")
s = excinfo.exconly()
assert s.find("takes no argument") != -1
assert py.std.re.search("division.+by zero", s) is not None
#def g():
# A.f()

View File

@@ -228,18 +228,26 @@ class TestFunctional:
keywords = item.keywords
marker = keywords['hello']
assert marker.args == ("pos0", "pos1")
assert marker.kwargs == {'x': 3, 'y': 2, 'z': 4}
assert marker.kwargs == {'x': 1, 'y': 2, 'z': 4}
def test_mark_other(self, testdir):
pytest.raises(TypeError, '''
testdir.getitem("""
# test the new __iter__ interface
l = list(marker)
assert len(l) == 3
assert l[0].args == ("pos0",)
assert l[1].args == ()
assert l[2].args == ("pos1", )
def test_mark_with_wrong_marker(self, testdir):
reprec = testdir.inline_runsource("""
import pytest
class pytestmark:
pass
def test_func():
pass
""")
''')
""")
l = reprec.getfailedcollections()
assert len(l) == 1
assert "TypeError" in str(l[0].longrepr)
def test_mark_dynamically_in_funcarg(self, testdir):
testdir.makeconftest("""
@@ -259,6 +267,23 @@ class TestFunctional:
"keyword: *hello*"
])
def test_merging_markers_two_functions(self, testdir):
p = testdir.makepyfile("""
import pytest
@pytest.mark.hello("pos1", z=4)
@pytest.mark.hello("pos0", z=3)
def test_func(self):
pass
""")
items, rec = testdir.inline_genitems(p)
item, = items
keywords = item.keywords
marker = keywords['hello']
l = list(marker)
assert len(l) == 2
assert l[0].args == ("pos0",)
assert l[1].args == ("pos1",)
class TestKeywordSelection:
def test_select_simple(self, testdir):

View File

@@ -2,6 +2,17 @@ import os, sys
import pytest
from _pytest.monkeypatch import monkeypatch as MonkeyPatch
def pytest_funcarg__mp(request):
cwd = os.getcwd()
sys_path = list(sys.path)
def cleanup():
sys.path[:] = sys_path
os.chdir(cwd)
request.addfinalizer(cleanup)
return MonkeyPatch()
def test_setattr():
class A:
x = 1
@@ -59,6 +70,29 @@ def test_setitem():
monkeypatch.undo()
assert d['x'] == 5
def test_setitem_deleted_meanwhile():
d = {}
monkeypatch = MonkeyPatch()
monkeypatch.setitem(d, 'x', 2)
del d['x']
monkeypatch.undo()
assert not d
@pytest.mark.parametrize("before", [True, False])
def test_setenv_deleted_meanwhile(before):
key = "qwpeoip123"
if before:
os.environ[key] = "world"
monkeypatch = MonkeyPatch()
monkeypatch.setenv(key, 'hello')
del os.environ[key]
monkeypatch.undo()
if before:
assert os.environ[key] == "world"
del os.environ[key]
else:
assert key not in os.environ
def test_delitem():
d = {'x': 1}
monkeypatch = MonkeyPatch()
@@ -121,19 +155,41 @@ def test_monkeypatch_plugin(testdir):
res = reprec.countoutcomes()
assert tuple(res) == (1, 0, 0), res
def test_syspath_prepend():
def test_syspath_prepend(mp):
old = list(sys.path)
try:
monkeypatch = MonkeyPatch()
monkeypatch.syspath_prepend('world')
monkeypatch.syspath_prepend('hello')
assert sys.path[0] == "hello"
assert sys.path[1] == "world"
monkeypatch.undo()
assert sys.path == old
monkeypatch.undo()
assert sys.path == old
finally:
sys.path[:] = old
mp.syspath_prepend('world')
mp.syspath_prepend('hello')
assert sys.path[0] == "hello"
assert sys.path[1] == "world"
mp.undo()
assert sys.path == old
mp.undo()
assert sys.path == old
def test_syspath_prepend_double_undo(mp):
mp.syspath_prepend('hello world')
mp.undo()
sys.path.append('more hello world')
mp.undo()
assert sys.path[-1] == 'more hello world'
def test_chdir_with_path_local(mp, tmpdir):
mp.chdir(tmpdir)
assert os.getcwd() == tmpdir.strpath
def test_chdir_with_str(mp, tmpdir):
mp.chdir(tmpdir.strpath)
assert os.getcwd() == tmpdir.strpath
def test_chdir_undo(mp, tmpdir):
cwd = os.getcwd()
mp.chdir(tmpdir)
mp.undo()
assert os.getcwd() == cwd
def test_chdir_double_undo(mp, tmpdir):
mp.chdir(tmpdir.strpath)
mp.undo()
tmpdir.chdir()
mp.undo()
assert os.getcwd() == tmpdir.strpath

View File

@@ -477,7 +477,7 @@ class TestTracebackCutting:
out = result.stdout.str()
assert out.find("conftest.py:2: ValueError") != -1
numentries = out.count("_ _ _ _") # separator for traceback entries
assert numentries >3
assert numentries > 3
def test_traceback_error_during_import(self, testdir):
testdir.makepyfile("""
@@ -983,11 +983,12 @@ class TestMetafunc:
metafunc = funcargs.Metafunc(func)
metafunc.parametrize('x', [1], indirect=True)
metafunc.parametrize('y', [2,3], indirect=True)
metafunc.parametrize('unnamed', [1], indirect=True)
assert len(metafunc._calls) == 2
assert metafunc._calls[0].funcargs == {}
assert metafunc._calls[1].funcargs == {}
assert metafunc._calls[0].params == dict(x=1,y=2)
assert metafunc._calls[1].params == dict(x=1,y=3)
assert metafunc._calls[0].params == dict(x=1,y=2, unnamed=1)
assert metafunc._calls[1].params == dict(x=1,y=3, unnamed=1)
def test_addcalls_and_parametrize_indirect(self):
def func(x, y): pass
@@ -1048,6 +1049,23 @@ class TestMetafunc:
assert metafunc._calls[1].funcargs == dict(x=3, y=4)
assert metafunc._calls[1].id == "3-4"
def test_parametrize_multiple_times(self, testdir):
testdir.makepyfile("""
import pytest
pytestmark = pytest.mark.parametrize("x", [1,2])
def test_func(x):
assert 0, x
class TestClass:
pytestmark = pytest.mark.parametrize("y", [3,4])
def test_meth(self, x, y):
assert 0, x
""")
result = testdir.runpytest()
assert result.ret == 1
result.stdout.fnmatch_lines([
"*6 fail*",
])
class TestMetafuncFunctional:
def test_attributes(self, testdir):
p = testdir.makepyfile("""
@@ -1534,3 +1552,21 @@ def test_unorderable_types(testdir):
result = testdir.runpytest()
assert "TypeError" not in result.stdout.str()
assert result.ret == 0
def test_issue117_sessionscopeteardown(testdir):
testdir.makepyfile("""
def pytest_funcarg__app(request):
app = request.cached_setup(
scope='session',
setup=lambda: 0,
teardown=lambda x: 3/x)
return app
def test_func(app):
pass
""")
result = testdir.runpytest()
assert result.ret != 0
result.stderr.fnmatch_lines([
"*3/x*",
"*ZeroDivisionError*",
])

View File

@@ -1,4 +1,4 @@
import pytest, py, sys
import pytest, py, sys, os
from _pytest import runner
from py._code.code import ReprExceptionInfo
@@ -315,6 +315,21 @@ class TestSessionReports:
assert not rep.passed
assert rep.skipped
reporttypes = [
runner.BaseReport,
runner.TestReport,
runner.TeardownErrorReport,
runner.CollectReport,
]
@pytest.mark.parametrize('reporttype', reporttypes, ids=[x.__name__ for x in reporttypes])
def test_report_extra_parameters(reporttype):
args = py.std.inspect.getargspec(reporttype.__init__)[0][1:]
basekw = dict.fromkeys(args, [])
report = reporttype(newthing=1, **basekw)
assert report.newthing == 1
def test_callinfo():
ci = runner.CallInfo(lambda: 0, '123')
assert ci.when == "123"
@@ -423,21 +438,18 @@ def test_importorskip():
py.test.fail("spurious skip")
def test_importorskip_imports_last_module_part():
import os
ospath = py.test.importorskip("os.path")
assert os.path == ospath
def test_pytest_cmdline_main(testdir):
p = testdir.makepyfile("""
import sys
sys.path.insert(0, %r)
import py
def test_hello():
assert 1
if __name__ == '__main__':
py.test.cmdline.main([__file__])
""" % (str(py._pydir.dirpath())))
""")
import subprocess
popen = subprocess.Popen([sys.executable, str(p)], stdout=subprocess.PIPE)
s = popen.stdout.read()

View File

@@ -256,6 +256,31 @@ class TestCollectonly:
*1 error*
""").strip())
def test_collectonly_missing_path(self, testdir):
"""this checks issue 115,
failure in parseargs will cause session
not to have the items attribute
"""
result = testdir.runpytest("--collectonly", "uhm_missing_path")
assert result.ret == 3
result.stderr.fnmatch_lines([
'*ERROR: file not found*',
])
def test_collectonly_quiet(self, testdir):
testdir.makepyfile("def test_foo(): pass")
result = testdir.runpytest("--collectonly", "-q")
result.stdout.fnmatch_lines([
'*test_foo*',
])
def test_collectonly_more_quiet(self, testdir):
testdir.makepyfile(test_fun="def test_foo(): pass")
result = testdir.runpytest("--collectonly", "-qq")
result.stdout.fnmatch_lines([
'*test_fun.py: 1*',
])
def test_repr_python_version(monkeypatch):
try:

View File

@@ -448,3 +448,14 @@ def test_unorderable_types(testdir):
result = testdir.runpytest()
assert "TypeError" not in result.stdout.str()
assert result.ret == 0
def test_unittest_typerror_traceback(testdir):
testdir.makepyfile("""
import unittest
class TestJoinEmpty(unittest.TestCase):
def test_hello(self, arg1):
pass
""")
result = testdir.runpytest()
assert "TypeError" in result.stdout.str()
assert result.ret == 1

View File

@@ -33,7 +33,7 @@ deps=:pypi:twisted
:pypi:pexpect
py>=1.4.5.dev1
commands=
py.test -rsxf \
py.test -rsxf testing/test_unittest.py \
--junitxml={envlogdir}/junit-{envname}.xml {posargs:testing/test_unittest.py}
[testenv:doctest]
changedir=.