[py-dev] Decorators and funcargs in py.test

Vyacheslav Rafalskiy rafalskiy at gmail.com
Fri Jun 3 18:06:06 CEST 2011


On Thu, Jun 2, 2011 at 12:46 AM, holger krekel <holger at merlinux.eu> wrote:
> On Wed, Jun 01, 2011 at 17:16 -0400, Vyacheslav Rafalskiy wrote:
>> >> #---------->>  in test_1.py
>> >> @pytest.mark.timeout(10)
>> >> def test_f1():
>> >>     # test here
>> >>
>> >> #---------->>  in conftest.py
>> >> def pytest_runtest_call(item):
>> >>     if hasattr(item.obj, 'timeout'):
>> >>         timeout = item.obj.timeout.args[0]
>> >>         item.obj = run_with_timeout(timeout)(item.obj)
>> >>
>> >> Your comments are welcome.
>> >
>> > it's basically ok but there are some bits that could
>> > be improved.  You are actually implementing the general
>> > test item call.  Also I am not sure why you assign
>> > "item.obj = ...".
>>
>> I replace (or so I think) the original test function by the decorated
>> one. It gets called elsewhere.
>
> ah, of course :)
>
>> > I'd probably write something like this:
>> >
>> >    @pytest.mark.tryfirst
>> >    def pytest_pyfunc_call(pyfuncitem, __multicall__):
>> >        if 'timeout' in pyfuncitem.keywords:
>> >            timeout = pyfuncitem.keywords['timeout'].args[0]
>> >            run_with_timeout(timeout)(__multicall__.execute)
>>
>> this will take a while to digest
>
> it's actually wrong if run_with_timeout is only decorating
> but not running the function.  I think it makes sense to
> rather directly call a helper which calls the function
> (note that __multicall__.execute() will execute the remainder
> of the hook chain one of which will actually execute the
> function).  Such a helper would look like
> call_with_timeout(timeout, func) i guess.

To call the function I need to know what arguments to give it to.
The following seems to work, but this is just a guess:

def pytest_runtest_call(item):
    if hasattr(item.obj, 'timeout'):
        timeout = item.obj.timeout.args[0]
        run_with_timeout(timeout)(item.obj)(**item.funcargs)

I still don't quite get your example, specifically the
__multicall__.execute part.

Btw, the pytest_pyfunc_call() parameters seem to be in the wrong order
based on _pytest.python.py and the prototype in _pytest.hookspec.py
only lists one parameter.


 Vyacheslav



More information about the Pytest-dev mailing list