On Fri, 2010-08-20 at 15:49 +0200, Florian Bauer wrote: 
> Hi all,
> 
> I'm trying to make an existing testsuite py.test compatible.
> At the moment, we use nose as test runner. I stumbled upon the following
> (simplified example).
>  
> from functools import partial
>  
> def forall_cases(cases):
>     def decorate(testfn):
>         def gen():
>             for case in cases:
>                 description = case[0]
>                 args = case[1:]
>                 func = partial(testfn, *args)
>                 func.description = description
>                 yield func,
>         gen.__name__= 'test_%s_' % testfn.__name__ 
>         #
>         # inject the generator into the module testfn came from
>         #
>         gen.__module__ = testfn.__module__
>         return gen
>     return decorate
>  
> 
> @forall_cases([['case1', 1, 1], ['case2', 2, 2],['case3', 3, 4]]) def
> test_equal(a, b):
>     assert a == b
> 
>  
> If I run this with nosetests, I get 3 test cases, 2 pass and 1 fail.
> 
> py.test tries to call inspect.getsource on the partial object, which
> results in a TypeError:
> 
> $ py.test -v
> ...
> INTERNALERROR>
> INTERNALERROR> object = <functools.partial object at 0x00F019C0>
> INTERNALERROR>
> INTERNALERROR>     def getfile(object):
> INTERNALERROR>         """Work out which source or compiled file an 
> INTERNALERROR> object was d
> efined in."""
> ...
> INTERNALERROR> >       raise TypeError('arg is not a module, class,
> method, '
> INTERNALERROR>                         'function, traceback, frame, or 
> INTERNALERROR> code obje
> ct')
> INTERNALERROR> E       TypeError: arg is not a module, class, method,
> function,
> traceback, frame, or code object
> INTERNALERROR>
> INTERNALERROR> object     = <functools.partial object at 0x00F019C0>
> INTERNALERROR>
> INTERNALERROR> c:\Python26\lib\inspect.py:418: TypeError
> 
>  This seems to be a documented limitation of inspect.getsource
> (functools.partial returns a partial object, not a function).
> I can fix this by replacing functools.partial with code given as roughly
> equivalent in the python documentation:
> 
> def partial(func, *args, **keywords):
>     def newfunc(*fargs, **fkeywords):
>         newkeywords = keywords.copy()
>         newkeywords.update(fkeywords)
>         return func(*(args + fargs), **newkeywords)
>     newfunc.func = func
>     newfunc.args = args
>     newfunc.keywords = keywords
>     return newfunc
> 
> But I was certainly not expecting this. The default behavior of py.test
> is even more puzzling, as it fails silently:
> 
> fba...@mn-eng-lt-fb ~/My Documents/Software/pytestbug1 $ py.test
> ============================= test session starts
> ============================= platform win32 -- Python 2.6.5 --
> pytest-1.3.3 test path 1: c:\docume~1\fbauer\My
> Documents\Software\pytestbug1
> 
> test_case.py ..

that looks like 2 bugs cooperating for certain confusion
not being able to get the source causes pytest to internally fail
and those seem to be failing

i'll try to make minimal replications for the pytest testsuite as i cant
tell from your trace where exactly the issue orginates

> 
> In my actual code, the forall_cases decorator lives in a utils module.
> Is there a conditional flag that can tell me whether I'm running under
> py.test? Then I could start experimenting with parametric tests using
> funcargs, while keeping the test suite runnable with nose at the moment.
> I still have a bug in the test suite, as I have tests passing under nose
> that fail under py.test...
> 
im not sure of such a flag, you could use the pytest_configure hook in a
conftest to set up certain globals

same goes for the per module setup hooks

also you could try to use the collect hooks to strip your decorated
testcases of the decorator

Regards,
Ronny

_______________________________________________
py-dev mailing list
py-dev@codespeak.net
http://codespeak.net/mailman/listinfo/py-dev

Reply via email to