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
|
Changes between 1.0.0b8 and 1.0.0b9
|
||||||
=====================================
|
=====================================
|
||||||
|
|
||||||
|
* simplified py.test.mark API
|
||||||
|
|
||||||
* make assert-reinterpretation work better with comparisons not
|
* make assert-reinterpretation work better with comparisons not
|
||||||
returning bools (reported with numpy from thanks maciej fijalkowski)
|
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
|
of keywords for a given test. You can specify additional
|
||||||
kewords like this::
|
kewords like this::
|
||||||
|
|
||||||
@py.test.mark(webtest=True)
|
@py.test.mark.webtest
|
||||||
def test_send_http():
|
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
|
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'),
|
'unittest doctest oejskit restdoc'),
|
||||||
('Plugins for generic reporting and failure logging',
|
('Plugins for generic reporting and failure logging',
|
||||||
'pocoo resultlog terminal',),
|
'pocoo resultlog terminal',),
|
||||||
|
('internal plugins / core functionality',
|
||||||
|
'pdb keyword hooklog')
|
||||||
#('internal plugins / core functionality',
|
#('internal plugins / core functionality',
|
||||||
# #'pdb keyword hooklog runner execnetcleanup # pytester',
|
# #'pdb keyword hooklog runner execnetcleanup # pytester',
|
||||||
# '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
|
import py
|
||||||
|
|
||||||
def pytest_namespace():
|
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):
|
def __getattr__(self, name):
|
||||||
if name[0] == "_":
|
if name[0] == "_":
|
||||||
raise AttributeError(name)
|
raise AttributeError(name)
|
||||||
kw = self._keywords.copy()
|
return MarkerDecorator(name)
|
||||||
kw[name] = True
|
|
||||||
return self.__class__(kw, lastname=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
|
def f(): pass
|
||||||
|
|
||||||
mark.hello(f)
|
mark.hello(f)
|
||||||
assert f.hello == True
|
assert f.hello
|
||||||
|
|
||||||
mark.hello("test")(f)
|
mark.world(x=3, y=4)(f)
|
||||||
assert f.hello == "test"
|
assert f.world
|
||||||
|
assert f.world.x == 3
|
||||||
|
assert f.world.y == 4
|
||||||
|
|
||||||
py.test.raises(AttributeError, "mark._hello")
|
py.test.raises(TypeError, "mark.some(x=3)(f=5)")
|
||||||
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"
|
|
||||||
|
|
||||||
def test_mark_plugin(testdir):
|
def test_mark_plugin(testdir):
|
||||||
p = testdir.makepyfile("""
|
p = testdir.makepyfile("""
|
||||||
|
|
Loading…
Reference in New Issue