simplify py.test.mark API,
add more plugin docs --HG-- branch : 1.0.x
This commit is contained in:
parent
5b205e0711
commit
dcf194ebb8
|
@ -1,6 +1,8 @@
|
|||
Changes between 1.0.0b8 and 1.0.0b9
|
||||
=====================================
|
||||
|
||||
* simplified py.test.mark API
|
||||
|
||||
* make assert-reinterpretation work better with comparisons not
|
||||
returning bools (reported with numpy from thanks maciej fijalkowski)
|
||||
|
||||
|
|
|
@ -237,11 +237,15 @@ class/function names of a test function are put into the set
|
|||
of keywords for a given test. You can specify additional
|
||||
kewords like this::
|
||||
|
||||
@py.test.mark(webtest=True)
|
||||
@py.test.mark.webtest
|
||||
def test_send_http():
|
||||
...
|
||||
|
||||
and then use those keywords to select tests.
|
||||
and then use those keywords to select tests. See the `pytest_keyword`_
|
||||
plugin for more information.
|
||||
|
||||
.. _`pytest_keyword`: plugin/keyword.html
|
||||
|
||||
|
||||
disabling a test class
|
||||
----------------------
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
|
||||
pytest_hooklog plugin
|
||||
=====================
|
||||
|
||||
log invocations of extension hooks to a file.
|
||||
|
||||
.. contents::
|
||||
:local:
|
||||
|
||||
|
||||
|
||||
command line options
|
||||
--------------------
|
||||
|
||||
|
||||
``--hooklog=HOOKLOG``
|
||||
write hook calls to the given file.
|
||||
|
||||
Start improving this plugin in 30 seconds
|
||||
=========================================
|
||||
|
||||
|
||||
Do you find the above documentation or the plugin itself lacking?
|
||||
|
||||
1. Download `pytest_hooklog.py`_ plugin source code
|
||||
2. put it somewhere as ``pytest_hooklog.py`` into your import path
|
||||
3. a subsequent ``py.test`` run will use your local version
|
||||
|
||||
Further information: extend_ documentation, other plugins_ or contact_.
|
||||
|
||||
.. _`pytest_hooklog.py`: http://bitbucket.org/hpk42/py-trunk/raw/2b8d56b82ce6966960cf41d38dc2b794797912ba/py/test/plugin/pytest_hooklog.py
|
||||
.. _`extend`: ../extend.html
|
||||
.. _`plugins`: index.html
|
||||
.. _`contact`: ../../contact.html
|
||||
.. _`checkout the py.test development version`: ../../download.html#checkout
|
|
@ -0,0 +1,50 @@
|
|||
|
||||
pytest_keyword plugin
|
||||
=====================
|
||||
|
||||
mark test functions with keywords that may hold values.
|
||||
|
||||
.. contents::
|
||||
:local:
|
||||
|
||||
Marking functions and setting rich attributes
|
||||
----------------------------------------------------
|
||||
|
||||
By default, all filename parts and class/function names of a test
|
||||
function are put into the set of keywords for a given test. You can
|
||||
specify additional kewords like this::
|
||||
|
||||
@py.test.mark.webtest
|
||||
def test_send_http():
|
||||
...
|
||||
|
||||
This will set an attribute 'webtest' on the given test function
|
||||
and by default all such attributes signal keywords. You can
|
||||
also set values in this attribute which you could read from
|
||||
a hook in order to do something special with respect to
|
||||
the test function::
|
||||
|
||||
@py.test.mark.timeout(seconds=5)
|
||||
def test_receive():
|
||||
...
|
||||
|
||||
This will set the "timeout" attribute with a Marker object
|
||||
that has a 'seconds' attribute.
|
||||
|
||||
Start improving this plugin in 30 seconds
|
||||
=========================================
|
||||
|
||||
|
||||
Do you find the above documentation or the plugin itself lacking?
|
||||
|
||||
1. Download `pytest_keyword.py`_ plugin source code
|
||||
2. put it somewhere as ``pytest_keyword.py`` into your import path
|
||||
3. a subsequent ``py.test`` run will use your local version
|
||||
|
||||
Further information: extend_ documentation, other plugins_ or contact_.
|
||||
|
||||
.. _`pytest_keyword.py`: http://bitbucket.org/hpk42/py-trunk/raw/2b8d56b82ce6966960cf41d38dc2b794797912ba/py/test/plugin/pytest_keyword.py
|
||||
.. _`extend`: ../extend.html
|
||||
.. _`plugins`: index.html
|
||||
.. _`contact`: ../../contact.html
|
||||
.. _`checkout the py.test development version`: ../../download.html#checkout
|
|
@ -0,0 +1,35 @@
|
|||
|
||||
pytest_pdb plugin
|
||||
=================
|
||||
|
||||
interactive debugging with the Python Debugger.
|
||||
|
||||
.. contents::
|
||||
:local:
|
||||
|
||||
|
||||
|
||||
command line options
|
||||
--------------------
|
||||
|
||||
|
||||
``--pdb``
|
||||
start pdb (the Python debugger) on errors.
|
||||
|
||||
Start improving this plugin in 30 seconds
|
||||
=========================================
|
||||
|
||||
|
||||
Do you find the above documentation or the plugin itself lacking?
|
||||
|
||||
1. Download `pytest_pdb.py`_ plugin source code
|
||||
2. put it somewhere as ``pytest_pdb.py`` into your import path
|
||||
3. a subsequent ``py.test`` run will use your local version
|
||||
|
||||
Further information: extend_ documentation, other plugins_ or contact_.
|
||||
|
||||
.. _`pytest_pdb.py`: http://bitbucket.org/hpk42/py-trunk/raw/2b8d56b82ce6966960cf41d38dc2b794797912ba/py/test/plugin/pytest_pdb.py
|
||||
.. _`extend`: ../extend.html
|
||||
.. _`plugins`: index.html
|
||||
.. _`contact`: ../../contact.html
|
||||
.. _`checkout the py.test development version`: ../../download.html#checkout
|
|
@ -10,6 +10,8 @@ plugins = [
|
|||
'unittest doctest oejskit restdoc'),
|
||||
('Plugins for generic reporting and failure logging',
|
||||
'pocoo resultlog terminal',),
|
||||
('internal plugins / core functionality',
|
||||
'pdb keyword hooklog')
|
||||
#('internal plugins / core functionality',
|
||||
# #'pdb keyword hooklog runner execnetcleanup # pytester',
|
||||
# 'pdb keyword hooklog runner execnetcleanup' # pytester',
|
||||
|
|
|
@ -1,70 +1,86 @@
|
|||
"""
|
||||
py.test.mark / keyword plugin
|
||||
mark test functions with keywords that may hold values.
|
||||
|
||||
Marking functions and setting rich attributes
|
||||
----------------------------------------------------
|
||||
|
||||
By default, all filename parts and class/function names of a test
|
||||
function are put into the set of keywords for a given test. You can
|
||||
specify additional kewords like this::
|
||||
|
||||
@py.test.mark.webtest
|
||||
def test_send_http():
|
||||
...
|
||||
|
||||
This will set an attribute 'webtest' on the given test function
|
||||
and by default all such attributes signal keywords. You can
|
||||
also set values in this attribute which you could read from
|
||||
a hook in order to do something special with respect to
|
||||
the test function::
|
||||
|
||||
@py.test.mark.timeout(seconds=5)
|
||||
def test_receive():
|
||||
...
|
||||
|
||||
This will set the "timeout" attribute with a Marker object
|
||||
that has a 'seconds' attribute.
|
||||
|
||||
"""
|
||||
import py
|
||||
|
||||
def pytest_namespace():
|
||||
mark = KeywordDecorator({})
|
||||
return {'mark': mark}
|
||||
return {'mark': Mark()}
|
||||
|
||||
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
|
||||
|
||||
class Mark(object):
|
||||
def __getattr__(self, name):
|
||||
if name[0] == "_":
|
||||
raise AttributeError(name)
|
||||
kw = self._keywords.copy()
|
||||
kw[name] = True
|
||||
return self.__class__(kw, lastname=name)
|
||||
return MarkerDecorator(name)
|
||||
|
||||
class MarkerDecorator:
|
||||
""" decorator for setting function attributes. """
|
||||
def __init__(self, name):
|
||||
self.markname = name
|
||||
|
||||
def __repr__(self):
|
||||
d = self.__dict__.copy()
|
||||
name = d.pop('markname')
|
||||
return "<MarkerDecorator %r %r>" %(name, d)
|
||||
|
||||
def __call__(self, *args, **kwargs):
|
||||
if not args:
|
||||
if hasattr(self, 'kwargs'):
|
||||
raise TypeError("double mark-keywords?")
|
||||
self.kwargs = kwargs.copy()
|
||||
return self
|
||||
else:
|
||||
if not len(args) == 1 or not hasattr(args[0], 'func_dict'):
|
||||
raise TypeError("need exactly one function to decorate, "
|
||||
"got %r" %(args,))
|
||||
func = args[0]
|
||||
mh = MarkHolder(getattr(self, 'kwargs', {}))
|
||||
setattr(func, self.markname, mh)
|
||||
return func
|
||||
|
||||
class MarkHolder:
|
||||
def __init__(self, kwargs):
|
||||
self.__dict__.update(kwargs)
|
||||
|
||||
def test_pytest_mark_api():
|
||||
mark = Mark()
|
||||
py.test.raises(TypeError, "mark(x=3)")
|
||||
|
||||
def test_pytest_mark_getattr():
|
||||
mark = KeywordDecorator({})
|
||||
def f(): pass
|
||||
|
||||
mark.hello(f)
|
||||
assert f.hello == True
|
||||
assert f.hello
|
||||
|
||||
mark.hello("test")(f)
|
||||
assert f.hello == "test"
|
||||
mark.world(x=3, y=4)(f)
|
||||
assert f.world
|
||||
assert f.world.x == 3
|
||||
assert f.world.y == 4
|
||||
|
||||
py.test.raises(AttributeError, "mark._hello")
|
||||
py.test.raises(AttributeError, "mark.__str__")
|
||||
|
||||
def test_pytest_mark_call():
|
||||
mark = KeywordDecorator({})
|
||||
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"
|
||||
py.test.raises(TypeError, "mark.some(x=3)(f=5)")
|
||||
|
||||
def test_mark_plugin(testdir):
|
||||
p = testdir.makepyfile("""
|
||||
|
|
Loading…
Reference in New Issue