99 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			Python
		
	
	
	
			
		
		
	
	
			99 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			Python
		
	
	
	
"""nose-compatibility plugin: allow to run nose test suites natively. 
 | 
						|
 | 
						|
This is an experimental plugin for allowing to run tests written 
 | 
						|
in 'nosetests style with py.test.   
 | 
						|
 | 
						|
Usage
 | 
						|
-------------
 | 
						|
 | 
						|
type::
 | 
						|
 | 
						|
    py.test  # instead of 'nosetests'
 | 
						|
 | 
						|
and you should be able to run nose style tests and at the same
 | 
						|
time can make full use of py.test's capabilities.  
 | 
						|
 | 
						|
Supported nose Idioms
 | 
						|
----------------------
 | 
						|
 | 
						|
* setup and teardown at module/class/method level
 | 
						|
* SkipTest exceptions and markers 
 | 
						|
* setup/teardown decorators
 | 
						|
* yield-based tests and their setup 
 | 
						|
* general usage of nose utilities 
 | 
						|
 | 
						|
Unsupported idioms / issues
 | 
						|
----------------------------------
 | 
						|
 | 
						|
- nose-style doctests are not collected and executed correctly,
 | 
						|
  also fixtures don't work. 
 | 
						|
 | 
						|
- no nose-configuration is recognized 
 | 
						|
 | 
						|
If you find other issues or have suggestions please run:: 
 | 
						|
 | 
						|
    py.test --pastebin=all 
 | 
						|
 | 
						|
and send the resulting URL to a py.test contact channel,
 | 
						|
at best to the mailing list. 
 | 
						|
"""
 | 
						|
import py
 | 
						|
import inspect
 | 
						|
import sys
 | 
						|
 | 
						|
def pytest_runtest_makereport(__multicall__, item, call):
 | 
						|
    SkipTest = getattr(sys.modules.get('nose', None), 'SkipTest', None)
 | 
						|
    if SkipTest:
 | 
						|
        if call.excinfo and call.excinfo.errisinstance(SkipTest):
 | 
						|
            # let's substitute the excinfo with a py.test.skip one 
 | 
						|
            call2 = call.__class__(lambda: py.test.skip(str(call.excinfo.value)), call.when)
 | 
						|
            call.excinfo = call2.excinfo 
 | 
						|
 | 
						|
def pytest_report_iteminfo(item):
 | 
						|
    # nose 0.11.1 uses decorators for "raises" and other helpers. 
 | 
						|
    # for reporting progress by filename we fish for the filename 
 | 
						|
    if isinstance(item, py.test.collect.Function):
 | 
						|
        obj = item.obj
 | 
						|
        if hasattr(obj, 'compat_co_firstlineno'):
 | 
						|
            fn = sys.modules[obj.__module__].__file__ 
 | 
						|
            if fn.endswith(".pyc"):
 | 
						|
                fn = fn[:-1]
 | 
						|
            #assert 0
 | 
						|
            #fn = inspect.getsourcefile(obj) or inspect.getfile(obj)
 | 
						|
            lineno = obj.compat_co_firstlineno    
 | 
						|
            return py.path.local(fn), lineno, obj.__module__
 | 
						|
    
 | 
						|
def pytest_runtest_setup(item):
 | 
						|
    if isinstance(item, (py.test.collect.Function)):
 | 
						|
        if isinstance(item.parent, py.test.collect.Generator):
 | 
						|
            gen = item.parent 
 | 
						|
            if not hasattr(gen, '_nosegensetup'):
 | 
						|
                call_optional(gen.obj, 'setup')
 | 
						|
                if isinstance(gen.parent, py.test.collect.Instance):
 | 
						|
                    call_optional(gen.parent.obj, 'setup')
 | 
						|
                gen._nosegensetup = True
 | 
						|
        if not call_optional(item.obj, 'setup'):
 | 
						|
            # call module level setup if there is no object level one
 | 
						|
            call_optional(item.parent.obj, 'setup')
 | 
						|
 | 
						|
def pytest_runtest_teardown(item):
 | 
						|
    if isinstance(item, py.test.collect.Function):
 | 
						|
        if not call_optional(item.obj, 'teardown'):
 | 
						|
            call_optional(item.parent.obj, 'teardown')
 | 
						|
        #if hasattr(item.parent, '_nosegensetup'):
 | 
						|
        #    #call_optional(item._nosegensetup, 'teardown')
 | 
						|
        #    del item.parent._nosegensetup
 | 
						|
 | 
						|
def pytest_make_collect_report(collector):
 | 
						|
    if isinstance(collector, py.test.collect.Generator):
 | 
						|
        call_optional(collector.obj, 'setup')
 | 
						|
 | 
						|
def call_optional(obj, name):
 | 
						|
    method = getattr(obj, name, None)
 | 
						|
    if method:
 | 
						|
        ismethod = inspect.ismethod(method)
 | 
						|
        rawcode = py.code.getrawcode(method)
 | 
						|
        if not rawcode.co_varnames[ismethod:]:
 | 
						|
            method()
 | 
						|
            return True
 |