* introduce and document new pytest_namespace hook
* remove py.test.mark helper * move xfail to work directly on py.test namespace, simplified --HG-- branch : trunk
This commit is contained in:
parent
bcb30d1c7a
commit
4a48a50e3b
11
CHANGELOG
11
CHANGELOG
|
@ -7,10 +7,15 @@ Changes between 1.0.0b1 and 1.0.0b2
|
||||||
hooks directly in conftest.py or global pytest_*.py
|
hooks directly in conftest.py or global pytest_*.py
|
||||||
files.
|
files.
|
||||||
|
|
||||||
* documented and refined various hooks
|
* added new pytest_namespace(config) hook that allows
|
||||||
|
to inject helpers directly to the py.test.* namespace.
|
||||||
|
|
||||||
* added new style of generative tests via pytest_generate_tests
|
* documented and refined many hooks
|
||||||
hook
|
|
||||||
|
* added new style of generative tests via
|
||||||
|
pytest_generate_tests hook that integrates
|
||||||
|
well with function arguments.
|
||||||
|
|
||||||
|
|
||||||
Changes between 0.9.2 and 1.0.0b1
|
Changes between 0.9.2 and 1.0.0b1
|
||||||
=============================================
|
=============================================
|
||||||
|
|
|
@ -8,11 +8,14 @@ py.test implements much of its functionality by calling `well specified
|
||||||
hooks`_. Python modules which contain such hook functions are called
|
hooks`_. Python modules which contain such hook functions are called
|
||||||
plugins. Hook functions are discovered in ``conftest.py`` files or
|
plugins. Hook functions are discovered in ``conftest.py`` files or
|
||||||
in **named** plugins. ``conftest.py`` files are sometimes called "anonymous"
|
in **named** plugins. ``conftest.py`` files are sometimes called "anonymous"
|
||||||
or "local" plugins if they define hooks. Named plugins are python modules
|
or "local" plugins if they contain hooks. They allow to write and distribute
|
||||||
or packages that have an all lowercase ``pytest_`` prefixed name and who
|
some extensions along with the test suite or the application package easily.
|
||||||
are imported during tool startup or the testing process.
|
Named plugins are python modules or packages that have an all lowercase
|
||||||
|
``pytest_`` prefixed name and who are imported during tool startup or
|
||||||
|
the testing process.
|
||||||
|
|
||||||
.. _`tool startup`:
|
.. _`tool startup`:
|
||||||
|
.. _`test tool starts up`:
|
||||||
|
|
||||||
Plugin discovery at tool startup
|
Plugin discovery at tool startup
|
||||||
--------------------------------------------
|
--------------------------------------------
|
||||||
|
@ -92,6 +95,53 @@ and minimizes version incompatibilites.
|
||||||
|
|
||||||
.. _`original definition of the hook`: http://bitbucket.org/hpk42/py-trunk/src/tip/py/test/plugin/hookspec.py
|
.. _`original definition of the hook`: http://bitbucket.org/hpk42/py-trunk/src/tip/py/test/plugin/hookspec.py
|
||||||
|
|
||||||
|
.. _`configuration hooks`:
|
||||||
|
|
||||||
|
command line parsing and configuration hooks
|
||||||
|
--------------------------------------------------------------------
|
||||||
|
|
||||||
|
When the `test tool starts up`_ it will invoke all hooks that add
|
||||||
|
command line options in the python standard optparse style.
|
||||||
|
|
||||||
|
.. sourcecode:: python
|
||||||
|
|
||||||
|
def pytest_addoption(parser):
|
||||||
|
""" add command line options. """"
|
||||||
|
parser.addoption("--myopt", dest="myopt", action="store_true")
|
||||||
|
|
||||||
|
After all these hooks have been called, the command line is parser
|
||||||
|
and a ``config`` object is created and another hook is invoked,
|
||||||
|
for example:
|
||||||
|
|
||||||
|
.. sourcecode:: python
|
||||||
|
|
||||||
|
def pytest_configure(config):
|
||||||
|
config.getvalue("myopt")
|
||||||
|
|
||||||
|
When the test run finishes this corresponding finalizer hook is called:
|
||||||
|
|
||||||
|
def pytest_unconfigure(config):
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
adding global py.test helpers and functionality
|
||||||
|
--------------------------------------------------------------------
|
||||||
|
|
||||||
|
If you want to make global helper functions or objects available
|
||||||
|
to your test code you can implement:
|
||||||
|
|
||||||
|
def pytest_namespace(config):
|
||||||
|
""" return dictionary with items to be made available on py.test. """
|
||||||
|
|
||||||
|
All such returned items will be made available directly on
|
||||||
|
the ``py.test`` namespace.
|
||||||
|
|
||||||
|
If you want to provide helpers that are specific to a test function run or need
|
||||||
|
to be setup per test function run, please refer to the `funcargs mechanism`_.
|
||||||
|
|
||||||
|
.. _`funcargs mechanism`: funcargs.html
|
||||||
|
|
||||||
|
|
||||||
generic "runtest" hooks
|
generic "runtest" hooks
|
||||||
------------------------------
|
------------------------------
|
||||||
|
|
||||||
|
@ -179,7 +229,7 @@ the parent node and may be used to access command line
|
||||||
options via the ``parent.config`` object.
|
options via the ``parent.config`` object.
|
||||||
|
|
||||||
|
|
||||||
Python specific test function and module hooks
|
Python test function and module hooks
|
||||||
----------------------------------------------------
|
----------------------------------------------------
|
||||||
|
|
||||||
For influencing the collection of objects in Python modules
|
For influencing the collection of objects in Python modules
|
||||||
|
@ -187,12 +237,11 @@ you can use the following hook:
|
||||||
|
|
||||||
.. sourcecode:: python
|
.. sourcecode:: python
|
||||||
|
|
||||||
pytest_pycollect_makeitem(collector, name, obj)
|
def pytest_pycollect_makeitem(collector, name, obj):
|
||||||
|
""" return custom item/collector for a python object in a module, or None. """
|
||||||
|
|
||||||
This hook will be called for each Python object in a collected
|
This hook will be called for each Python object in a collected
|
||||||
Python module. The return value is a custom `collection node`_.
|
Python module. The return value is a custom `collection node`_ or None.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.. XXX or ``False`` if you want to indicate that the given item should not be collected.
|
.. XXX or ``False`` if you want to indicate that the given item should not be collected.
|
||||||
|
|
||||||
|
|
|
@ -66,13 +66,11 @@ initpkg(__name__,
|
||||||
'test.__doc__' : ('./test/__init__.py', '__doc__'),
|
'test.__doc__' : ('./test/__init__.py', '__doc__'),
|
||||||
'test._PluginManager' : ('./test/pluginmanager.py', 'PluginManager'),
|
'test._PluginManager' : ('./test/pluginmanager.py', 'PluginManager'),
|
||||||
'test.raises' : ('./test/outcome.py', 'raises'),
|
'test.raises' : ('./test/outcome.py', 'raises'),
|
||||||
'test.mark' : ('./test/outcome.py', 'mark',),
|
|
||||||
'test.deprecated_call' : ('./test/outcome.py', 'deprecated_call'),
|
'test.deprecated_call' : ('./test/outcome.py', 'deprecated_call'),
|
||||||
'test.skip' : ('./test/outcome.py', 'skip'),
|
'test.skip' : ('./test/outcome.py', 'skip'),
|
||||||
'test.importorskip' : ('./test/outcome.py', 'importorskip'),
|
'test.importorskip' : ('./test/outcome.py', 'importorskip'),
|
||||||
'test.fail' : ('./test/outcome.py', 'fail'),
|
'test.fail' : ('./test/outcome.py', 'fail'),
|
||||||
'test.exit' : ('./test/outcome.py', 'exit'),
|
'test.exit' : ('./test/outcome.py', 'exit'),
|
||||||
'test.pdb' : ('./test/custompdb.py', 'set_trace'),
|
|
||||||
|
|
||||||
# configuration/initialization related test api
|
# configuration/initialization related test api
|
||||||
'test.config' : ('./test/config.py', 'config_per_process'),
|
'test.config' : ('./test/config.py', 'config_per_process'),
|
||||||
|
|
|
@ -543,7 +543,7 @@ class TestPopenGateway(PopenGatewayTestSetup, BasicRemoteExecution):
|
||||||
ret = channel.receive()
|
ret = channel.receive()
|
||||||
assert ret == 42
|
assert ret == 42
|
||||||
|
|
||||||
@py.test.mark.xfail("fix needed: dying remote process does not cause waitclose() to fail")
|
@py.test.xfail # "fix needed: dying remote process does not cause waitclose() to fail"
|
||||||
def test_waitclose_on_remote_killed(self):
|
def test_waitclose_on_remote_killed(self):
|
||||||
gw = py.execnet.PopenGateway()
|
gw = py.execnet.PopenGateway()
|
||||||
channel = gw.remote_exec("""
|
channel = gw.remote_exec("""
|
||||||
|
@ -616,12 +616,12 @@ class TestSshGateway(BasicRemoteExecution):
|
||||||
def test_sshaddress(self):
|
def test_sshaddress(self):
|
||||||
assert self.gw.remoteaddress == self.sshhost
|
assert self.gw.remoteaddress == self.sshhost
|
||||||
|
|
||||||
@py.test.mark.xfail("XXX ssh-gateway error handling")
|
@py.test.xfail # XXX ssh-gateway error handling
|
||||||
def test_connexion_failes_on_non_existing_hosts(self):
|
def test_connexion_failes_on_non_existing_hosts(self):
|
||||||
py.test.raises(IOError,
|
py.test.raises(IOError,
|
||||||
"py.execnet.SshGateway('nowhere.codespeak.net')")
|
"py.execnet.SshGateway('nowhere.codespeak.net')")
|
||||||
|
|
||||||
@py.test.mark.xfail("XXX ssh-gateway error handling")
|
@py.test.xfail # "XXX ssh-gateway error handling"
|
||||||
def test_deprecated_identity(self):
|
def test_deprecated_identity(self):
|
||||||
py.test.deprecated_call(
|
py.test.deprecated_call(
|
||||||
py.test.raises, IOError,
|
py.test.raises, IOError,
|
||||||
|
|
|
@ -367,7 +367,7 @@ class TestDSession:
|
||||||
assert node.gateway.spec.popen
|
assert node.gateway.spec.popen
|
||||||
#XXX eq.geteventargs("pytest_sessionfinish")
|
#XXX eq.geteventargs("pytest_sessionfinish")
|
||||||
|
|
||||||
@py.test.mark.xfail("test implementation missing")
|
@py.test.xfail
|
||||||
def test_collected_function_causes_remote_skip_at_module_level(self, testdir):
|
def test_collected_function_causes_remote_skip_at_module_level(self, testdir):
|
||||||
p = testdir.makepyfile("""
|
p = testdir.makepyfile("""
|
||||||
import py
|
import py
|
||||||
|
|
|
@ -11,7 +11,7 @@ class pytest_funcarg__mysetup:
|
||||||
request.getfuncargvalue("_pytest")
|
request.getfuncargvalue("_pytest")
|
||||||
|
|
||||||
class TestNodeManager:
|
class TestNodeManager:
|
||||||
@py.test.mark.xfail("consider / forbid implicit rsyncdirs?")
|
@py.test.xfail
|
||||||
def test_rsync_roots_no_roots(self, mysetup):
|
def test_rsync_roots_no_roots(self, mysetup):
|
||||||
mysetup.source.ensure("dir1", "file1").write("hello")
|
mysetup.source.ensure("dir1", "file1").write("hello")
|
||||||
config = py.test.config._reparse([source])
|
config = py.test.config._reparse([source])
|
||||||
|
|
|
@ -139,36 +139,6 @@ def deprecated_call(func, *args, **kwargs):
|
||||||
raise AssertionError("%r did not produce DeprecationWarning" %(func,))
|
raise AssertionError("%r did not produce DeprecationWarning" %(func,))
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
class KeywordDecorator:
|
|
||||||
""" decorator for setting function attributes. """
|
|
||||||
def __init__(self, keywords, lastname=None):
|
|
||||||
self._keywords = keywords
|
|
||||||
self._lastname = lastname
|
|
||||||
|
|
||||||
def __call__(self, func=None, **kwargs):
|
|
||||||
if func is None:
|
|
||||||
kw = self._keywords.copy()
|
|
||||||
kw.update(kwargs)
|
|
||||||
return KeywordDecorator(kw)
|
|
||||||
elif not hasattr(func, 'func_dict'):
|
|
||||||
kw = self._keywords.copy()
|
|
||||||
name = self._lastname
|
|
||||||
if name is None:
|
|
||||||
name = "mark"
|
|
||||||
kw[name] = func
|
|
||||||
return KeywordDecorator(kw)
|
|
||||||
func.func_dict.update(self._keywords)
|
|
||||||
return func
|
|
||||||
|
|
||||||
def __getattr__(self, name):
|
|
||||||
if name[0] == "_":
|
|
||||||
raise AttributeError(name)
|
|
||||||
kw = self._keywords.copy()
|
|
||||||
kw[name] = True
|
|
||||||
return self.__class__(kw, lastname=name)
|
|
||||||
|
|
||||||
mark = KeywordDecorator({})
|
|
||||||
|
|
||||||
# exitcodes for the command line
|
# exitcodes for the command line
|
||||||
EXIT_OK = 0
|
EXIT_OK = 0
|
||||||
EXIT_TESTSFAILED = 1
|
EXIT_TESTSFAILED = 1
|
||||||
|
|
|
@ -14,6 +14,10 @@ def pytest_configure(config):
|
||||||
``config`` provides access to all such configuration values.
|
``config`` provides access to all such configuration values.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
def pytest_namespace(config):
|
||||||
|
""" return dict of name->object to become available at py.test.*"""
|
||||||
|
|
||||||
|
|
||||||
def pytest_unconfigure(config):
|
def pytest_unconfigure(config):
|
||||||
""" called before test process is exited. """
|
""" called before test process is exited. """
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,8 @@ cleanup gateways that were instantiated during a test function run.
|
||||||
"""
|
"""
|
||||||
import py
|
import py
|
||||||
|
|
||||||
|
pytest_plugins = "xfail"
|
||||||
|
|
||||||
def pytest_configure(config):
|
def pytest_configure(config):
|
||||||
config.pluginmanager.register(Execnetcleanup())
|
config.pluginmanager.register(Execnetcleanup())
|
||||||
|
|
||||||
|
@ -37,18 +39,16 @@ class Execnetcleanup:
|
||||||
while len(self._gateways) > len(gateways):
|
while len(self._gateways) > len(gateways):
|
||||||
self._gateways[-1].exit()
|
self._gateways[-1].exit()
|
||||||
return res
|
return res
|
||||||
|
|
||||||
@py.test.mark.xfail("clarify plugin registration/unregistration")
|
|
||||||
def test_execnetplugin(testdir):
|
def test_execnetplugin(testdir):
|
||||||
p = ExecnetcleanupPlugin()
|
reprec = testdir.inline_runsource("""
|
||||||
testdir.plugins.append(p)
|
|
||||||
testdir.inline_runsource("""
|
|
||||||
import py
|
import py
|
||||||
import sys
|
import sys
|
||||||
def test_hello():
|
def test_hello():
|
||||||
sys._gw = py.execnet.PopenGateway()
|
sys._gw = py.execnet.PopenGateway()
|
||||||
|
def test_world():
|
||||||
|
assert hasattr(sys, '_gw')
|
||||||
|
py.test.raises(KeyError, "sys._gw.exit()") # already closed
|
||||||
|
|
||||||
""", "-s", "--debug")
|
""", "-s", "--debug")
|
||||||
assert not p._gateways
|
reprec.assertoutcome(passed=2)
|
||||||
assert py.std.sys._gw
|
|
||||||
py.test.raises(KeyError, "py.std.sys._gw.exit()") # already closed
|
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ mark tests as expected-to-fail and report them separately.
|
||||||
|
|
||||||
example:
|
example:
|
||||||
|
|
||||||
@py.test.mark.xfail("needs refactoring")
|
@py.test.xfail
|
||||||
def test_hello():
|
def test_hello():
|
||||||
...
|
...
|
||||||
assert 0
|
assert 0
|
||||||
|
@ -52,29 +52,34 @@ def pytest_terminal_summary(terminalreporter):
|
||||||
for event in xpassed:
|
for event in xpassed:
|
||||||
tr._tw.line("%s: xpassed" %(event.item,))
|
tr._tw.line("%s: xpassed" %(event.item,))
|
||||||
|
|
||||||
|
def xfail_decorator(func):
|
||||||
|
func.xfail = True
|
||||||
|
return func
|
||||||
|
|
||||||
|
def pytest_namespace(config):
|
||||||
|
return dict(xfail=xfail_decorator)
|
||||||
|
|
||||||
# ===============================================================================
|
# ===============================================================================
|
||||||
#
|
#
|
||||||
# plugin tests
|
# plugin tests
|
||||||
#
|
#
|
||||||
# ===============================================================================
|
# ===============================================================================
|
||||||
|
|
||||||
|
|
||||||
def test_xfail(testdir, linecomp):
|
def test_xfail(testdir, linecomp):
|
||||||
p = testdir.makepyfile(test_one="""
|
p = testdir.makepyfile(test_one="""
|
||||||
import py
|
import py
|
||||||
pytest_plugins="pytest_xfail",
|
@py.test.xfail
|
||||||
@py.test.mark.xfail
|
|
||||||
def test_this():
|
def test_this():
|
||||||
assert 0
|
assert 0
|
||||||
|
|
||||||
@py.test.mark.xfail
|
@py.test.xfail
|
||||||
def test_that():
|
def test_that():
|
||||||
assert 1
|
assert 1
|
||||||
""")
|
""")
|
||||||
result = testdir.runpytest(p)
|
result = testdir.runpytest(p)
|
||||||
extra = result.stdout.fnmatch_lines([
|
extra = result.stdout.fnmatch_lines([
|
||||||
"*expected failures*",
|
"*expected failures*",
|
||||||
"*test_one.test_this*test_one.py:5*",
|
"*test_one.test_this*test_one.py:4*",
|
||||||
"*UNEXPECTEDLY PASSING*",
|
"*UNEXPECTEDLY PASSING*",
|
||||||
"*test_that*",
|
"*test_that*",
|
||||||
])
|
])
|
||||||
|
|
|
@ -29,16 +29,6 @@ class TestSetupState:
|
||||||
|
|
||||||
|
|
||||||
class BaseFunctionalTests:
|
class BaseFunctionalTests:
|
||||||
def test_funcattr(self, testdir):
|
|
||||||
reports = testdir.runitem("""
|
|
||||||
import py
|
|
||||||
@py.test.mark(xfail="needs refactoring")
|
|
||||||
def test_func():
|
|
||||||
raise Exit()
|
|
||||||
""")
|
|
||||||
rep = reports[1]
|
|
||||||
assert rep.keywords['xfail'] == "needs refactoring"
|
|
||||||
|
|
||||||
def test_passfunction(self, testdir):
|
def test_passfunction(self, testdir):
|
||||||
reports = testdir.runitem("""
|
reports = testdir.runitem("""
|
||||||
def test_func():
|
def test_func():
|
||||||
|
|
|
@ -162,16 +162,25 @@ class PluginManager(object):
|
||||||
if hasattr(self, '_config'):
|
if hasattr(self, '_config'):
|
||||||
self.call_plugin(plugin, "pytest_addoption", parser=self._config._parser)
|
self.call_plugin(plugin, "pytest_addoption", parser=self._config._parser)
|
||||||
self.call_plugin(plugin, "pytest_configure", config=self._config)
|
self.call_plugin(plugin, "pytest_configure", config=self._config)
|
||||||
|
#dic = self.call_plugin(plugin, "pytest_namespace", config=self._config)
|
||||||
|
#self._updateext(dic)
|
||||||
|
|
||||||
def call_plugin(self, plugin, methname, **kwargs):
|
def call_plugin(self, plugin, methname, **kwargs):
|
||||||
return self.MultiCall(self.listattr(methname, plugins=[plugin]),
|
return self.MultiCall(self.listattr(methname, plugins=[plugin]),
|
||||||
**kwargs).execute(firstresult=True)
|
**kwargs).execute(firstresult=True)
|
||||||
|
|
||||||
|
def _updateext(self, dic):
|
||||||
|
if dic:
|
||||||
|
for name, value in dic.items():
|
||||||
|
setattr(py.test, name, value)
|
||||||
|
|
||||||
def do_configure(self, config):
|
def do_configure(self, config):
|
||||||
assert not hasattr(self, '_config')
|
assert not hasattr(self, '_config')
|
||||||
config.pluginmanager.register(self)
|
config.pluginmanager.register(self)
|
||||||
self._config = config
|
self._config = config
|
||||||
config.hook.pytest_configure(config=self._config)
|
config.hook.pytest_configure(config=self._config)
|
||||||
|
for dic in config.hook.pytest_namespace(config=config) or []:
|
||||||
|
self._updateext(dic)
|
||||||
|
|
||||||
def do_unconfigure(self, config):
|
def do_unconfigure(self, config):
|
||||||
config = self._config
|
config = self._config
|
||||||
|
@ -179,6 +188,9 @@ class PluginManager(object):
|
||||||
config.hook.pytest_unconfigure(config=config)
|
config.hook.pytest_unconfigure(config=config)
|
||||||
config.pluginmanager.unregister(self)
|
config.pluginmanager.unregister(self)
|
||||||
|
|
||||||
|
class Ext:
|
||||||
|
""" namespace for extension objects. """
|
||||||
|
|
||||||
#
|
#
|
||||||
# XXX old code to automatically load classes
|
# XXX old code to automatically load classes
|
||||||
#
|
#
|
||||||
|
|
|
@ -91,6 +91,7 @@ class TestConfigTmpdir:
|
||||||
assert config2.basetemp != config3.basetemp
|
assert config2.basetemp != config3.basetemp
|
||||||
|
|
||||||
class TestConfigAPI:
|
class TestConfigAPI:
|
||||||
|
|
||||||
def test_config_getvalue_honours_conftest(self, testdir):
|
def test_config_getvalue_honours_conftest(self, testdir):
|
||||||
testdir.makepyfile(conftest="x=1")
|
testdir.makepyfile(conftest="x=1")
|
||||||
testdir.mkdir("sub").join("conftest.py").write("x=2 ; y = 3")
|
testdir.mkdir("sub").join("conftest.py").write("x=2 ; y = 3")
|
||||||
|
@ -320,8 +321,8 @@ def test_options_on_small_file_do_not_blow_up(testdir):
|
||||||
def test_default_registry():
|
def test_default_registry():
|
||||||
assert py.test.config.pluginmanager.comregistry is py._com.comregistry
|
assert py.test.config.pluginmanager.comregistry is py._com.comregistry
|
||||||
|
|
||||||
@py.test.mark.todo("test for deprecation")
|
|
||||||
def test_ensuretemp():
|
def test_ensuretemp():
|
||||||
|
# XXX test for deprecation
|
||||||
d1 = py.test.ensuretemp('hello')
|
d1 = py.test.ensuretemp('hello')
|
||||||
d2 = py.test.ensuretemp('hello')
|
d2 = py.test.ensuretemp('hello')
|
||||||
assert d1 == d2
|
assert d1 == d2
|
||||||
|
|
|
@ -200,18 +200,6 @@ class TestRequest:
|
||||||
req = funcargs.FuncargRequest(item)
|
req = funcargs.FuncargRequest(item)
|
||||||
assert req.fspath == modcol.fspath
|
assert req.fspath == modcol.fspath
|
||||||
|
|
||||||
class TestRequestProtocol:
|
|
||||||
@py.test.mark.xfail
|
|
||||||
def test_protocol(self, testdir):
|
|
||||||
item = testdir.getitem("""
|
|
||||||
def pytest_funcarg_arg1(request): return 1
|
|
||||||
def pytest_funcarg_arg2(request): return 2
|
|
||||||
def test_func(arg1, arg2): pass
|
|
||||||
""")
|
|
||||||
req = funcargs.FuncargRequest(item)
|
|
||||||
req._fillargs()
|
|
||||||
#assert item.funcreq.
|
|
||||||
|
|
||||||
|
|
||||||
class TestRequestCachedSetup:
|
class TestRequestCachedSetup:
|
||||||
def test_request_cachedsetup(self, testdir):
|
def test_request_cachedsetup(self, testdir):
|
||||||
|
|
|
@ -83,34 +83,3 @@ def test_pytest_exit():
|
||||||
excinfo = py.code.ExceptionInfo()
|
excinfo = py.code.ExceptionInfo()
|
||||||
assert excinfo.errisinstance(KeyboardInterrupt)
|
assert excinfo.errisinstance(KeyboardInterrupt)
|
||||||
|
|
||||||
def test_pytest_mark_getattr():
|
|
||||||
from py.__.test.outcome import mark
|
|
||||||
def f(): pass
|
|
||||||
|
|
||||||
mark.hello(f)
|
|
||||||
assert f.hello == True
|
|
||||||
|
|
||||||
mark.hello("test")(f)
|
|
||||||
assert f.hello == "test"
|
|
||||||
|
|
||||||
py.test.raises(AttributeError, "mark._hello")
|
|
||||||
py.test.raises(AttributeError, "mark.__str__")
|
|
||||||
|
|
||||||
def test_pytest_mark_call():
|
|
||||||
from py.__.test.outcome import mark
|
|
||||||
def f(): pass
|
|
||||||
mark(x=3)(f)
|
|
||||||
assert f.x == 3
|
|
||||||
def g(): pass
|
|
||||||
mark(g)
|
|
||||||
assert not g.func_dict
|
|
||||||
|
|
||||||
mark.hello(f)
|
|
||||||
assert f.hello == True
|
|
||||||
|
|
||||||
mark.hello("test")(f)
|
|
||||||
assert f.hello == "test"
|
|
||||||
|
|
||||||
mark("x1")(f)
|
|
||||||
assert f.mark == "x1"
|
|
||||||
|
|
||||||
|
|
|
@ -158,6 +158,22 @@ class TestPytestPluginInteractions:
|
||||||
config.parse([])
|
config.parse([])
|
||||||
assert not config.option.test123
|
assert not config.option.test123
|
||||||
|
|
||||||
|
def test_do_ext_namespace(self, testdir):
|
||||||
|
testdir.makeconftest("""
|
||||||
|
def pytest_namespace(config):
|
||||||
|
return {'hello': 'world'}
|
||||||
|
""")
|
||||||
|
p = testdir.makepyfile("""
|
||||||
|
from py.test import hello
|
||||||
|
import py
|
||||||
|
def test_hello():
|
||||||
|
assert hello == "world"
|
||||||
|
""")
|
||||||
|
result = testdir.runpytest(p)
|
||||||
|
assert result.stdout.fnmatch_lines([
|
||||||
|
"*1 passed*"
|
||||||
|
])
|
||||||
|
|
||||||
def test_do_option_postinitialize(self, testdir):
|
def test_do_option_postinitialize(self, testdir):
|
||||||
from py.__.test.config import Config
|
from py.__.test.config import Config
|
||||||
config = Config()
|
config = Config()
|
||||||
|
@ -205,7 +221,7 @@ class TestPytestPluginInteractions:
|
||||||
assert not pluginmanager.listattr("hello")
|
assert not pluginmanager.listattr("hello")
|
||||||
assert pluginmanager.listattr("x") == [42]
|
assert pluginmanager.listattr("x") == [42]
|
||||||
|
|
||||||
@py.test.mark(xfail="implement setupcall")
|
@py.test.xfail # setup call methods
|
||||||
def test_call_setup_participants(self, testdir):
|
def test_call_setup_participants(self, testdir):
|
||||||
testdir.makepyfile(
|
testdir.makepyfile(
|
||||||
conftest="""
|
conftest="""
|
||||||
|
|
Loading…
Reference in New Issue