Compare commits

...

42 Commits
2.3.1 ... 2.3.3

Author SHA1 Message Date
holger krekel
d6f10d502c fix py31 compat, amend setup.py long description 2012-11-06 15:36:11 +01:00
holger krekel
65d6ebe7d1 bump to 2.3.3, add release announce 2012-11-06 14:41:10 +01:00
holger krekel
33cd414420 fix issue127 improve pytest_addoption docs, add new config.getoption(name) method for consistency. 2012-11-06 14:09:12 +01:00
holger krekel
dba2a8bc64 fix issue217 - to support @mock.patch with pytest funcarg-fixtures, also split out python integration tests into python/integration.py and fix nose/mark tests 2012-11-06 11:04:11 +01:00
holger krekel
f203401964 amend changelog entries 2012-11-06 09:27:58 +01:00
holger krekel
c64699bba6 fix issue219 - add trove classifiers for py24-py33 2012-11-06 09:14:41 +01:00
holger krekel
002c5072af addresses issue209 - avoid error messages from pip on python2.4 related to file, however, never be imported with this interpreter 2012-11-06 09:08:54 +01:00
Ronny Pfannschmidt
b3c8991b22 add a xfailing test for issue 199 2012-11-05 21:52:12 +01:00
Ronny Pfannschmidt
1a41c9c001 update changelog 2012-11-05 21:31:08 +01:00
Ronny Pfannschmidt
df444906d6 merge pull request 2012-11-05 21:18:50 +01:00
Ronny Pfannschmidt
04754f6748 test call_optional not calling non-callable functions 2012-11-05 21:17:58 +01:00
holger krekel
d5ad91c64f fix issue209 - depend on pylib dev version which again supports python2.4 2012-11-05 12:21:58 +01:00
holger krekel
7e831b66ec fix issue148 - recognize @unittest.skip on classes, avoid setup/teardown 2012-11-03 20:54:48 +01:00
holger krekel
ba9b27fcd3 fix issue215 - refactor test_python.py into multiple files:
- python/collect.py cotaining the core collection nodes
- python/fixture.py containing funcargs/fixture code
- python/metafunc.py generate_tests and metafunc usage
- python/raises.py the pytest.raises implementation
2012-11-02 16:04:57 +01:00
holger krekel
ca281b7c1b remove unused code 2012-11-02 16:04:56 +01:00
holger krekel
fb173a97a8 extended - fix issue214 - ignore attribute-access errors with objects in test modules that can blow up (for example flask's request object) 2012-10-31 17:00:55 +01:00
holger krekel
983b2d2475 merge 2012-10-31 17:01:24 +01:00
Ronny Pfannschmidt
e7e5ee805f fix issue 214 - gracefully handle proxy objects that look like fixtures 2012-10-31 17:00:43 +01:00
holger krekel
67f8dd0cf2 remove issue that doesn't make sense anymore 2012-10-28 17:40:30 +01:00
holger krekel
07cc48517d fix wrong reference in basic fixture example, thanks for reporting! (closes #212) 2012-10-28 14:54:49 +01:00
holger krekel
fce13c3e46 re-allow to parametrize with values that don't support __eq__ (closes issue213) 2012-10-28 14:52:43 +01:00
holger krekel
573599beb3 i think "helps you write better programs" fits better than "makes" 2012-10-28 11:25:53 +01:00
holger krekel
6ebf39e9a6 fix wrong document version on pytest.org (closes #210) 2012-10-28 10:13:37 +01:00
holger krekel
6b6080ae6c remove unused code 2012-10-28 10:12:36 +01:00
holger krekel
427cf6f66d add release announce 2012-10-25 14:13:43 +02:00
holger krekel
2fc8ee0839 Added tag 2.3.2 for changeset 8738b828dec5 2012-10-25 14:13:06 +02:00
holger krekel
6ad16936bb bump version to 2.3.2, regen docs and changelog 2012-10-25 13:48:31 +02:00
holger krekel
bcb8dc71d2 fix issue208 and fix issue29 - avoid long pauses in traceback printing
by using the new getstatementrange() code of the py lib which uses
AST-parsing rather than the previous heuristic which had O(n^2) complexity
(with n = len(sourcelines))

- require new (in-dev) py version to
2012-10-25 12:08:11 +02:00
holger krekel
b8277bfed8 fix issue127 - improve pytest_addoption and related documentation 2012-10-25 11:07:07 +02:00
holger krekel
2637326782 improve support for trial a bit more: don't run trial's empty TestCase.runTest() method 2012-10-22 19:22:01 +02:00
holger krekel
aa79c0a4b9 fix unittest emulation: TestCase.runTest is now ignored
if there are test* methods.
2012-10-22 16:25:09 +02:00
holger krekel
05c86aeb28 make sure ihook uses a node's fspath - important for hooks
e.g. during a Module's collect to pick up conftest.py files
residing in the same dir
2012-10-22 16:12:22 +02:00
holger krekel
f28f073c7c fix teardown-ordering for parametrized setups/teardowns 2012-10-22 12:16:54 +02:00
holger krekel
036557ac18 fix issue206 - unset PYTHONDONTWRITEBYTECODE in assertrewrite test 2012-10-22 11:14:18 +02:00
holger krekel
1b61fbc8ed - fix test_nose.py by being more tolerant about the error message
(differs between py32 and py33, thanks Arfrever)
- use pypi again now that py is released
2012-10-22 10:55:59 +02:00
holger krekel
97f03edcd6 fix issue205 - nested conftest to pickup pycollect_makemodule - relates to the two
reports of a failing doc/en/example/py2py3.
2012-10-22 10:17:50 +02:00
holger krekel
7e5efa0005 mention twisted with external plugins 2012-10-22 09:32:41 +02:00
holger krekel
d55fc611c4 properly handle non-existent PYTHONPATH 2012-10-20 17:39:15 +02:00
holger krekel
720fe3405b allow to run self-tests with "python setup.py test" for pytest tests itself 2012-10-20 17:32:03 +02:00
holger krekel
c894b2b459 add tox.ini to distribution 2012-10-20 17:08:02 +02:00
holger krekel
6d5bf4b908 Added tag 2.3.1 for changeset acf0e1477fb1 2012-10-20 14:33:23 +02:00
ataumoefolau
40a55a640c nose.py: don't try to call setup if it's not callable 2012-10-12 14:39:17 +10:00
48 changed files with 2359 additions and 1903 deletions

View File

@@ -50,3 +50,5 @@ e5e1746a197f0398356a43fbe2eebac9690f795d 2.1.0
3c11c5c9776f3c678719161e96cc0a08169c1cb8 2.2.3
ad9fe504a371ad8eb613052d58f229aa66f53527 2.2.4
c27a60097767c16a54ae56d9669a77925b213b9b 2.3.0
acf0e1477fb19a1d35a4e40242b77fa6af32eb17 2.3.1
8738b828dec53937765db71951ef955cca4c51f6 2.3.2

View File

@@ -1,3 +1,68 @@
Changes between 2.3.2 and 2.3.3
-----------------------------------
- fix issue214 - parse modules that contain special objects like e. g.
flask's request object which blows up on getattr access if no request
is active. thanks Thomas Waldmann.
- fix issue213 - allow to parametrize with values like numpy arrays that
do not support an __eq__ operator
- fix issue215 - split test_python.org into multiple files
- fix issue148 - @unittest.skip on classes is now recognized and avoids
calling setUpClass/tearDownClass, thanks Pavel Repin
- fix issue209 - reintroduce python2.4 support by depending on newer
pylib which re-introduced statement-finding for pre-AST interpreters
- nose support: only call setup if its a callable, thanks Andrew
Taumoefolau
- fix issue219 - add py2.4-3.3 classifiers to TROVE list
- in tracebacks *,** arg values are now shown next to normal arguments
(thanks Manuel Jacob)
- fix issue217 - support mock.patch with pytest's fixtures - note that
you need either mock-1.0.1 or the python3.3 builtin unittest.mock.
- fix issue127 - improve documentation for pytest_addoption() and
add a ``config.getoption(name)`` helper function for consistency.
Changes between 2.3.1 and 2.3.2
-----------------------------------
- fix issue208 and fix issue29 use new py version to avoid long pauses
when printing tracebacks in long modules
- fix issue205 - conftests in subdirs customizing
pytest_pycollect_makemodule and pytest_pycollect_makeitem
now work properly
- fix teardown-ordering for parametrized setups
- fix issue127 - better documentation for pytest_addoption
and related objects.
- fix unittest behaviour: TestCase.runtest only called if there are
test methods defined
- improve trial support: don't collect its empty
unittest.TestCase.runTest() method
- "python setup.py test" now works with pytest itself
- fix/improve internal/packaging related bits:
- exception message check of test_nose.py now passes on python33 as well
- issue206 - fix test_assertrewrite.py to work when a global
PYTHONDONTWRITEBYTECODE=1 is present
- add tox.ini to pytest distribution so that ignore-dirs and others config
bits are properly distributed for maintainers who run pytest-own tests
Changes between 2.3.0 and 2.3.1
-----------------------------------

View File

@@ -48,59 +48,6 @@ if the signature of a decorated function does not match. XXX is it
not sufficient to always allow non-matches?
unify item/request classes, generalize items
---------------------------------------------------------------
tags: 2.4 wish
in lieu of extended parametrization and the new way to specify resource
factories in terms of the parametrize decorator, consider unification
of the item and request class. This also is connected with allowing
funcargs in setup functions. Example of new item API:
item.getresource("db") # alias for request.getfuncargvalue
item.addfinalizer(...)
item.cached_setup(...)
item.applymarker(...)
test classes/modules could then use this api via::
def pytest_runtest_setup(item):
use item API ...
introduction of this new method needs to be _fully_ backward compatible -
and the documentation needs to change along to mention this new way of
doing things.
impl note: probably Request._fillfixtures would be called from the
python plugins own pytest_runtest_setup(item) and would call
item.getresource(X) for all X in the funcargs of a function.
XXX is it possible to even put the above item API to Nodes, i.e. also
to Directorty/module/file/class collectors? Problem is that current
funcarg factories presume they are called with a per-function (even
per-funcarg-per-function) scope. Could there be small tweaks to the new
API that lift this restriction?
consider::
def setup_class(cls, tmpdir):
# would get a per-class tmpdir because tmpdir parametrization
# would know that it is called with a class scope
#
#
#
this looks very difficult because those setup functions are also used
by nose etc. Rather consider introduction of a new setup hook:
def setup_test(self, item):
self.db = item.cached_setup(..., scope='class')
self.tmpdir = item.getresource("tmpdir")
this should be compatible to unittest/nose and provide much of what
"testresources" provide. XXX This would not allow full parametrization
such that test function could be run multiple times with different
values. See "parametrized attributes" issue.
allow parametrized attributes on classes
--------------------------------------------------

View File

@@ -2,6 +2,7 @@ include CHANGELOG
include README.txt
include setup.py
include distribute_setup.py
include tox.ini
include LICENSE
graft doc
graft testing

View File

@@ -1,2 +1,2 @@
#
__version__ = '2.3.1'
__version__ = '2.3.3'

View File

@@ -34,7 +34,7 @@ else:
PYTEST_TAG = "%s-%s%s-PYTEST" % (impl, ver[0], ver[1])
del ver, impl
PYC_EXT = ".py" + ("c" if __debug__ else "o")
PYC_EXT = ".py" + (__debug__ and "c" or "o")
PYC_TAIL = "." + PYTEST_TAG + PYC_EXT
REWRITE_NEWLINES = sys.version_info[:2] != (2, 7) and sys.version_info < (3, 2)

View File

@@ -19,7 +19,7 @@ def pytest_unconfigure(config):
fin()
class Parser:
""" Parser for command line arguments. """
""" Parser for command line arguments and ini-file values. """
def __init__(self, usage=None, processopt=None):
self._anonymous = OptionGroup("custom options", parser=self)
@@ -38,9 +38,14 @@ class Parser:
def getgroup(self, name, description="", after=None):
""" get (or create) a named option Group.
:name: unique name of the option group.
:name: name of the option group.
:description: long description for --help output.
:after: name of other group, used for ordering --help output.
The returned group object has an ``addoption`` method with the same
signature as :py:func:`parser.addoption
<_pytest.config.Parser.addoption>` but will be shown in the
respective group in the output of ``pytest. --help``.
"""
for group in self._groups:
if group.name == name:
@@ -54,7 +59,19 @@ class Parser:
return group
def addoption(self, *opts, **attrs):
""" add an optparse-style option. """
""" register a command line option.
:opts: option names, can be short or long options.
:attrs: same attributes which the ``add_option()`` function of the
`optparse library
<http://docs.python.org/library/optparse.html#module-optparse>`_
accepts.
After command line parsing options are available on the pytest config
object via ``config.option.NAME`` where ``NAME`` is usually set
by passing a ``dest`` attribute, for example
``addoption("--long", dest="NAME", ...)``.
"""
self._anonymous.addoption(*opts, **attrs)
def parse(self, args):
@@ -75,7 +92,15 @@ class Parser:
return args
def addini(self, name, help, type=None, default=None):
""" add an ini-file option with the given name and description. """
""" register an ini-file option.
:name: name of the ini-variable
:type: type of the variable, can be ``pathlist``, ``args`` or ``linelist``.
:default: default value if no ini-file option exists but is queried.
The value of ini-variables can be retrieved via a call to
:py:func:`config.getini(name) <_pytest.config.Config.getini>`.
"""
assert type in (None, "pathlist", "args", "linelist")
self._inidict[name] = (help, type, default)
self._ininames.append(name)
@@ -246,8 +271,8 @@ class CmdOptions(object):
class Config(object):
""" access to configuration values, pluginmanager and plugin hooks. """
def __init__(self, pluginmanager=None):
#: command line option values, usually added via parser.addoption(...)
#: or parser.getgroup(...).addoption(...) calls
#: access to command line option as attributes.
#: (deprecated), use :py:func:`getoption() <_pytest.config.Config.getoption>` instead
self.option = CmdOptions()
self._parser = Parser(
usage="usage: %prog [options] [file_or_dir] [file_or_dir] [...]",
@@ -259,6 +284,7 @@ class Config(object):
self._conftest = Conftest(onimport=self._onimportconftest)
self.hook = self.pluginmanager.hook
self._inicache = {}
self._opt2dest = {}
self._cleanup = []
@classmethod
@@ -279,6 +305,9 @@ class Config(object):
self.pluginmanager.consider_conftest(conftestmodule)
def _processopt(self, opt):
for name in opt._short_opts + opt._long_opts:
self._opt2dest[name] = opt.dest
if hasattr(opt, 'default') and opt.dest:
if not hasattr(self.option, opt.dest):
setattr(self.option, opt.dest, opt.default)
@@ -357,8 +386,9 @@ class Config(object):
x.append(line) # modifies the cached list inline
def getini(self, name):
""" return configuration value from an ini file. If the
specified name hasn't been registered through a prior ``parse.addini``
""" return configuration value from an :ref:`ini file <inifiles>`. If the
specified name hasn't been registered through a prior
:py:func:`parser.addini <pytest.config.Parser.addini>`
call (usually from a plugin), a ValueError is raised. """
try:
return self._inicache[name]
@@ -412,8 +442,22 @@ class Config(object):
self._checkconftest(name)
return self._conftest.rget(name, path)
def getoption(self, name):
""" return command line option value.
:arg name: name of the option. You may also specify
the literal ``--OPT`` option instead of the "dest" option name.
"""
name = self._opt2dest.get(name, name)
try:
return getattr(self.option, name)
except AttributeError:
raise ValueError("no option named %r" % (name,))
def getvalue(self, name, path=None):
""" return ``name`` value looked set from command line options.
""" return command line option value.
:arg name: name of the command line option
(deprecated) if we can't find the option also lookup
the name in a matching conftest file.
@@ -451,14 +495,3 @@ def getcfg(args, inibasenames):
return iniconfig['pytest']
return {}
def findupwards(current, basename):
current = py.path.local(current)
while 1:
p = current.join(basename)
if p.check():
return p
p = current.dirpath()
if p == current:
return
current = p

View File

@@ -23,8 +23,28 @@ def pytest_cmdline_preparse(config, args):
"""modify command line arguments before option parsing. """
def pytest_addoption(parser):
"""add optparse-style options and ini-style config values via calls
to ``parser.addoption`` and ``parser.addini(...)``.
"""register optparse-style options and ini-style config values.
This function must be implemented in a :ref:`plugin <pluginorder>` and is
called once at the beginning of a test run.
:arg parser: To add command line options, call
:py:func:`parser.addoption(...) <_pytest.config.Parser.addoption>`.
To add ini-file values call :py:func:`parser.addini(...)
<_pytest.config.Parser.addini>`.
Options can later be accessed through the
:py:class:`config <_pytest.config.Config>` object, respectively:
- :py:func:`config.getoption(name) <_pytest.config.Config.getoption>` to
retrieve the value of a command line option.
- :py:func:`config.getini(name) <_pytest.config.Config.getini>` to retrieve
a value read from an ini-style file.
The config object is passed around on many internal objects via the ``.config``
attribute or can be retrieved as the ``pytestconfig`` fixture or accessed
via (deprecated) ``pytest.config``.
"""
def pytest_cmdline_main(config):
@@ -33,7 +53,7 @@ def pytest_cmdline_main(config):
pytest_cmdline_main.firstresult = True
def pytest_configure(config):
""" called after command line options have been parsed.
""" called after command line options have been parsed
and all plugins and initial conftest files been loaded.
"""

View File

@@ -211,14 +211,16 @@ class Node(object):
#: filesystem path where this node was collected from (can be None)
self.fspath = getattr(parent, 'fspath', None)
#: fspath sensitive hook proxy used to call pytest hooks
self.ihook = self.session.gethookproxy(self.fspath)
#: keywords/markers collected from all scopes
self.keywords = NodeKeywords(self)
#self.extrainit()
@property
def ihook(self):
""" fspath sensitive hook proxy used to call pytest hooks"""
return self.session.gethookproxy(self.fspath)
#def extrainit(self):
# """"extra initialization after Node is initialized. Implemented
# by some subclasses. """

View File

@@ -41,7 +41,7 @@ def pytest_make_collect_report(collector):
def call_optional(obj, name):
method = getattr(obj, name, None)
if method is not None and not hasattr(method, "_pytestfixturefunction"):
if method is not None and not hasattr(method, "_pytestfixturefunction") and py.builtin.callable(method):
# If there's any problems allow the exception to raise rather than
# silently ignoring them
method()

View File

@@ -161,8 +161,8 @@ def pytest_collect_file(path, parent):
break
else:
return
return parent.ihook.pytest_pycollect_makemodule(
path=path, parent=parent)
ihook = parent.session.gethookproxy(path)
return ihook.pytest_pycollect_makemodule(path=path, parent=parent)
def pytest_pycollect_makemodule(path, parent):
return Module(path, parent)
@@ -288,6 +288,7 @@ class PyCollector(PyobjMixin, pytest.Collector):
return l
def makeitem(self, name, obj):
#assert self.ihook.fspath == self.fspath, self
return self.ihook.pytest_pycollect_makeitem(
collector=self, name=name, obj=obj)
@@ -597,7 +598,7 @@ class CallSpec2(object):
if valtype == "funcargs":
self.params[arg] = id
self._arg2scopenum[arg] = scopenum
if val == _notexists:
if val is _notexists:
self._emptyparamspecified = True
self._idlist.append(id)
@@ -1285,12 +1286,6 @@ scopenum_subfunction = scopes.index("subfunction")
def scopemismatch(currentscope, newscope):
return scopes.index(newscope) > scopes.index(currentscope)
def slice_kwargs(names, kwargs):
new_kwargs = {}
for name in names:
new_kwargs[name] = kwargs[name]
return new_kwargs
class FixtureLookupError(LookupError):
""" could not return a requested Fixture (missing or invalid). """
def __init__(self, argname, request, msg=None):
@@ -1531,7 +1526,7 @@ class FixtureManager:
item.session._setupstate._callfinalizers((name, param))
l = self._arg2finish.get(name)
if l is not None:
for fin in l:
for fin in reversed(l):
fin()
def parsefactories(self, node_or_obj, nodeid=None, unittest=False):
@@ -1550,7 +1545,15 @@ class FixtureManager:
continue
# fixture functions have a pytest_funcarg__ prefix (pre-2.3 style)
# or are "@pytest.fixture" marked
marker = getattr(obj, "_pytestfixturefunction", None)
try:
marker = obj._pytestfixturefunction
except KeyboardInterrupt:
raise
except Exception:
# some objects raise errors like request (from flask import request)
# we don't expect them to be fixture functions
marker = None
if marker is None:
if not name.startswith(self._argprefix):
continue
@@ -1656,8 +1659,14 @@ class FixtureDef:
def getfuncargnames(function, startindex=None):
# XXX merge with main.py's varnames
#assert not inspect.isclass(function)
realfunction = function
while hasattr(realfunction, "__wrapped__"):
realfunction = realfunction.__wrapped__
if startindex is None:
startindex = inspect.ismethod(function) and 1 or 0
if realfunction != function:
startindex += len(getattr(function, "patchings", []))
function = realfunction
argnames = inspect.getargs(py.code.getrawcode(function))[0]
defaults = getattr(function, 'func_defaults',
getattr(function, '__defaults__', None)) or ()

View File

@@ -28,6 +28,7 @@ class UnitTestCase(pytest.Class):
loader = py.std.unittest.TestLoader()
module = self.getparent(pytest.Module).obj
cls = self.obj
foundsomething = False
for name in loader.getTestCaseNames(self.obj):
x = getattr(self.obj, name)
funcobj = getattr(x, 'im_func', x)
@@ -35,17 +36,26 @@ class UnitTestCase(pytest.Class):
if hasattr(funcobj, 'todo'):
pytest.mark.xfail(reason=str(funcobj.todo))(funcobj)
yield TestCaseFunction(name, parent=self)
foundsomething = True
if getattr(self.obj, 'runTest', None) is not None:
yield TestCaseFunction('runTest', parent=self)
if not foundsomething:
runtest = getattr(self.obj, 'runTest', None)
if runtest is not None:
ut = sys.modules.get("twisted.trial.unittest", None)
if ut is None or runtest != ut.TestCase.runTest:
yield TestCaseFunction('runTest', parent=self)
def setup(self):
if getattr(self.obj, '__unittest_skip__', False):
return
meth = getattr(self.obj, 'setUpClass', None)
if meth is not None:
meth()
super(UnitTestCase, self).setup()
def teardown(self):
if getattr(self.obj, '__unittest_skip__', False):
return
meth = getattr(self.obj, 'tearDownClass', None)
if meth is not None:
meth()

View File

@@ -5,6 +5,9 @@ Release announcements
.. toctree::
:maxdepth: 2
release-2.3.3
release-2.3.2
release-2.3.1
release-2.3.0
release-2.2.4
release-2.2.2

View File

@@ -0,0 +1,57 @@
pytest-2.3.2: some fixes and more traceback-printing speed
===========================================================================
pytest-2.3.2 is a another stabilization release:
- issue 205: fixes a regression with conftest detection
- issue 208/29: fixes traceback-printing speed in some bad cases
- fix teardown-ordering for parametrized setups
- fix unittest and trial compat behaviour with respect to runTest() methods
- issue 206 and others: some improvements to packaging
- fix issue127 and others: improve some docs
See
http://pytest.org/
for general information. To install or upgrade pytest:
pip install -U pytest # or
easy_install -U pytest
best,
holger krekel
Changes between 2.3.1 and 2.3.2
-----------------------------------
- fix issue208 and fix issue29 use new py version to avoid long pauses
when printing tracebacks in long modules
- fix issue205 - conftests in subdirs customizing
pytest_pycollect_makemodule and pytest_pycollect_makeitem
now work properly
- fix teardown-ordering for parametrized setups
- fix issue127 - better documentation for pytest_addoption
and related objects.
- fix unittest behaviour: TestCase.runtest only called if there are
test methods defined
- improve trial support: don't collect its empty
unittest.TestCase.runTest() method
- "python setup.py test" now works with pytest itself
- fix/improve internal/packaging related bits:
- exception message check of test_nose.py now passes on python33 as well
- issue206 - fix test_assertrewrite.py to work when a global
PYTHONDONTWRITEBYTECODE=1 is present
- add tox.ini to pytest distribution so that ignore-dirs and others config
bits are properly distributed for maintainers who run pytest-own tests

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 linux2 -- Python 2.7.3 -- pytest-2.3.1
platform linux2 -- Python 2.7.3 -- pytest-2.3.3
collected 1 items
test_assert1.py F
@@ -110,7 +110,7 @@ if you run this module::
$ py.test test_assert2.py
=========================== test session starts ============================
platform linux2 -- Python 2.7.3 -- pytest-2.3.1
platform linux2 -- Python 2.7.3 -- pytest-2.3.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 linux2 -- Python 2.7.3 -- pytest-2.3.1
platform linux2 -- Python 2.7.3 -- pytest-2.3.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 ------------------------------
setting up <function test_func2 at 0x240e050>
setting up <function test_func2 at 0x2d63d70>
==================== 1 failed, 1 passed in 0.01 seconds ====================
Accessing captured output from a test function

View File

@@ -17,7 +17,7 @@
#
# The full version, including alpha/beta/rc tags.
# The short X.Y version.
version = release = "2.3.1"
version = release = "2.3.3"
import sys, os
@@ -53,7 +53,7 @@ master_doc = 'contents'
# General information about the project.
project = u'pytest'
copyright = u'2011, holger krekel et alii'
copyright = u'2012, holger krekel'
@@ -197,7 +197,7 @@ htmlhelp_basename = 'pytestdoc'
# (source start file, target name, title, author, documentclass [howto/manual]).
latex_documents = [
('contents', 'pytest.tex', u'pytest Documentation',
u'holger krekel et alii', 'manual'),
u'holger krekel, http://merlinux.eu', 'manual'),
]
# The name of an image file (relative to this directory) to place at the top of
@@ -239,7 +239,7 @@ man_pages = [
epub_title = u'pytest'
epub_author = u'holger krekel at merlinux eu'
epub_publisher = u'holger krekel at merlinux eu'
epub_copyright = u'2011, holger krekel et alii'
epub_copyright = u'2012, holger krekel et alii'
# The language of the text. It defaults to the language option
# or en if the language is not set.

View File

@@ -12,6 +12,8 @@ configurations files by using the general help option::
This will display command line and configuration file settings
which were registered by installed plugins.
.. _inifiles:
How test configuration is read from configuration INI-files
-------------------------------------------------------------

View File

@@ -44,7 +44,7 @@ then you can just invoke ``py.test`` without command line options::
$ py.test
=========================== test session starts ============================
platform linux2 -- Python 2.7.3 -- pytest-2.3.1
platform linux2 -- Python 2.7.3 -- pytest-2.3.3
collected 1 items
mymodule.py .

View File

@@ -26,25 +26,25 @@ You can then restrict a test run to only run tests marked with ``webtest``::
$ py.test -v -m webtest
=========================== test session starts ============================
platform linux2 -- Python 2.7.3 -- pytest-2.3.1 -- /home/hpk/p/pytest/.tox/regen/bin/python
platform linux2 -- Python 2.7.3 -- pytest-2.3.3 -- /home/hpk/p/pytest/.tox/regen/bin/python
collecting ... collected 2 items
test_server.py:3: test_send_http PASSED
=================== 1 tests deselected by "-m 'webtest'" ===================
================== 1 passed, 1 deselected in 0.00 seconds ==================
================== 1 passed, 1 deselected in 0.02 seconds ==================
Or the inverse, running all tests except the webtest ones::
$ py.test -v -m "not webtest"
=========================== test session starts ============================
platform linux2 -- Python 2.7.3 -- pytest-2.3.1 -- /home/hpk/p/pytest/.tox/regen/bin/python
platform linux2 -- Python 2.7.3 -- pytest-2.3.3 -- /home/hpk/p/pytest/.tox/regen/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.00 seconds ==================
================== 1 passed, 1 deselected in 0.01 seconds ==================
Registering markers
-------------------------------------
@@ -145,7 +145,7 @@ the given argument::
$ py.test -k send_http # running with the above defined examples
=========================== test session starts ============================
platform linux2 -- Python 2.7.3 -- pytest-2.3.1
platform linux2 -- Python 2.7.3 -- pytest-2.3.3
collected 4 items
test_server.py .
@@ -157,7 +157,7 @@ And you can also run all tests except the ones that match the keyword::
$ py.test -k-send_http
=========================== test session starts ============================
platform linux2 -- Python 2.7.3 -- pytest-2.3.1
platform linux2 -- Python 2.7.3 -- pytest-2.3.3
collected 4 items
test_mark_classlevel.py ..
@@ -170,7 +170,7 @@ Or to only select the class::
$ py.test -kTestClass
=========================== test session starts ============================
platform linux2 -- Python 2.7.3 -- pytest-2.3.1
platform linux2 -- Python 2.7.3 -- pytest-2.3.3
collected 4 items
test_mark_classlevel.py ..
@@ -194,7 +194,7 @@ specifies via named environments::
import pytest
def pytest_addoption(parser):
parser.addoption("-E", dest="env", action="store", metavar="NAME",
parser.addoption("-E", action="store", metavar="NAME",
help="only run tests matching the environment NAME.")
def pytest_configure(config):
@@ -206,7 +206,7 @@ specifies via named environments::
envmarker = item.keywords.get("env", None)
if envmarker is not None:
envname = envmarker.args[0]
if envname != item.config.option.env:
if envname != item.config.getoption("-E"):
pytest.skip("test requires env %r" % envname)
A test file using this local plugin::
@@ -223,23 +223,23 @@ the test needs::
$ py.test -E stage2
=========================== test session starts ============================
platform linux2 -- Python 2.7.3 -- pytest-2.3.1
platform linux2 -- Python 2.7.3 -- pytest-2.3.3
collected 1 items
test_someenv.py s
======================== 1 skipped in 0.00 seconds =========================
======================== 1 skipped in 0.01 seconds =========================
and here is one that specifies exactly the environment needed::
$ py.test -E stage1
=========================== test session starts ============================
platform linux2 -- Python 2.7.3 -- pytest-2.3.1
platform linux2 -- Python 2.7.3 -- pytest-2.3.3
collected 1 items
test_someenv.py .
========================= 1 passed in 0.00 seconds =========================
========================= 1 passed in 0.01 seconds =========================
The ``--markers`` option always gives you a list of available markers::
@@ -351,12 +351,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 linux2 -- Python 2.7.3 -- pytest-2.3.1
platform linux2 -- Python 2.7.3 -- pytest-2.3.3
collected 4 items
test_plat.py s.s.
========================= short test summary info ==========================
SKIP [2] /tmp/doc-exec-592/conftest.py:12: cannot run on platform linux2
SKIP [2] /tmp/doc-exec-57/conftest.py:12: cannot run on platform linux2
=================== 2 passed, 2 skipped in 0.01 seconds ====================
@@ -364,7 +364,7 @@ Note that if you specify a platform via the marker-command line option like this
$ py.test -m linux2
=========================== test session starts ============================
platform linux2 -- Python 2.7.3 -- pytest-2.3.1
platform linux2 -- Python 2.7.3 -- pytest-2.3.3
collected 4 items
test_plat.py .

View File

@@ -27,7 +27,7 @@ now execute the test specification::
nonpython $ py.test test_simple.yml
=========================== test session starts ============================
platform linux2 -- Python 2.7.3 -- pytest-2.3.1
platform linux2 -- Python 2.7.3 -- pytest-2.3.3
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.03 seconds ====================
==================== 1 failed, 1 passed in 0.04 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 linux2 -- Python 2.7.3 -- pytest-2.3.1 -- /home/hpk/p/pytest/.tox/regen/bin/python
platform linux2 -- Python 2.7.3 -- pytest-2.3.3 -- /home/hpk/p/pytest/.tox/regen/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.03 seconds ====================
==================== 1 failed, 1 passed in 0.04 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 linux2 -- Python 2.7.3 -- pytest-2.3.1
platform linux2 -- Python 2.7.3 -- pytest-2.3.3
collected 2 items
<YamlFile 'test_simple.yml'>
<YamlItem 'ok'>
<YamlItem 'hello'>
============================= in 0.02 seconds =============================
============================= in 0.04 seconds =============================

View File

@@ -2,10 +2,10 @@
import pytest
def pytest_collect_file(path, parent):
def pytest_collect_file(parent, path):
if path.ext == ".yml" and path.basename.startswith("test"):
return YamlFile(path, parent)
class YamlFile(pytest.File):
def collect(self):
import yaml # we need a yaml parser, e.g. PyYAML
@@ -17,7 +17,7 @@ class YamlItem(pytest.Item):
def __init__(self, name, parent, spec):
super(YamlItem, self).__init__(name, parent)
self.spec = spec
def runtest(self):
for name, value in self.spec.items():
# some custom test execution (dumb example follows)

View File

@@ -104,7 +104,7 @@ this is a fully self-contained example which you can run with::
$ py.test test_scenarios.py
=========================== test session starts ============================
platform linux2 -- Python 2.7.3 -- pytest-2.3.1
platform linux2 -- Python 2.7.3 -- pytest-2.3.3
collected 4 items
test_scenarios.py ....
@@ -116,7 +116,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 linux2 -- Python 2.7.3 -- pytest-2.3.1
platform linux2 -- Python 2.7.3 -- pytest-2.3.3
collected 4 items
<Module 'test_scenarios.py'>
<Class 'TestSampleWithScenarios'>
@@ -180,7 +180,7 @@ Let's first see how it looks like at collection time::
$ py.test test_backends.py --collectonly
=========================== test session starts ============================
platform linux2 -- Python 2.7.3 -- pytest-2.3.1
platform linux2 -- Python 2.7.3 -- pytest-2.3.3
collected 2 items
<Module 'test_backends.py'>
<Function 'test_db_initialized[d1]'>
@@ -195,7 +195,7 @@ And then when we run the test::
================================= FAILURES =================================
_________________________ test_db_initialized[d2] __________________________
db = <conftest.DB2 instance at 0x233e8c0>
db = <conftest.DB2 instance at 0x1d8aef0>
def test_db_initialized(db):
# a dummy test
@@ -250,7 +250,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 0x2a73518>, a = 1, b = 2
self = <test_parametrize.TestClass instance at 0x1628cb0>, a = 1, b = 2
def test_equals(self, a, b):
> assert a == b

View File

@@ -43,7 +43,7 @@ then the test collection looks like this::
$ py.test --collectonly
=========================== test session starts ============================
platform linux2 -- Python 2.7.3 -- pytest-2.3.1
platform linux2 -- Python 2.7.3 -- pytest-2.3.3
collected 2 items
<Module 'check_myapp.py'>
<Class 'CheckMyApp'>
@@ -51,7 +51,7 @@ then the test collection looks like this::
<Function 'check_simple'>
<Function 'check_complex'>
============================= in 0.00 seconds =============================
============================= in 0.01 seconds =============================
Interpreting cmdline arguments as Python packages
-----------------------------------------------------
@@ -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 linux2 -- Python 2.7.3 -- pytest-2.3.1
platform linux2 -- Python 2.7.3 -- pytest-2.3.3
collected 3 items
<Module 'pythoncollection.py'>
<Function 'test_function'>
@@ -91,7 +91,7 @@ You can always peek at the collection tree without running tests like this::
<Function 'test_method'>
<Function 'test_anothermethod'>
============================= in 0.00 seconds =============================
============================= in 0.01 seconds =============================
customizing test collection to find all .py files
---------------------------------------------------------
@@ -135,7 +135,7 @@ interpreters and will leave out the setup.py file::
$ py.test --collectonly
=========================== test session starts ============================
platform linux2 -- Python 2.7.3 -- pytest-2.3.1
platform linux2 -- Python 2.7.3 -- pytest-2.3.3
collected 1 items
<Module 'pkg/module_py2.py'>
<Function 'test_only_on_python2'>

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 linux2 -- Python 2.7.3 -- pytest-2.3.1
platform linux2 -- Python 2.7.3 -- pytest-2.3.3
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 0x27ee810>
self = <failure_demo.TestFailing object at 0x1136710>
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 0x2786488>()
E + and 43 = <function g at 0x2786500>()
E + where 42 = <function f at 0x1146410>()
E + and 43 = <function g at 0x1146488>()
failure_demo.py:28: AssertionError
____________________ TestFailing.test_simple_multiline _____________________
self = <failure_demo.TestFailing object at 0x27ee890>
self = <failure_demo.TestFailing object at 0x11329d0>
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 0x27eea50>
self = <failure_demo.TestFailing object at 0x10d09d0>
def test_not(self):
def f():
return 42
> assert not f()
E assert not 42
E + where 42 = <function f at 0x27867d0>()
E + where 42 = <function f at 0x1146848>()
failure_demo.py:38: AssertionError
_________________ TestSpecialisedExplanations.test_eq_text _________________
self = <failure_demo.TestSpecialisedExplanations object at 0x27ee9d0>
self = <failure_demo.TestSpecialisedExplanations object at 0x10ca210>
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 0x27961d0>
self = <failure_demo.TestSpecialisedExplanations object at 0x11368d0>
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 0x2796250>
self = <failure_demo.TestSpecialisedExplanations object at 0x11340d0>
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 0x2796090>
self = <failure_demo.TestSpecialisedExplanations object at 0x10cfd90>
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 0x278cf50>
self = <failure_demo.TestSpecialisedExplanations object at 0x10d0b10>
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 0x278c250>
self = <failure_demo.TestSpecialisedExplanations object at 0x1142dd0>
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 0x278c4d0>
self = <failure_demo.TestSpecialisedExplanations object at 0x1136850>
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 0x278cbd0>
self = <failure_demo.TestSpecialisedExplanations object at 0x1134e10>
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 0x278c750>
self = <failure_demo.TestSpecialisedExplanations object at 0x1169c90>
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 0x278c5d0>
self = <failure_demo.TestSpecialisedExplanations object at 0x1142c50>
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 0x27880d0>
self = <failure_demo.TestSpecialisedExplanations object at 0x10d0d90>
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 0x2788ed0>
self = <failure_demo.TestSpecialisedExplanations object at 0x10e0110>
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 0x2788fd0>
self = <failure_demo.TestSpecialisedExplanations object at 0x10ca7d0>
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 0x2788850>
self = <failure_demo.TestSpecialisedExplanations object at 0x1142750>
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 0x27882d0>
self = <failure_demo.TestSpecialisedExplanations object at 0x1134410>
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 0x2788910>.b
E + where 1 = <failure_demo.Foo object at 0x10e07d0>.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 0x2788f50>.b
E + where <failure_demo.Foo object at 0x2788f50> = <class 'failure_demo.Foo'>()
E + where 1 = <failure_demo.Foo object at 0x1132390>.b
E + where <failure_demo.Foo object at 0x1132390> = <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 0x29558d0>
self = <failure_demo.Foo object at 0x1136fd0>
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 0x2788690>.b
E + where <failure_demo.Foo object at 0x2788690> = <class 'failure_demo.Foo'>()
E + and 2 = <failure_demo.Bar object at 0x2788d10>.b
E + where <failure_demo.Bar object at 0x2788d10> = <class 'failure_demo.Bar'>()
E + where 1 = <failure_demo.Foo object at 0x1134c50>.b
E + where <failure_demo.Foo object at 0x1134c50> = <class 'failure_demo.Foo'>()
E + and 2 = <failure_demo.Bar object at 0x1134790>.b
E + where <failure_demo.Bar object at 0x1134790> = <class 'failure_demo.Bar'>()
failure_demo.py:124: AssertionError
__________________________ TestRaises.test_raises __________________________
self = <failure_demo.TestRaises instance at 0x28000e0>
self = <failure_demo.TestRaises instance at 0x10dc098>
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 /home/hpk/p/pytest/.tox/regen/local/lib/python2.7/site-packages/_pytest/python.py:850>:1: ValueError
<0-codegen /home/hpk/p/pytest/.tox/regen/lib/python2.7/site-packages/_pytest/python.py:851>:1: ValueError
______________________ TestRaises.test_raises_doesnt _______________________
self = <failure_demo.TestRaises instance at 0x2806b90>
self = <failure_demo.TestRaises instance at 0x10d8320>
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 0x27ff518>
self = <failure_demo.TestRaises instance at 0x10c0680>
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 0x27f2290>
self = <failure_demo.TestRaises instance at 0x11604d0>
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 0x27f2fc8>
self = <failure_demo.TestRaises instance at 0x10e2290>
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 0x27f3dd0>
self = <failure_demo.TestRaises instance at 0x10e2f80>
def test_some_error(self):
> if namenotexi:
@@ -423,7 +423,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 instance at 0x28067a0>
self = <failure_demo.TestMoreErrors instance at 0x10d1b90>
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 0x27eddd0>
self = <failure_demo.TestMoreErrors instance at 0x114f3b0>
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 0x27efbd8>
self = <failure_demo.TestMoreErrors instance at 0x11496c8>
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 0x27f09e0>
self = <failure_demo.TestMoreErrors instance at 0x10cec20>
def test_startswith(self):
s = "123"
g = "456"
> assert s.startswith(g)
E assert <built-in method startswith of str object at 0x27f9ad0>('456')
E + where <built-in method startswith of str object at 0x27f9ad0> = '123'.startswith
E assert <built-in method startswith of str object at 0x113b918>('456')
E + where <built-in method startswith of str object at 0x113b918> = '123'.startswith
failure_demo.py:188: AssertionError
__________________ TestMoreErrors.test_startswith_nested ___________________
self = <failure_demo.TestMoreErrors instance at 0x27ef098>
self = <failure_demo.TestMoreErrors instance at 0x10c87a0>
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 0x27f9ad0>('456')
E + where <built-in method startswith of str object at 0x27f9ad0> = '123'.startswith
E + where '123' = <function f at 0x28169b0>()
E + and '456' = <function g at 0x280e8c0>()
E assert <built-in method startswith of str object at 0x113b918>('456')
E + where <built-in method startswith of str object at 0x113b918> = '123'.startswith
E + where '123' = <function f at 0x10bea28>()
E + and '456' = <function g at 0x10beaa0>()
failure_demo.py:195: AssertionError
_____________________ TestMoreErrors.test_global_func ______________________
self = <failure_demo.TestMoreErrors instance at 0x2800878>
self = <failure_demo.TestMoreErrors instance at 0x10c5488>
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 0x27f20e0>
self = <failure_demo.TestMoreErrors instance at 0x113f710>
def test_instance(self):
self.x = 6*7
> assert self.x != 42
E assert 42 != 42
E + where 42 = <failure_demo.TestMoreErrors instance at 0x27f20e0>.x
E + where 42 = <failure_demo.TestMoreErrors instance at 0x113f710>.x
failure_demo.py:202: AssertionError
_______________________ TestMoreErrors.test_compare ________________________
self = <failure_demo.TestMoreErrors instance at 0x27ec5a8>
self = <failure_demo.TestMoreErrors instance at 0x10bae18>
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 0x27e43b0>
self = <failure_demo.TestMoreErrors instance at 0x1160248>
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.16 seconds =========================
======================== 39 failed in 0.25 seconds =========================

View File

@@ -33,7 +33,7 @@ provide the ``cmdopt`` through a :ref:`fixture function <fixture function>`::
@pytest.fixture
def cmdopt(request):
return request.config.option.cmdopt
return request.config.getoption("--cmdopt")
Let's run this without supplying our new option::
@@ -106,7 +106,7 @@ directory with the above conftest.py::
$ py.test
=========================== test session starts ============================
platform linux2 -- Python 2.7.3 -- pytest-2.3.1
platform linux2 -- Python 2.7.3 -- pytest-2.3.3
collected 0 items
============================= in 0.00 seconds =============================
@@ -129,7 +129,7 @@ line option to control skipping of ``slow`` marked tests::
help="run slow tests")
def pytest_runtest_setup(item):
if 'slow' in item.keywords and not item.config.getvalue("runslow"):
if 'slow' in item.keywords and not item.config.getoption("--runslow"):
pytest.skip("need --runslow option to run")
We can now write a test module like this::
@@ -150,12 +150,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 linux2 -- Python 2.7.3 -- pytest-2.3.1
platform linux2 -- Python 2.7.3 -- pytest-2.3.3
collected 2 items
test_module.py .s
========================= short test summary info ==========================
SKIP [1] /tmp/doc-exec-597/conftest.py:9: need --runslow option to run
SKIP [1] /tmp/doc-exec-62/conftest.py:9: need --runslow option to run
=================== 1 passed, 1 skipped in 0.01 seconds ====================
@@ -163,7 +163,7 @@ Or run it including the ``slow`` marked test::
$ py.test --runslow
=========================== test session starts ============================
platform linux2 -- Python 2.7.3 -- pytest-2.3.1
platform linux2 -- Python 2.7.3 -- pytest-2.3.3
collected 2 items
test_module.py ..
@@ -253,7 +253,7 @@ which will add the string to the test header accordingly::
$ py.test
=========================== test session starts ============================
platform linux2 -- Python 2.7.3 -- pytest-2.3.1
platform linux2 -- Python 2.7.3 -- pytest-2.3.3
project deps: mylib-1.1
collected 0 items
@@ -276,7 +276,7 @@ which will add info only when run with "--v"::
$ py.test -v
=========================== test session starts ============================
platform linux2 -- Python 2.7.3 -- pytest-2.3.1 -- /home/hpk/p/pytest/.tox/regen/bin/python
platform linux2 -- Python 2.7.3 -- pytest-2.3.3 -- /home/hpk/p/pytest/.tox/regen/bin/python
info1: did you know that ...
did you?
collecting ... collected 0 items
@@ -287,7 +287,7 @@ and nothing when run plainly::
$ py.test
=========================== test session starts ============================
platform linux2 -- Python 2.7.3 -- pytest-2.3.1
platform linux2 -- Python 2.7.3 -- pytest-2.3.3
collected 0 items
============================= in 0.00 seconds =============================
@@ -319,7 +319,7 @@ Now we can profile which test functions execute the slowest::
$ py.test --durations=3
=========================== test session starts ============================
platform linux2 -- Python 2.7.3 -- pytest-2.3.1
platform linux2 -- Python 2.7.3 -- pytest-2.3.3
collected 3 items
test_some_are_slow.py ...
@@ -327,7 +327,7 @@ 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
0.00s call test_some_are_slow.py::test_funcfast
========================= 3 passed in 0.31 seconds =========================
incremental testing - test steps
@@ -380,7 +380,7 @@ If we run this::
$ py.test -rx
=========================== test session starts ============================
platform linux2 -- Python 2.7.3 -- pytest-2.3.1
platform linux2 -- Python 2.7.3 -- pytest-2.3.3
collected 4 items
test_step.py .Fx.
@@ -388,7 +388,7 @@ If we run this::
================================= FAILURES =================================
____________________ TestUserHandling.test_modification ____________________
self = <test_step.TestUserHandling instance at 0x1aad680>
self = <test_step.TestUserHandling instance at 0x2677b90>
def test_modification(self):
> assert 0
@@ -398,7 +398,7 @@ If we run this::
========================= short test summary info ==========================
XFAIL test_step.py::TestUserHandling::()::test_deletion
reason: previous test failed (test_modification)
============== 1 failed, 2 passed, 1 xfailed in 0.01 seconds ===============
============== 1 failed, 2 passed, 1 xfailed in 0.02 seconds ===============
We'll see that ``test_deletion`` was not executed because ``test_modification``
failed. It is reported as an "expected failure".

View File

@@ -25,10 +25,13 @@ how does py.test relate to twisted's trial?
Since some time py.test has builtin support for supporting tests
written using trial. It does not itself start a reactor, however,
and does not handle Deferreds returned from a test. Someone using
these features might eventually write a dedicated ``pytest-twisted``
plugin which will surely see strong support from the pytest development
team.
and does not handle Deferreds returned from a test in pytest style.
If you are using trial's unittest.TestCase chances are that you can
just run your tests even if you return Deferreds. In addition,
there also is a dedicated `pytest-twisted
<http://pypi.python.org/pypi/pytest-twisted`` plugin which allows to
return deferreds from pytest-style tests, allowing to use
:ref:`fixtures` and other features.
how does py.test work with Django?
++++++++++++++++++++++++++++++++++++++++++++++

View File

@@ -30,11 +30,10 @@ functions:
to configuration and component options, or to re-use fixtures
across class, module or whole test session scopes.
In addition, pytest continues to support :ref:`xunitsetup` which it
originally introduced in 2005. You can mix both styles, moving
incrementally from classic to new style, if you prefer. You can also
start out from existing :ref:`unittest.TestCase style <unittest.TestCase>`
or :ref:`nose based <nosestyle>` projects.
In addition, pytest continues to support :ref:`xunitsetup`. You can mix
both styles, moving incrementally from classic to new style, as you
prefer. You can also start out from existing :ref:`unittest.TestCase
style <unittest.TestCase>` or :ref:`nose based <nosestyle>` projects.
.. _`funcargs`:
.. _`funcarg mechanism`:
@@ -66,13 +65,13 @@ using it::
assert "merlinux" in msg
assert 0 # for demo purposes
Here, the ``test_function`` needs the ``smtp`` fixture value. pytest
Here, the ``test_ehlo`` needs the ``smtp`` fixture value. pytest
will discover and call the :py:func:`@pytest.fixture <_pytest.python.fixture>`
marked ``smtp`` fixture function. Running the test looks like this::
$ py.test test_smtpsimple.py
=========================== test session starts ============================
platform linux2 -- Python 2.7.3 -- pytest-2.3.1
platform linux2 -- Python 2.7.3 -- pytest-2.3.3
collected 1 items
test_smtpsimple.py F
@@ -80,7 +79,7 @@ marked ``smtp`` fixture function. Running the test looks like this::
================================= FAILURES =================================
________________________________ test_ehlo _________________________________
smtp = <smtplib.SMTP instance at 0x1ab68c0>
smtp = <smtplib.SMTP instance at 0x1992a70>
def test_ehlo(smtp):
response, msg = smtp.ehlo()
@@ -90,7 +89,7 @@ marked ``smtp`` fixture function. Running the test looks like this::
E assert 0
test_smtpsimple.py:12: AssertionError
========================= 1 failed in 0.12 seconds =========================
========================= 1 failed in 0.30 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
@@ -190,7 +189,7 @@ inspect what is going on and can now run the tests::
$ py.test test_module.py
=========================== test session starts ============================
platform linux2 -- Python 2.7.3 -- pytest-2.3.1
platform linux2 -- Python 2.7.3 -- pytest-2.3.3
collected 2 items
test_module.py FF
@@ -198,7 +197,7 @@ inspect what is going on and can now run the tests::
================================= FAILURES =================================
________________________________ test_ehlo _________________________________
smtp = <smtplib.SMTP instance at 0x2c35488>
smtp = <smtplib.SMTP instance at 0x2b8a248>
def test_ehlo(smtp):
response = smtp.ehlo()
@@ -210,7 +209,7 @@ inspect what is going on and can now run the tests::
test_module.py:6: AssertionError
________________________________ test_noop _________________________________
smtp = <smtplib.SMTP instance at 0x2c35488>
smtp = <smtplib.SMTP instance at 0x2b8a248>
def test_noop(smtp):
response = smtp.noop()
@@ -219,7 +218,7 @@ inspect what is going on and can now run the tests::
E assert 0
test_module.py:11: AssertionError
========================= 2 failed in 0.13 seconds =========================
========================= 2 failed in 0.48 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
@@ -272,7 +271,7 @@ using it has executed::
$ py.test -s -q --tb=no
FF
finalizing <smtplib.SMTP instance at 0x2afd830>
finalizing <smtplib.SMTP instance at 0x1584908>
We see that the ``smtp`` instance is finalized after the two
tests using it tests executed. If we had specified ``scope='function'``
@@ -343,7 +342,7 @@ So let's just do another run::
================================= FAILURES =================================
__________________________ test_ehlo[merlinux.eu] __________________________
smtp = <smtplib.SMTP instance at 0x1bd3710>
smtp = <smtplib.SMTP instance at 0x2368248>
def test_ehlo(smtp):
response = smtp.ehlo()
@@ -355,7 +354,7 @@ So let's just do another run::
test_module.py:6: AssertionError
__________________________ test_noop[merlinux.eu] __________________________
smtp = <smtplib.SMTP instance at 0x1bd3710>
smtp = <smtplib.SMTP instance at 0x2368248>
def test_noop(smtp):
response = smtp.noop()
@@ -366,7 +365,7 @@ So let's just do another run::
test_module.py:11: AssertionError
________________________ test_ehlo[mail.python.org] ________________________
smtp = <smtplib.SMTP instance at 0x1c58128>
smtp = <smtplib.SMTP instance at 0x2377680>
def test_ehlo(smtp):
response = smtp.ehlo()
@@ -377,7 +376,7 @@ So let's just do another run::
test_module.py:5: AssertionError
________________________ test_noop[mail.python.org] ________________________
smtp = <smtplib.SMTP instance at 0x1c58128>
smtp = <smtplib.SMTP instance at 0x2377680>
def test_noop(smtp):
response = smtp.noop()
@@ -425,13 +424,13 @@ Here we declare an ``app`` fixture which receives the previously defined
$ py.test -v test_appsetup.py
=========================== test session starts ============================
platform linux2 -- Python 2.7.3 -- pytest-2.3.1 -- /home/hpk/p/pytest/.tox/regen/bin/python
platform linux2 -- Python 2.7.3 -- pytest-2.3.3 -- /home/hpk/p/pytest/.tox/regen/bin/python
collecting ... collected 2 items
test_appsetup.py:12: test_smtp_exists[merlinux.eu] PASSED
test_appsetup.py:12: test_smtp_exists[mail.python.org] PASSED
========================= 2 passed in 0.20 seconds =========================
========================= 2 passed in 6.79 seconds =========================
Due to the parametrization of ``smtp`` the test will run twice with two
different ``App`` instances and respective smtp servers. There is no
@@ -490,7 +489,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 linux2 -- Python 2.7.3 -- pytest-2.3.1 -- /home/hpk/p/pytest/.tox/regen/bin/python
platform linux2 -- Python 2.7.3 -- pytest-2.3.3 -- /home/hpk/p/pytest/.tox/regen/bin/python
collecting ... collected 8 items
test_module.py:16: test_0[1] PASSED

View File

@@ -23,7 +23,7 @@ Installation options::
To check your installation has installed the correct version::
$ py.test --version
This is py.test version 2.3.1, imported from /home/hpk/p/pytest/.tox/regen/local/lib/python2.7/site-packages/pytest.pyc
This is py.test version 2.3.3, imported from /home/hpk/p/pytest/.tox/regen/lib/python2.7/site-packages/pytest.pyc
If you get an error checkout :ref:`installation issues`.
@@ -45,7 +45,7 @@ That's it. You can execute the test function now::
$ py.test
=========================== test session starts ============================
platform linux2 -- Python 2.7.3 -- pytest-2.3.1
platform linux2 -- Python 2.7.3 -- pytest-2.3.3
collected 1 items
test_sample.py F
@@ -122,7 +122,7 @@ run the module by passing its filename::
================================= FAILURES =================================
____________________________ TestClass.test_two ____________________________
self = <test_class.TestClass instance at 0x10de710>
self = <test_class.TestClass instance at 0x22a4d40>
def test_two(self):
x = "hello"
@@ -157,7 +157,7 @@ before performing the test function call. Let's just run it::
================================= FAILURES =================================
_____________________________ test_needsfiles ______________________________
tmpdir = local('/tmp/pytest-1516/test_needsfiles0')
tmpdir = local('/tmp/pytest-594/test_needsfiles0')
def test_needsfiles(tmpdir):
print tmpdir
@@ -166,7 +166,7 @@ before performing the test function call. Let's just run it::
test_tmpdir.py:3: AssertionError
----------------------------- Captured stdout ------------------------------
/tmp/pytest-1516/test_needsfiles0
/tmp/pytest-594/test_needsfiles0
Before the test runs, a unique-per-test-invocation temporary directory
was created. More info at :ref:`tmpdir handling`.

View File

@@ -1,7 +1,7 @@
.. _features:
pytest: makes you write better programs
pytest: helps you write better programs
=============================================
**a mature full-featured Python testing tool**
@@ -34,8 +34,9 @@ pytest: makes you write better programs
**integrates many common testing methods**:
- can run many ``nose``, ``unittest.py`` and ``doctest.py`` style
tests, including running testcases made for Django and trial
- multi-paradigm: pytest can run many ``nose``, ``unittest.py`` and
``doctest.py`` style test suites, including running testcases made for
Django and trial
- supports :ref:`good integration practises <goodpractises>`
- supports extended :ref:`xUnit style setup <xunitsetup>`
- supports domain-specific :ref:`non-python tests`

View File

@@ -53,7 +53,7 @@ which will thus run three times::
$ py.test
=========================== test session starts ============================
platform linux2 -- Python 2.7.3 -- pytest-2.3.1
platform linux2 -- Python 2.7.3 -- pytest-2.3.3
collected 3 items
test_expectation.py ..F
@@ -135,8 +135,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 0x2b21d78ed030>()
E + where <built-in method isalpha of str object at 0x2b21d78ed030> = '!'.isalpha
E assert <built-in method isalpha of str object at 0x2b1792721fa8>()
E + where <built-in method isalpha of str object at 0x2b1792721fa8> = '!'.isalpha
test_strings.py:3: AssertionError
@@ -149,7 +149,7 @@ listlist::
$ py.test -q -rs test_strings.py
s
========================= short test summary info ==========================
SKIP [1] /home/hpk/p/pytest/.tox/regen/local/lib/python2.7/site-packages/_pytest/python.py:959: got empty parameter set, function test_valid_string at /tmp/doc-exec-564/test_strings.py:1
SKIP [1] /home/hpk/p/pytest/.tox/regen/lib/python2.7/site-packages/_pytest/python.py:960: got empty parameter set, function test_valid_string at /tmp/doc-exec-26/test_strings.py:1
For further examples, you might want to look at :ref:`more
parametrization examples <paramexamples>`.

View File

@@ -5,7 +5,7 @@ Working with plugins and conftest files
py.test implements all aspects of configuration, collection, running and reporting by calling `well specified hooks`_. Virtually any Python module can be registered as a plugin. It can implement any number of hook functions (usually two or three) which all have a ``pytest_`` prefix, making hook functions easy to distinguish and find. There are three basic location types:
* `builtin plugins`_: loaded from py.test's own ``pytest/plugin`` directory.
* `builtin plugins`_: loaded from py.test's internal ``_pytest`` directory.
* `external plugins`_: modules discovered through `setuptools entry points`_
* `conftest.py plugins`_: modules auto-discovered in test directories
@@ -71,6 +71,10 @@ there is no need to activate it. Here is a initial list of known plugins:
* `pytest-django <http://pypi.python.org/pypi/pytest-django>`_: write tests
for `django`_ apps, using pytest integration.
* `pytest-twisted <http://pypi.python.org/pypi/pytest-twisted>`_: write tests
for `twisted <http://twistedmatrix.com>`_ apps, starting a reactor and
processing deferreds from test functions.
* `pytest-capturelog <http://pypi.python.org/pypi/pytest-capturelog>`_:
to capture and assert about messages from the logging module
@@ -151,6 +155,8 @@ If a package is installed this way, py.test will load
``myproject.pluginmodule`` as a plugin which can define
`well specified hooks`_.
.. _`pluginorder`:
Plugin discovery order at tool startup
--------------------------------------------
@@ -171,6 +177,7 @@ py.test loads plugin modules at tool startup in the following way:
* by recursively loading all plugins specified by the
``pytest_plugins`` variable in ``conftest.py`` files
Requiring/Loading plugins in a test module or conftest file
-------------------------------------------------------------

View File

@@ -132,7 +132,7 @@ Running it with the report-on-xfail option gives this output::
example $ py.test -rx xfail_demo.py
=========================== test session starts ============================
platform linux2 -- Python 2.7.3 -- pytest-2.3.1
platform linux2 -- Python 2.7.3 -- pytest-2.3.3
collected 6 items
xfail_demo.py xxxxxx
@@ -149,7 +149,7 @@ Running it with the report-on-xfail option gives this output::
XFAIL xfail_demo.py::test_hello6
reason: reason
======================== 6 xfailed in 0.03 seconds =========================
======================== 6 xfailed in 0.05 seconds =========================
.. _`evaluation of skipif/xfail conditions`:

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 linux2 -- Python 2.7.3 -- pytest-2.3.1
platform linux2 -- Python 2.7.3 -- pytest-2.3.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-1517/test_create_file0')
tmpdir = local('/tmp/pytest-595/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.04 seconds =========================
========================= 1 failed in 0.03 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 linux2 -- Python 2.7.3 -- pytest-2.3.1
platform linux2 -- Python 2.7.3 -- pytest-2.3.3
collected 2 items
test_unittest_db.py FF
@@ -101,7 +101,7 @@ 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.DummyDB instance at 0x25b1998>
E AssertionError: <conftest.DummyDB instance at 0x269e5a8>
test_unittest_db.py:9: AssertionError
___________________________ MyTest.test_method2 ____________________________
@@ -110,7 +110,7 @@ the ``self.db`` values in the traceback::
def test_method2(self):
> assert 0, self.db # fail for demo purposes
E AssertionError: <conftest.DummyDB instance at 0x25b1998>
E AssertionError: <conftest.DummyDB instance at 0x269e5a8>
test_unittest_db.py:12: AssertionError
========================= 2 failed in 0.02 seconds =========================

View File

@@ -5,13 +5,16 @@
classic xunit-style setup
========================================
.. note::
This section describes the classic way how you can implement setup and
teardown on a per-module/class/function basis. It remains fully
supported but it is recommended to rather use the more flexible,
more modular and more scalable :ref:`fixture functions
<fixture>` for implementing for fixing test state for your tests.
This section describes a classic and popular way how you can implement
fixtures (setup and teardown test state) on a per-module/class/function basis.
pytest started supporting these methods around 2005 and subsequently
nose and the standard library introduced them (under slightly different
names). While these setup/teardown methods are and will remain fully
supported you may also use pytest's more powerful :ref:`fixture mechanism
<fixture>` which leverages the concept of dependency injection, allowing
for a more modular and more scalable approach for managing test state,
especially for larger projects and for functional testing. It is safe
to mix both fixture mechanisms.
Module level setup/teardown
--------------------------------------

View File

@@ -1,21 +1,45 @@
import os, sys
try:
from setuptools import setup
from setuptools import setup, Command
except ImportError:
from distribute_setup import use_setuptools
use_setuptools()
from setuptools import setup
from setuptools import setup, Command
long_description = """
cross-project testing tool for Python.
The `py.test`` testing tool makes it easy to write small tests, yet
scales to support complex functional testing. It provides
Platforms: Linux, Win32, OSX
- `auto-discovery
<http://pytest.org/latest/goodpractises.html#python-test-discovery>`_
of test modules and functions,
- detailed info on failing `assert statements <http://pytest.org/latest/assert.html>`_ (no need to remember ``self.assert*`` names)
- `modular fixtures <http://pytest.org/latest/fixture.html>`_ for
managing small or parametrized long-lived test resources.
- multi-paradigm support: you can use ``py.test`` 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.4 all the way up to Python3.3,
PyPy and Jython.
Interpreters: Python versions 2.4 through to 3.3, Jython 2.5.1 and PyPy-1.9
- many `external plugins <http://pytest.org/latest/plugins.html#installing-external-plugins-searching>`_.
Bugs and issues: http://bitbucket.org/hpk42/pytest/issues/
A simple example for a test::
Web page: http://pytest.org
# content of test_module.py
def test_function():
i = 4
assert i == 3
which can be run with ``py.test test_module.py``. See `getting-started <http://pytest.org/latest/getting-started.html#our-first-test-run>`_ for more examples.
For much more info, including PDF docs, see
http://pytest.org
and report bugs at:
http://bitbucket.org/hpk42/pytest/issues/
(c) Holger Krekel and others, 2004-2012
"""
@@ -24,15 +48,16 @@ def main():
name='pytest',
description='py.test: simple powerful testing with Python',
long_description = long_description,
version='2.3.1',
version='2.3.3',
url='http://pytest.org',
license='MIT license',
platforms=['unix', 'linux', 'osx', 'cygwin', 'win32'],
author='Holger Krekel, Benjamin Peterson, Ronny Pfannschmidt, Floris Bruynooghe and others',
author_email='holger at merlinux.eu',
entry_points= make_entry_points(),
cmdclass = {'test': PyTest},
# the following should be enabled for release
install_requires=['py>=1.4.10'],
install_requires=['py>=1.4.12'],
classifiers=['Development Status :: 6 - Mature',
'Intended Audience :: Developers',
'License :: OSI Approved :: MIT License',
@@ -42,8 +67,10 @@ def main():
'Topic :: Software Development :: Testing',
'Topic :: Software Development :: Libraries',
'Topic :: Utilities',
'Programming Language :: Python',
'Programming Language :: Python :: 3'],
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 3'] + [
("Programming Language :: Python :: %s" % x) for x in
"2.4 2.5 2.6 2.7 3.0 3.1 3.2 3.3".split()],
packages=['_pytest', '_pytest.assertion'],
py_modules=['pytest'],
zip_safe=False,
@@ -69,5 +96,20 @@ def make_entry_points():
l = ["%s = %s" % (x, points[x]) for x in keys]
return {'console_scripts': l}
class PyTest(Command):
user_options = []
def initialize_options(self):
pass
def finalize_options(self):
pass
def run(self):
import sys,subprocess
PPATH=[x for x in os.environ.get("PYTHONPATH", "").split(":") if x]
PPATH.insert(0, os.getcwd())
os.environ["PYTHONPATH"] = ":".join(PPATH)
errno = subprocess.call([sys.executable, 'pytest.py'])
raise SystemExit(errno)
if __name__ == '__main__':
main()

721
testing/python/collect.py Normal file
View File

@@ -0,0 +1,721 @@
import pytest, py, sys
from _pytest import python as funcargs
from _pytest.python import FixtureLookupError
class TestModule:
def test_failing_import(self, testdir):
modcol = testdir.getmodulecol("import alksdjalskdjalkjals")
pytest.raises(ImportError, modcol.collect)
pytest.raises(ImportError, modcol.collect)
def test_import_duplicate(self, testdir):
a = testdir.mkdir("a")
b = testdir.mkdir("b")
p = a.ensure("test_whatever.py")
p.pyimport()
del py.std.sys.modules['test_whatever']
b.ensure("test_whatever.py")
result = testdir.runpytest()
result.stdout.fnmatch_lines([
"*import*mismatch*",
"*imported*test_whatever*",
"*%s*" % a.join("test_whatever.py"),
"*not the same*",
"*%s*" % b.join("test_whatever.py"),
"*HINT*",
])
def test_syntax_error_in_module(self, testdir):
modcol = testdir.getmodulecol("this is a syntax error")
pytest.raises(modcol.CollectError, modcol.collect)
pytest.raises(modcol.CollectError, modcol.collect)
def test_module_considers_pluginmanager_at_import(self, testdir):
modcol = testdir.getmodulecol("pytest_plugins='xasdlkj',")
pytest.raises(ImportError, "modcol.obj")
class TestClass:
def test_class_with_init_not_collected(self, testdir):
modcol = testdir.getmodulecol("""
class TestClass1:
def __init__(self):
pass
class TestClass2(object):
def __init__(self):
pass
""")
l = modcol.collect()
assert len(l) == 0
def test_class_subclassobject(self, testdir):
testdir.getmodulecol("""
class test(object):
pass
""")
result = testdir.runpytest()
result.stdout.fnmatch_lines([
"*collected 0*",
])
def test_setup_teardown_class_as_classmethod(self, testdir):
testdir.makepyfile(test_mod1="""
class TestClassMethod:
@classmethod
def setup_class(cls):
pass
def test_1(self):
pass
@classmethod
def teardown_class(cls):
pass
""")
result = testdir.runpytest()
result.stdout.fnmatch_lines([
"*1 passed*",
])
class TestGenerator:
def test_generative_functions(self, testdir):
modcol = testdir.getmodulecol("""
def func1(arg, arg2):
assert arg == arg2
def test_gen():
yield func1, 17, 3*5
yield func1, 42, 6*7
""")
colitems = modcol.collect()
assert len(colitems) == 1
gencol = colitems[0]
assert isinstance(gencol, pytest.Generator)
gencolitems = gencol.collect()
assert len(gencolitems) == 2
assert isinstance(gencolitems[0], pytest.Function)
assert isinstance(gencolitems[1], pytest.Function)
assert gencolitems[0].name == '[0]'
assert gencolitems[0].obj.__name__ == 'func1'
def test_generative_methods(self, testdir):
modcol = testdir.getmodulecol("""
def func1(arg, arg2):
assert arg == arg2
class TestGenMethods:
def test_gen(self):
yield func1, 17, 3*5
yield func1, 42, 6*7
""")
gencol = modcol.collect()[0].collect()[0].collect()[0]
assert isinstance(gencol, pytest.Generator)
gencolitems = gencol.collect()
assert len(gencolitems) == 2
assert isinstance(gencolitems[0], pytest.Function)
assert isinstance(gencolitems[1], pytest.Function)
assert gencolitems[0].name == '[0]'
assert gencolitems[0].obj.__name__ == 'func1'
def test_generative_functions_with_explicit_names(self, testdir):
modcol = testdir.getmodulecol("""
def func1(arg, arg2):
assert arg == arg2
def test_gen():
yield "seventeen", func1, 17, 3*5
yield "fortytwo", func1, 42, 6*7
""")
colitems = modcol.collect()
assert len(colitems) == 1
gencol = colitems[0]
assert isinstance(gencol, pytest.Generator)
gencolitems = gencol.collect()
assert len(gencolitems) == 2
assert isinstance(gencolitems[0], pytest.Function)
assert isinstance(gencolitems[1], pytest.Function)
assert gencolitems[0].name == "['seventeen']"
assert gencolitems[0].obj.__name__ == 'func1'
assert gencolitems[1].name == "['fortytwo']"
assert gencolitems[1].obj.__name__ == 'func1'
def test_generative_functions_unique_explicit_names(self, testdir):
# generative
modcol = testdir.getmodulecol("""
def func(): pass
def test_gen():
yield "name", func
yield "name", func
""")
colitems = modcol.collect()
assert len(colitems) == 1
gencol = colitems[0]
assert isinstance(gencol, pytest.Generator)
pytest.raises(ValueError, "gencol.collect()")
def test_generative_methods_with_explicit_names(self, testdir):
modcol = testdir.getmodulecol("""
def func1(arg, arg2):
assert arg == arg2
class TestGenMethods:
def test_gen(self):
yield "m1", func1, 17, 3*5
yield "m2", func1, 42, 6*7
""")
gencol = modcol.collect()[0].collect()[0].collect()[0]
assert isinstance(gencol, pytest.Generator)
gencolitems = gencol.collect()
assert len(gencolitems) == 2
assert isinstance(gencolitems[0], pytest.Function)
assert isinstance(gencolitems[1], pytest.Function)
assert gencolitems[0].name == "['m1']"
assert gencolitems[0].obj.__name__ == 'func1'
assert gencolitems[1].name == "['m2']"
assert gencolitems[1].obj.__name__ == 'func1'
def test_order_of_execution_generator_same_codeline(self, testdir, tmpdir):
o = testdir.makepyfile("""
def test_generative_order_of_execution():
import py, pytest
test_list = []
expected_list = list(range(6))
def list_append(item):
test_list.append(item)
def assert_order_of_execution():
py.builtin.print_('expected order', expected_list)
py.builtin.print_('but got ', test_list)
assert test_list == expected_list
for i in expected_list:
yield list_append, i
yield assert_order_of_execution
""")
reprec = testdir.inline_run(o)
passed, skipped, failed = reprec.countoutcomes()
assert passed == 7
assert not skipped and not failed
def test_order_of_execution_generator_different_codeline(self, testdir):
o = testdir.makepyfile("""
def test_generative_tests_different_codeline():
import py, pytest
test_list = []
expected_list = list(range(3))
def list_append_2():
test_list.append(2)
def list_append_1():
test_list.append(1)
def list_append_0():
test_list.append(0)
def assert_order_of_execution():
py.builtin.print_('expected order', expected_list)
py.builtin.print_('but got ', test_list)
assert test_list == expected_list
yield list_append_0
yield list_append_1
yield list_append_2
yield assert_order_of_execution
""")
reprec = testdir.inline_run(o)
passed, skipped, failed = reprec.countoutcomes()
assert passed == 4
assert not skipped and not failed
def test_setupstate_is_preserved_134(self, testdir):
# yield-based tests are messy wrt to setupstate because
# during collection they already invoke setup functions
# and then again when they are run. For now, we want to make sure
# that the old 1.3.4 behaviour is preserved such that all
# yielded functions all share the same "self" instance that
# has been used during collection.
o = testdir.makepyfile("""
setuplist = []
class TestClass:
def setup_method(self, func):
#print "setup_method", self, func
setuplist.append(self)
self.init = 42
def teardown_method(self, func):
self.init = None
def test_func1(self):
pass
def test_func2(self):
yield self.func2
yield self.func2
def func2(self):
assert self.init
def test_setuplist():
# once for test_func2 during collection
# once for test_func1 during test run
# once for test_func2 during test run
#print setuplist
assert len(setuplist) == 3, len(setuplist)
assert setuplist[0] == setuplist[2], setuplist
assert setuplist[1] != setuplist[2], setuplist
""")
reprec = testdir.inline_run(o, '-v')
passed, skipped, failed = reprec.countoutcomes()
assert passed == 4
assert not skipped and not failed
class TestFunction:
def test_getmodulecollector(self, testdir):
item = testdir.getitem("def test_func(): pass")
modcol = item.getparent(pytest.Module)
assert isinstance(modcol, pytest.Module)
assert hasattr(modcol.obj, 'test_func')
def test_function_equality(self, testdir, tmpdir):
from _pytest.python import FixtureManager
config = testdir.parseconfigure()
session = testdir.Session(config)
session._fixturemanager = FixtureManager(session)
def func1():
pass
def func2():
pass
f1 = pytest.Function(name="name", parent=session, config=config,
args=(1,), callobj=func1)
f2 = pytest.Function(name="name",config=config,
args=(1,), callobj=func2, parent=session)
assert not f1 == f2
assert f1 != f2
f3 = pytest.Function(name="name", parent=session, config=config,
args=(1,2), callobj=func2)
assert not f3 == f2
assert f3 != f2
assert not f3 == f1
assert f3 != f1
f1_b = pytest.Function(name="name", parent=session, config=config,
args=(1,), callobj=func1)
assert f1 == f1_b
assert not f1 != f1_b
def test_issue197_parametrize_emptyset(self, testdir):
testdir.makepyfile("""
import pytest
@pytest.mark.parametrize('arg', [])
def test_function(arg):
pass
""")
reprec = testdir.inline_run()
reprec.assertoutcome(skipped=1)
def test_issue213_parametrize_value_no_equal(self, testdir):
testdir.makepyfile("""
import pytest
class A:
def __eq__(self, other):
raise ValueError("not possible")
@pytest.mark.parametrize('arg', [A()])
def test_function(arg):
assert arg.__class__.__name__ == "A"
""")
reprec = testdir.inline_run()
reprec.assertoutcome(passed=1)
def test_function_equality_with_callspec(self, testdir, tmpdir):
items = testdir.getitems("""
import pytest
@pytest.mark.parametrize('arg', [1,2])
def test_function(arg):
pass
""")
assert items[0] != items[1]
assert not (items[0] == items[1])
def test_pyfunc_call(self, testdir):
item = testdir.getitem("def test_func(): raise ValueError")
config = item.config
class MyPlugin1:
def pytest_pyfunc_call(self, pyfuncitem):
raise ValueError
class MyPlugin2:
def pytest_pyfunc_call(self, pyfuncitem):
return True
config.pluginmanager.register(MyPlugin1())
config.pluginmanager.register(MyPlugin2())
config.hook.pytest_pyfunc_call(pyfuncitem=item)
class TestSorting:
def test_check_equality(self, testdir):
modcol = testdir.getmodulecol("""
def test_pass(): pass
def test_fail(): assert 0
""")
fn1 = testdir.collect_by_name(modcol, "test_pass")
assert isinstance(fn1, pytest.Function)
fn2 = testdir.collect_by_name(modcol, "test_pass")
assert isinstance(fn2, pytest.Function)
assert fn1 == fn2
assert fn1 != modcol
if py.std.sys.version_info < (3, 0):
assert cmp(fn1, fn2) == 0
assert hash(fn1) == hash(fn2)
fn3 = testdir.collect_by_name(modcol, "test_fail")
assert isinstance(fn3, pytest.Function)
assert not (fn1 == fn3)
assert fn1 != fn3
for fn in fn1,fn2,fn3:
assert fn != 3
assert fn != modcol
assert fn != [1,2,3]
assert [1,2,3] != fn
assert modcol != fn
def test_allow_sane_sorting_for_decorators(self, testdir):
modcol = testdir.getmodulecol("""
def dec(f):
g = lambda: f(2)
g.place_as = f
return g
def test_b(y):
pass
test_b = dec(test_b)
def test_a(y):
pass
test_a = dec(test_a)
""")
colitems = modcol.collect()
assert len(colitems) == 2
assert [item.name for item in colitems] == ['test_b', 'test_a']
class TestConftestCustomization:
def test_pytest_pycollect_module(self, testdir):
testdir.makeconftest("""
import pytest
class MyModule(pytest.Module):
pass
def pytest_pycollect_makemodule(path, parent):
if path.basename == "test_xyz.py":
return MyModule(path, parent)
""")
testdir.makepyfile("def test_some(): pass")
testdir.makepyfile(test_xyz="def test_func(): pass")
result = testdir.runpytest("--collectonly")
result.stdout.fnmatch_lines([
"*<Module*test_pytest*",
"*<MyModule*xyz*",
])
def test_customized_pymakemodule_issue205_subdir(self, testdir):
b = testdir.mkdir("a").mkdir("b")
b.join("conftest.py").write(py.code.Source("""
def pytest_pycollect_makemodule(__multicall__):
mod = __multicall__.execute()
mod.obj.hello = "world"
return mod
"""))
b.join("test_module.py").write(py.code.Source("""
def test_hello():
assert hello == "world"
"""))
reprec = testdir.inline_run()
reprec.assertoutcome(passed=1)
def test_customized_pymakeitem(self, testdir):
b = testdir.mkdir("a").mkdir("b")
b.join("conftest.py").write(py.code.Source("""
def pytest_pycollect_makeitem(__multicall__):
result = __multicall__.execute()
if result:
for func in result:
func._some123 = "world"
return result
"""))
b.join("test_module.py").write(py.code.Source("""
import pytest
@pytest.fixture()
def obj(request):
return request.node._some123
def test_hello(obj):
assert obj == "world"
"""))
reprec = testdir.inline_run()
reprec.assertoutcome(passed=1)
def test_pytest_pycollect_makeitem(self, testdir):
testdir.makeconftest("""
import pytest
class MyFunction(pytest.Function):
pass
def pytest_pycollect_makeitem(collector, name, obj):
if name == "some":
return MyFunction(name, collector)
""")
testdir.makepyfile("def some(): pass")
result = testdir.runpytest("--collectonly")
result.stdout.fnmatch_lines([
"*MyFunction*some*",
])
def test_makeitem_non_underscore(self, testdir, monkeypatch):
modcol = testdir.getmodulecol("def _hello(): pass")
l = []
monkeypatch.setattr(pytest.Module, 'makeitem',
lambda self, name, obj: l.append(name))
l = modcol.collect()
assert '_hello' not in l
def test_setup_only_available_in_subdir(testdir):
sub1 = testdir.mkpydir("sub1")
sub2 = testdir.mkpydir("sub2")
sub1.join("conftest.py").write(py.code.Source("""
import pytest
def pytest_runtest_setup(item):
assert item.fspath.purebasename == "test_in_sub1"
def pytest_runtest_call(item):
assert item.fspath.purebasename == "test_in_sub1"
def pytest_runtest_teardown(item):
assert item.fspath.purebasename == "test_in_sub1"
"""))
sub2.join("conftest.py").write(py.code.Source("""
import pytest
def pytest_runtest_setup(item):
assert item.fspath.purebasename == "test_in_sub2"
def pytest_runtest_call(item):
assert item.fspath.purebasename == "test_in_sub2"
def pytest_runtest_teardown(item):
assert item.fspath.purebasename == "test_in_sub2"
"""))
sub1.join("test_in_sub1.py").write("def test_1(): pass")
sub2.join("test_in_sub2.py").write("def test_2(): pass")
result = testdir.runpytest("-v", "-s")
result.stdout.fnmatch_lines([
"*2 passed*"
])
def test_modulecol_roundtrip(testdir):
modcol = testdir.getmodulecol("pass", withinit=True)
trail = modcol.nodeid
newcol = modcol.session.perform_collect([trail], genitems=0)[0]
assert modcol.name == newcol.name
class TestTracebackCutting:
def test_skip_simple(self):
excinfo = pytest.raises(pytest.skip.Exception, 'pytest.skip("xxx")')
assert excinfo.traceback[-1].frame.code.name == "skip"
assert excinfo.traceback[-1].ishidden()
def test_traceback_argsetup(self, testdir):
testdir.makeconftest("""
def pytest_funcarg__hello(request):
raise ValueError("xyz")
""")
p = testdir.makepyfile("def test(hello): pass")
result = testdir.runpytest(p)
assert result.ret != 0
out = result.stdout.str()
assert out.find("xyz") != -1
assert out.find("conftest.py:2: ValueError") != -1
numentries = out.count("_ _ _") # separator for traceback entries
assert numentries == 0
result = testdir.runpytest("--fulltrace", p)
out = result.stdout.str()
assert out.find("conftest.py:2: ValueError") != -1
numentries = out.count("_ _ _ _") # separator for traceback entries
assert numentries > 3
def test_traceback_error_during_import(self, testdir):
testdir.makepyfile("""
x = 1
x = 2
x = 17
asd
""")
result = testdir.runpytest()
assert result.ret != 0
out = result.stdout.str()
assert "x = 1" not in out
assert "x = 2" not in out
result.stdout.fnmatch_lines([
">*asd*",
"E*NameError*",
])
result = testdir.runpytest("--fulltrace")
out = result.stdout.str()
assert "x = 1" in out
assert "x = 2" in out
result.stdout.fnmatch_lines([
">*asd*",
"E*NameError*",
])
class TestReportInfo:
def test_itemreport_reportinfo(self, testdir, linecomp):
testdir.makeconftest("""
import pytest
class MyFunction(pytest.Function):
def reportinfo(self):
return "ABCDE", 42, "custom"
def pytest_pycollect_makeitem(collector, name, obj):
if name == "test_func":
return MyFunction(name, parent=collector)
""")
item = testdir.getitem("def test_func(): pass")
runner = item.config.pluginmanager.getplugin("runner")
assert item.location == ("ABCDE", 42, "custom")
def test_func_reportinfo(self, testdir):
item = testdir.getitem("def test_func(): pass")
fspath, lineno, modpath = item.reportinfo()
assert fspath == item.fspath
assert lineno == 0
assert modpath == "test_func"
def test_class_reportinfo(self, testdir):
modcol = testdir.getmodulecol("""
# lineno 0
class TestClass:
def test_hello(self): pass
""")
classcol = testdir.collect_by_name(modcol, "TestClass")
fspath, lineno, msg = classcol.reportinfo()
assert fspath == modcol.fspath
assert lineno == 1
assert msg == "TestClass"
def test_generator_reportinfo(self, testdir):
modcol = testdir.getmodulecol("""
# lineno 0
def test_gen():
def check(x):
assert x
yield check, 3
""")
gencol = testdir.collect_by_name(modcol, "test_gen")
fspath, lineno, modpath = gencol.reportinfo()
assert fspath == modcol.fspath
assert lineno == 1
assert modpath == "test_gen"
genitem = gencol.collect()[0]
fspath, lineno, modpath = genitem.reportinfo()
assert fspath == modcol.fspath
assert lineno == 2
assert modpath == "test_gen[0]"
"""
def test_func():
pass
def test_genfunc():
def check(x):
pass
yield check, 3
class TestClass:
def test_method(self):
pass
"""
def test_customized_python_discovery(testdir):
testdir.makeini("""
[pytest]
python_files=check_*.py
python_classes=Check
python_functions=check
""")
p = testdir.makepyfile("""
def check_simple():
pass
class CheckMyApp:
def check_meth(self):
pass
""")
p2 = p.new(basename=p.basename.replace("test", "check"))
p.move(p2)
result = testdir.runpytest("--collectonly", "-s")
result.stdout.fnmatch_lines([
"*check_customized*",
"*check_simple*",
"*CheckMyApp*",
"*check_meth*",
])
result = testdir.runpytest()
assert result.ret == 0
result.stdout.fnmatch_lines([
"*2 passed*",
])
def test_collector_attributes(testdir):
testdir.makeconftest("""
import pytest
def pytest_pycollect_makeitem(collector):
assert collector.Function == pytest.Function
assert collector.Class == pytest.Class
assert collector.Instance == pytest.Instance
assert collector.Module == pytest.Module
""")
testdir.makepyfile("""
def test_hello():
pass
""")
result = testdir.runpytest()
result.stdout.fnmatch_lines([
"*1 passed*",
])
def test_customize_through_attributes(testdir):
testdir.makeconftest("""
import pytest
class MyFunction(pytest.Function):
pass
class MyInstance(pytest.Instance):
Function = MyFunction
class MyClass(pytest.Class):
Instance = MyInstance
def pytest_pycollect_makeitem(collector, name, obj):
if name.startswith("MyTestClass"):
return MyClass(name, parent=collector)
""")
testdir.makepyfile("""
class MyTestClass:
def test_hello(self):
pass
""")
result = testdir.runpytest("--collectonly")
result.stdout.fnmatch_lines([
"*MyClass*",
"*MyInstance*",
"*MyFunction*test_hello*",
])
def test_unorderable_types(testdir):
testdir.makepyfile("""
class TestJoinEmpty:
pass
def make_test():
class Test:
pass
Test.__name__ = "TestFoo"
return Test
TestFoo = make_test()
""")
result = testdir.runpytest()
assert "TypeError" not in result.stdout.str()
assert result.ret == 0

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,119 @@
import pytest, py, sys
class TestOEJSKITSpecials:
def test_funcarg_non_pycollectobj(self, testdir): # rough jstests usage
testdir.makeconftest("""
import pytest
def pytest_pycollect_makeitem(collector, name, obj):
if name == "MyClass":
return MyCollector(name, parent=collector)
class MyCollector(pytest.Collector):
def reportinfo(self):
return self.fspath, 3, "xyz"
""")
modcol = testdir.getmodulecol("""
def pytest_funcarg__arg1(request):
return 42
class MyClass:
pass
""")
# this hook finds funcarg factories
rep = modcol.ihook.pytest_make_collect_report(collector=modcol)
clscol = rep.result[0]
clscol.obj = lambda arg1: None
clscol.funcargs = {}
pytest._fillfuncargs(clscol)
assert clscol.funcargs['arg1'] == 42
def test_autouse_fixture(self, testdir): # rough jstests usage
testdir.makeconftest("""
import pytest
def pytest_pycollect_makeitem(collector, name, obj):
if name == "MyClass":
return MyCollector(name, parent=collector)
class MyCollector(pytest.Collector):
def reportinfo(self):
return self.fspath, 3, "xyz"
""")
modcol = testdir.getmodulecol("""
import pytest
@pytest.fixture(autouse=True)
def hello():
pass
def pytest_funcarg__arg1(request):
return 42
class MyClass:
pass
""")
# this hook finds funcarg factories
rep = modcol.ihook.pytest_make_collect_report(collector=modcol)
clscol = rep.result[0]
clscol.obj = lambda: None
clscol.funcargs = {}
pytest._fillfuncargs(clscol)
assert not clscol.funcargs
class TestMockDecoration:
def test_wrapped_getfuncargnames(self):
from _pytest.python import getfuncargnames
def wrap(f):
def func():
pass
func.__wrapped__ = f
return func
@wrap
def f(x):
pass
l = getfuncargnames(f)
assert l == ("x",)
def test_wrapped_getfuncargnames_patching(self):
from _pytest.python import getfuncargnames
def wrap(f):
def func():
pass
func.__wrapped__ = f
func.patchings = ["qwe"]
return func
@wrap
def f(x, y, z):
pass
l = getfuncargnames(f)
assert l == ("y", "z")
def test_unittest_mock(self, testdir):
pytest.importorskip("unittest.mock")
testdir.makepyfile("""
import unittest.mock
class T(unittest.TestCase):
@unittest.mock.patch("os.path.abspath")
def test_hello(self, abspath):
import os
os.path.abspath("hello")
abspath.assert_any_call("hello")
""")
reprec = testdir.inline_run()
reprec.assertoutcome(passed=1)
def test_mock(self, testdir):
pytest.importorskip("mock", "1.0.1")
testdir.makepyfile("""
import os
import unittest
import mock
class T(unittest.TestCase):
@mock.patch("os.path.abspath")
def test_hello(self, abspath):
os.path.abspath("hello")
abspath.assert_any_call("hello")
@mock.patch("os.path.abspath")
@mock.patch("os.path.normpath")
def test_someting(normpath, abspath, tmpdir):
abspath.return_value = "this"
os.path.normpath(os.path.abspath("hello"))
normpath.assert_any_call("this")
""")
reprec = testdir.inline_run()
reprec.assertoutcome(passed=2)

575
testing/python/metafunc.py Normal file
View File

@@ -0,0 +1,575 @@
import pytest, py, sys
from _pytest import python as funcargs
from _pytest.python import FixtureLookupError
class TestMetafunc:
def Metafunc(self, func):
# the unit tests of this class check if things work correctly
# on the funcarg level, so we don't need a full blown
# initiliazation
class FixtureInfo:
name2fixturedefs = None
def __init__(self, names):
self.names_closure = names
names = funcargs.getfuncargnames(func)
fixtureinfo = FixtureInfo(names)
return funcargs.Metafunc(func, fixtureinfo, None)
def test_no_funcargs(self, testdir):
def function(): pass
metafunc = self.Metafunc(function)
assert not metafunc.fixturenames
repr(metafunc._calls)
def test_function_basic(self):
def func(arg1, arg2="qwe"): pass
metafunc = self.Metafunc(func)
assert len(metafunc.fixturenames) == 1
assert 'arg1' in metafunc.fixturenames
assert metafunc.function is func
assert metafunc.cls is None
def test_addcall_no_args(self):
def func(arg1): pass
metafunc = self.Metafunc(func)
metafunc.addcall()
assert len(metafunc._calls) == 1
call = metafunc._calls[0]
assert call.id == "0"
assert not hasattr(call, 'param')
def test_addcall_id(self):
def func(arg1): pass
metafunc = self.Metafunc(func)
pytest.raises(ValueError, "metafunc.addcall(id=None)")
metafunc.addcall(id=1)
pytest.raises(ValueError, "metafunc.addcall(id=1)")
pytest.raises(ValueError, "metafunc.addcall(id='1')")
metafunc.addcall(id=2)
assert len(metafunc._calls) == 2
assert metafunc._calls[0].id == "1"
assert metafunc._calls[1].id == "2"
def test_addcall_param(self):
def func(arg1): pass
metafunc = self.Metafunc(func)
class obj: pass
metafunc.addcall(param=obj)
metafunc.addcall(param=obj)
metafunc.addcall(param=1)
assert len(metafunc._calls) == 3
assert metafunc._calls[0].getparam("arg1") == obj
assert metafunc._calls[1].getparam("arg1") == obj
assert metafunc._calls[2].getparam("arg1") == 1
def test_addcall_funcargs(self):
def func(x): pass
metafunc = self.Metafunc(func)
class obj: pass
metafunc.addcall(funcargs={"x": 2})
metafunc.addcall(funcargs={"x": 3})
pytest.raises(pytest.fail.Exception, "metafunc.addcall({'xyz': 0})")
assert len(metafunc._calls) == 2
assert metafunc._calls[0].funcargs == {'x': 2}
assert metafunc._calls[1].funcargs == {'x': 3}
assert not hasattr(metafunc._calls[1], 'param')
def test_parametrize_error(self):
def func(x, y): pass
metafunc = self.Metafunc(func)
metafunc.parametrize("x", [1,2])
pytest.raises(ValueError, lambda: metafunc.parametrize("x", [5,6]))
pytest.raises(ValueError, lambda: metafunc.parametrize("x", [5,6]))
metafunc.parametrize("y", [1,2])
pytest.raises(ValueError, lambda: metafunc.parametrize("y", [5,6]))
pytest.raises(ValueError, lambda: metafunc.parametrize("y", [5,6]))
def test_parametrize_and_id(self):
def func(x, y): pass
metafunc = self.Metafunc(func)
metafunc.parametrize("x", [1,2], ids=['basic', 'advanced'])
metafunc.parametrize("y", ["abc", "def"])
ids = [x.id for x in metafunc._calls]
assert ids == ["basic-abc", "basic-def", "advanced-abc", "advanced-def"]
def test_parametrize_with_userobjects(self):
def func(x, y): pass
metafunc = self.Metafunc(func)
class A:
pass
metafunc.parametrize("x", [A(), A()])
metafunc.parametrize("y", list("ab"))
assert metafunc._calls[0].id == "x0-a"
assert metafunc._calls[1].id == "x0-b"
assert metafunc._calls[2].id == "x1-a"
assert metafunc._calls[3].id == "x1-b"
def test_idmaker_autoname(self):
from _pytest.python import idmaker
result = idmaker(("a", "b"), [("string", 1.0),
("st-ring", 2.0)])
assert result == ["string-1.0", "st-ring-2.0"]
result = idmaker(("a", "b"), [(object(), 1.0),
(object(), object())])
assert result == ["a0-1.0", "a1-b1"]
def test_addcall_and_parametrize(self):
def func(x, y): pass
metafunc = self.Metafunc(func)
metafunc.addcall({'x': 1})
metafunc.parametrize('y', [2,3])
assert len(metafunc._calls) == 2
assert metafunc._calls[0].funcargs == {'x': 1, 'y': 2}
assert metafunc._calls[1].funcargs == {'x': 1, 'y': 3}
assert metafunc._calls[0].id == "0-2"
assert metafunc._calls[1].id == "0-3"
def test_parametrize_indirect(self):
def func(x, y): pass
metafunc = self.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, 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
metafunc = self.Metafunc(func)
metafunc.addcall(param="123")
metafunc.parametrize('x', [1], indirect=True)
metafunc.parametrize('y', [2,3], 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)
def test_parametrize_functional(self, testdir):
testdir.makepyfile("""
def pytest_generate_tests(metafunc):
metafunc.parametrize('x', [1,2], indirect=True)
metafunc.parametrize('y', [2])
def pytest_funcarg__x(request):
return request.param * 10
def pytest_funcarg__y(request):
return request.param
def test_simple(x,y):
assert x in (10,20)
assert y == 2
""")
result = testdir.runpytest("-v")
result.stdout.fnmatch_lines([
"*test_simple*1-2*",
"*test_simple*2-2*",
"*2 passed*",
])
def test_parametrize_onearg(self):
metafunc = self.Metafunc(lambda x: None)
metafunc.parametrize("x", [1,2])
assert len(metafunc._calls) == 2
assert metafunc._calls[0].funcargs == dict(x=1)
assert metafunc._calls[0].id == "1"
assert metafunc._calls[1].funcargs == dict(x=2)
assert metafunc._calls[1].id == "2"
def test_parametrize_onearg_indirect(self):
metafunc = self.Metafunc(lambda x: None)
metafunc.parametrize("x", [1,2], indirect=True)
assert metafunc._calls[0].params == dict(x=1)
assert metafunc._calls[0].id == "1"
assert metafunc._calls[1].params == dict(x=2)
assert metafunc._calls[1].id == "2"
def test_parametrize_twoargs(self):
metafunc = self.Metafunc(lambda x,y: None)
metafunc.parametrize(("x", "y"), [(1,2), (3,4)])
assert len(metafunc._calls) == 2
assert metafunc._calls[0].funcargs == dict(x=1, y=2)
assert metafunc._calls[0].id == "1-2"
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*",
])
def test_parametrize_class_scenarios(self, testdir):
testdir.makepyfile("""
# same as doc/en/example/parametrize scenario example
def pytest_generate_tests(metafunc):
idlist = []
argvalues = []
for scenario in metafunc.cls.scenarios:
idlist.append(scenario[0])
items = scenario[1].items()
argnames = [x[0] for x in items]
argvalues.append(([x[1] for x in items]))
metafunc.parametrize(argnames, argvalues, ids=idlist, scope="class")
class Test(object):
scenarios = [['1', {'arg': {1: 2}, "arg2": "value2"}],
['2', {'arg':'value2', "arg2": "value2"}]]
def test_1(self, arg, arg2):
pass
def test_2(self, arg2, arg):
pass
def test_3(self, arg, arg2):
pass
""")
result = testdir.runpytest("-v")
assert result.ret == 0
result.stdout.fnmatch_lines("""
*test_1*1*
*test_2*1*
*test_3*1*
*test_1*2*
*test_2*2*
*test_3*2*
*6 passed*
""")
class TestMetafuncFunctional:
def test_attributes(self, testdir):
p = testdir.makepyfile("""
# assumes that generate/provide runs in the same process
import py, pytest
def pytest_generate_tests(metafunc):
metafunc.addcall(param=metafunc)
def pytest_funcarg__metafunc(request):
assert request._pyfuncitem._genid == "0"
return request.param
def test_function(metafunc, pytestconfig):
assert metafunc.config == pytestconfig
assert metafunc.module.__name__ == __name__
assert metafunc.function == test_function
assert metafunc.cls is None
class TestClass:
def test_method(self, metafunc, pytestconfig):
assert metafunc.config == pytestconfig
assert metafunc.module.__name__ == __name__
if py.std.sys.version_info > (3, 0):
unbound = TestClass.test_method
else:
unbound = TestClass.test_method.im_func
# XXX actually have an unbound test function here?
assert metafunc.function == unbound
assert metafunc.cls == TestClass
""")
result = testdir.runpytest(p, "-v")
result.stdout.fnmatch_lines([
"*2 passed in*",
])
def test_addcall_with_two_funcargs_generators(self, testdir):
testdir.makeconftest("""
def pytest_generate_tests(metafunc):
assert "arg1" in metafunc.fixturenames
metafunc.addcall(funcargs=dict(arg1=1, arg2=2))
""")
p = testdir.makepyfile("""
def pytest_generate_tests(metafunc):
metafunc.addcall(funcargs=dict(arg1=1, arg2=1))
class TestClass:
def test_myfunc(self, arg1, arg2):
assert arg1 == arg2
""")
result = testdir.runpytest("-v", p)
result.stdout.fnmatch_lines([
"*test_myfunc*0*PASS*",
"*test_myfunc*1*FAIL*",
"*1 failed, 1 passed*"
])
def test_two_functions(self, testdir):
p = testdir.makepyfile("""
def pytest_generate_tests(metafunc):
metafunc.addcall(param=10)
metafunc.addcall(param=20)
def pytest_funcarg__arg1(request):
return request.param
def test_func1(arg1):
assert arg1 == 10
def test_func2(arg1):
assert arg1 in (10, 20)
""")
result = testdir.runpytest("-v", p)
result.stdout.fnmatch_lines([
"*test_func1*0*PASS*",
"*test_func1*1*FAIL*",
"*test_func2*PASS*",
"*1 failed, 3 passed*"
])
def test_noself_in_method(self, testdir):
p = testdir.makepyfile("""
def pytest_generate_tests(metafunc):
assert 'xyz' not in metafunc.fixturenames
class TestHello:
def test_hello(xyz):
pass
""")
result = testdir.runpytest(p)
result.stdout.fnmatch_lines([
"*1 pass*",
])
def test_generate_plugin_and_module(self, testdir):
testdir.makeconftest("""
def pytest_generate_tests(metafunc):
assert "arg1" in metafunc.fixturenames
metafunc.addcall(id="world", param=(2,100))
""")
p = testdir.makepyfile("""
def pytest_generate_tests(metafunc):
metafunc.addcall(param=(1,1), id="hello")
def pytest_funcarg__arg1(request):
return request.param[0]
def pytest_funcarg__arg2(request):
return request.param[1]
class TestClass:
def test_myfunc(self, arg1, arg2):
assert arg1 == arg2
""")
result = testdir.runpytest("-v", p)
result.stdout.fnmatch_lines([
"*test_myfunc*hello*PASS*",
"*test_myfunc*world*FAIL*",
"*1 failed, 1 passed*"
])
def test_generate_tests_in_class(self, testdir):
p = testdir.makepyfile("""
class TestClass:
def pytest_generate_tests(self, metafunc):
metafunc.addcall(funcargs={'hello': 'world'}, id="hello")
def test_myfunc(self, hello):
assert hello == "world"
""")
result = testdir.runpytest("-v", p)
result.stdout.fnmatch_lines([
"*test_myfunc*hello*PASS*",
"*1 passed*"
])
def test_two_functions_not_same_instance(self, testdir):
p = testdir.makepyfile("""
def pytest_generate_tests(metafunc):
metafunc.addcall({'arg1': 10})
metafunc.addcall({'arg1': 20})
class TestClass:
def test_func(self, arg1):
assert not hasattr(self, 'x')
self.x = 1
""")
result = testdir.runpytest("-v", p)
result.stdout.fnmatch_lines([
"*test_func*0*PASS*",
"*test_func*1*PASS*",
"*2 pass*",
])
def test_issue28_setup_method_in_generate_tests(self, testdir):
p = testdir.makepyfile("""
def pytest_generate_tests(metafunc):
metafunc.addcall({'arg1': 1})
class TestClass:
def test_method(self, arg1):
assert arg1 == self.val
def setup_method(self, func):
self.val = 1
""")
result = testdir.runpytest(p)
result.stdout.fnmatch_lines([
"*1 pass*",
])
def test_parametrize_functional2(self, testdir):
testdir.makepyfile("""
def pytest_generate_tests(metafunc):
metafunc.parametrize("arg1", [1,2])
metafunc.parametrize("arg2", [4,5])
def test_hello(arg1, arg2):
assert 0, (arg1, arg2)
""")
result = testdir.runpytest()
result.stdout.fnmatch_lines([
"*(1, 4)*",
"*(1, 5)*",
"*(2, 4)*",
"*(2, 5)*",
"*4 failed*",
])
def test_parametrize_and_inner_getfuncargvalue(self, testdir):
p = testdir.makepyfile("""
def pytest_generate_tests(metafunc):
metafunc.parametrize("arg1", [1], indirect=True)
metafunc.parametrize("arg2", [10], indirect=True)
def pytest_funcarg__arg1(request):
x = request.getfuncargvalue("arg2")
return x + request.param
def pytest_funcarg__arg2(request):
return request.param
def test_func1(arg1, arg2):
assert arg1 == 11
""")
result = testdir.runpytest("-v", p)
result.stdout.fnmatch_lines([
"*test_func1*1*PASS*",
"*1 passed*"
])
def test_parametrize_on_setup_arg(self, testdir):
p = testdir.makepyfile("""
def pytest_generate_tests(metafunc):
assert "arg1" in metafunc.fixturenames
metafunc.parametrize("arg1", [1], indirect=True)
def pytest_funcarg__arg1(request):
return request.param
def pytest_funcarg__arg2(request, arg1):
return 10 * arg1
def test_func(arg2):
assert arg2 == 10
""")
result = testdir.runpytest("-v", p)
result.stdout.fnmatch_lines([
"*test_func*1*PASS*",
"*1 passed*"
])
def test_parametrize_with_ids(self, testdir):
testdir.makepyfile("""
import pytest
def pytest_generate_tests(metafunc):
metafunc.parametrize(("a", "b"), [(1,1), (1,2)],
ids=["basic", "advanced"])
def test_function(a, b):
assert a == b
""")
result = testdir.runpytest("-v")
assert result.ret == 1
result.stdout.fnmatch_lines_random([
"*test_function*basic*PASSED",
"*test_function*advanced*FAILED",
])
def test_parametrize_without_ids(self, testdir):
testdir.makepyfile("""
import pytest
def pytest_generate_tests(metafunc):
metafunc.parametrize(("a", "b"),
[(1,object()), (1.3,object())])
def test_function(a, b):
assert 1
""")
result = testdir.runpytest("-v")
result.stdout.fnmatch_lines("""
*test_function*1-b0*
*test_function*1.3-b1*
""")
@pytest.mark.parametrize(("scope", "length"),
[("module", 2), ("function", 4)])
def test_parametrize_scope_overrides(self, testdir, scope, length):
testdir.makepyfile("""
import pytest
l = []
def pytest_generate_tests(metafunc):
if "arg" in metafunc.funcargnames:
metafunc.parametrize("arg", [1,2], indirect=True,
scope=%r)
def pytest_funcarg__arg(request):
l.append(request.param)
return request.param
def test_hello(arg):
assert arg in (1,2)
def test_world(arg):
assert arg in (1,2)
def test_checklength():
assert len(l) == %d
""" % (scope, length))
reprec = testdir.inline_run()
reprec.assertoutcome(passed=5)
def test_usefixtures_seen_in_generate_tests(self, testdir):
testdir.makepyfile("""
import pytest
def pytest_generate_tests(metafunc):
assert "abc" in metafunc.fixturenames
metafunc.parametrize("abc", [1])
@pytest.mark.usefixtures("abc")
def test_function():
pass
""")
reprec = testdir.inline_run()
reprec.assertoutcome(passed=1)
def test_generate_tests_only_done_in_subdir(self, testdir):
sub1 = testdir.mkpydir("sub1")
sub2 = testdir.mkpydir("sub2")
sub1.join("conftest.py").write(py.code.Source("""
def pytest_generate_tests(metafunc):
assert metafunc.function.__name__ == "test_1"
"""))
sub2.join("conftest.py").write(py.code.Source("""
def pytest_generate_tests(metafunc):
assert metafunc.function.__name__ == "test_2"
"""))
sub1.join("test_in_sub1.py").write("def test_1(): pass")
sub2.join("test_in_sub2.py").write("def test_2(): pass")
result = testdir.runpytest("-v", "-s", sub1, sub2, sub1)
result.stdout.fnmatch_lines([
"*3 passed*"
])

64
testing/python/raises.py Normal file
View File

@@ -0,0 +1,64 @@
import pytest
class TestRaises:
def test_raises(self):
source = "int('qwe')"
excinfo = pytest.raises(ValueError, source)
code = excinfo.traceback[-1].frame.code
s = str(code.fullsource)
assert s == source
def test_raises_exec(self):
pytest.raises(ValueError, "a,x = []")
def test_raises_syntax_error(self):
pytest.raises(SyntaxError, "qwe qwe qwe")
def test_raises_function(self):
pytest.raises(ValueError, int, 'hello')
def test_raises_callable_no_exception(self):
class A:
def __call__(self):
pass
try:
pytest.raises(ValueError, A())
except pytest.raises.Exception:
pass
def test_raises_flip_builtin_AssertionError(self):
# we replace AssertionError on python level
# however c code might still raise the builtin one
from _pytest.assertion.util import BuiltinAssertionError
pytest.raises(AssertionError,"""
raise BuiltinAssertionError
""")
@pytest.mark.skipif('sys.version < "2.5"')
def test_raises_as_contextmanager(self, testdir):
testdir.makepyfile("""
from __future__ import with_statement
import py, pytest
def test_simple():
with pytest.raises(ZeroDivisionError) as excinfo:
assert isinstance(excinfo, py.code.ExceptionInfo)
1/0
print (excinfo)
assert excinfo.type == ZeroDivisionError
def test_noraise():
with pytest.raises(pytest.raises.Exception):
with pytest.raises(ValueError):
int()
def test_raise_wrong_exception_passes_by():
with pytest.raises(ZeroDivisionError):
with pytest.raises(ValueError):
1/0
""")
result = testdir.runpytest()
result.stdout.fnmatch_lines([
'*3 passed*',
])

View File

@@ -354,18 +354,21 @@ def test_no_bytecode():
@pytest.mark.skipif('"__pypy__" in sys.modules')
def test_pyc_vs_pyo(self, testdir, monkeypatch):
testdir.makepyfile("""
import pytest
def test_optimized():
"hello"
assert test_optimized.__doc__ is None""")
import pytest
def test_optimized():
"hello"
assert test_optimized.__doc__ is None"""
)
p = py.path.local.make_numbered_dir(prefix="runpytest-", keep=None,
rootdir=testdir.tmpdir)
tmp = "--basetemp=%s" % p
monkeypatch.setenv("PYTHONOPTIMIZE", "2")
monkeypatch.delenv("PYTHONDONTWRITEBYTECODE", raising=False)
assert testdir.runpybin("py.test", tmp).ret == 0
tagged = "test_pyc_vs_pyo." + PYTEST_TAG
assert tagged + ".pyo" in os.listdir("__pycache__")
monkeypatch.undo()
monkeypatch.delenv("PYTHONDONTWRITEBYTECODE", raising=False)
assert testdir.runpybin("py.test", tmp).ret == 1
assert tagged + ".pyc" in os.listdir("__pycache__")

View File

@@ -103,6 +103,16 @@ class TestConfigAPI:
assert config.getvalue("x", o) == 1
pytest.raises(KeyError, 'config.getvalue("y", o)')
def test_config_getoption(self, testdir):
testdir.makeconftest("""
def pytest_addoption(parser):
parser.addoption("--hello", "-X", dest="hello")
""")
config = testdir.parseconfig("--hello=this")
for x in ("hello", "--hello", "-X"):
assert config.getoption(x) == "this"
pytest.raises(ValueError, "config.getoption('qweqwe')")
def test_config_getvalueorskip(self, testdir):
config = testdir.parseconfig()
pytest.raises(pytest.skip.Exception,
@@ -304,3 +314,4 @@ def test_cmdline_processargs_simple(testdir):
"*pytest*",
"*-h*",
])

View File

@@ -237,6 +237,25 @@ class TestFunctional:
assert l[1].args == ()
assert l[2].args == ("pos1", )
@pytest.mark.xfail(reason='unfixed')
def test_merging_markers_deep(self, testdir):
# issue 199 - propagate markers into nested classes
p = testdir.makepyfile("""
import pytest
class TestA:
pytestmark = pytest.mark.a
def test_b(self):
assert True
class TestC:
# this one didnt get marked
def test_d(self):
assert True
""")
items, rec = testdir.inline_genitems(p)
for item in items:
print (item, item.keywords)
assert 'a' in item.keywords
def test_mark_with_wrong_marker(self, testdir):
reprec = testdir.inline_runsource("""
import pytest

View File

@@ -35,6 +35,12 @@ def test_setup_func_with_setup_decorator():
assert not l
def test_setup_func_not_callable():
from _pytest.nose import call_optional
class A:
f = 1
call_optional(A(), "f")
def test_nose_setup_func(testdir):
p = testdir.makepyfile("""
from nose.tools import with_setup
@@ -85,7 +91,7 @@ def test_nose_setup_func_failure(testdir):
""")
result = testdir.runpytest(p, '-p', 'nose')
result.stdout.fnmatch_lines([
"*TypeError: <lambda>() takes exactly 1*0 given*"
"*TypeError: <lambda>()*"
])
@@ -97,21 +103,13 @@ def test_nose_setup_func_failure_2(testdir):
my_teardown = 2
def test_hello():
print (l)
assert l == [1]
def test_world():
print (l)
assert l == [1,2]
assert l == []
test_hello.setup = my_setup
test_hello.teardown = my_teardown
""")
result = testdir.runpytest(p, '-p', 'nose')
result.stdout.fnmatch_lines([
"*TypeError: 'int' object is not callable*"
])
reprec = testdir.inline_run()
reprec.assertoutcome(passed=1)
def test_nose_setup_partial(testdir):
py.test.importorskip("functools")

View File

@@ -18,12 +18,21 @@ def test_runTest_method(testdir):
testpath=testdir.makepyfile("""
import unittest
pytest_plugins = "pytest_unittest"
class MyTestCase(unittest.TestCase):
class MyTestCaseWithRunTest(unittest.TestCase):
def runTest(self):
self.assertEquals('foo', 'foo')
class MyTestCaseWithoutRunTest(unittest.TestCase):
def runTest(self):
self.assertEquals('foo', 'foo')
def test_something(self):
pass
""")
reprec = testdir.inline_run(testpath)
assert reprec.matchreport('runTest').passed
result = testdir.runpytest("-v")
result.stdout.fnmatch_lines("""
*MyTestCaseWithRunTest.runTest*
*MyTestCaseWithoutRunTest.test_something*
*2 passed*
""")
def test_isclasscheck_issue53(testdir):
testpath = testdir.makepyfile("""
@@ -87,6 +96,25 @@ def test_teardown(testdir):
assert passed == 2
assert passed + skipped + failed == 2
@pytest.mark.skipif("sys.version_info < (3,1)")
def test_unittest_skip_issue148(testdir):
testpath = testdir.makepyfile("""
import unittest
@unittest.skip("hello")
class MyTestCase(unittest.TestCase):
@classmethod
def setUpClass(self):
xxx
def test_one(self):
pass
@classmethod
def tearDownClass(self):
xxx
""")
reprec = testdir.inline_run(testpath)
reprec.assertoutcome(skipped=1)
def test_method_and_teardown_failing_reporting(testdir):
testdir.makepyfile("""
import unittest, pytest
@@ -268,7 +296,27 @@ def test_testfunction_skip_property(testdir):
class TestTrialUnittest:
def setup_class(cls):
pytest.importorskip("twisted.trial.unittest")
cls.ut = pytest.importorskip("twisted.trial.unittest")
def test_trial_testcase_runtest_not_collected(self, testdir):
testdir.makepyfile("""
from twisted.trial.unittest import TestCase
class TC(TestCase):
def test_hello(self):
pass
""")
reprec = testdir.inline_run()
reprec.assertoutcome(passed=1)
testdir.makepyfile("""
from twisted.trial.unittest import TestCase
class TC(TestCase):
def runTest(self):
pass
""")
reprec = testdir.inline_run()
reprec.assertoutcome(passed=1)
def test_trial_exceptions_with_skips(self, testdir):
testdir.makepyfile("""
@@ -313,7 +361,7 @@ class TestTrialUnittest:
"*i2wanto*",
"*sys.version_info*",
"*skip_in_method*",
"*5 skipped*3 xfail*1 xpass*",
"*4 skipped*3 xfail*1 xpass*",
])
def test_trial_error(self, testdir):

23
tox.ini
View File

@@ -1,10 +1,10 @@
[tox]
distshare={homedir}/.tox/distshare
envlist=py26,py27,py31,py32,py33,py27-xdist,py25,trial
envlist=py24,py26,py27,py27-nobyte,py31,py32,py33,py27-xdist,py25,trial
indexserver=
pypi = http://pypi.python.org/simple
testrun = http://pypi.testrun.org
default = http://pypi.testrun.org
#default = http://pypi.testrun.org
[testenv]
changedir=testing
@@ -16,22 +16,32 @@ deps=
[testenv:genscript]
changedir=.
commands= py.test --genscript=pytest1
deps=py>=1.4.0
[testenv:py27-xdist]
changedir=.
basepython=python2.7
deps=pytest-xdist
:pypi:mock
:pypi:nose
commands=
py.test -n3 -rfsxX \
--ignore .tox --junitxml={envlogdir}/junit-{envname}.xml testing
--junitxml={envlogdir}/junit-{envname}.xml testing
[testenv:py27-nobyte]
changedir=.
basepython=python2.7
deps=pytest-xdist
setenv=
PYTHONDONTWRITEBYTECODE=1
commands=
py.test -n3 -rfsxX \
--junitxml={envlogdir}/junit-{envname}.xml []
[testenv:trial]
changedir=.
basepython=python2.6
deps=:pypi:twisted
:pypi:pexpect
py>=1.4.5.dev1
commands=
py.test -rsxf testing/test_unittest.py \
--junitxml={envlogdir}/junit-{envname}.xml {posargs:testing/test_unittest.py}
@@ -74,6 +84,7 @@ deps=py>=1.4.0
[testenv:py33]
deps=py>=1.4.0
:pypi:nose
[testenv:jython]
changedir=testing
@@ -87,7 +98,7 @@ plugins=pytester
#--pyargs --doctest-modules --ignore=.tox
addopts= -rxs
rsyncdirs=tox.ini pytest.py _pytest testing
python_files=test_*.py *_test.py
python_files=test_*.py *_test.py testing/*/*.py
python_classes=Test Acceptance
python_functions=test
pep8ignore = E401 E225 E261 E128 E124 E302