merged ronny's nose-compatibility hacks, i.e. nosestyle

setup_module() and setup() functions are supported.
added a few notes to changelog and documentation about it

--HG--
branch : trunk
This commit is contained in:
holger krekel 2009-10-27 16:49:38 +01:00
commit cc3404b832
6 changed files with 123 additions and 34 deletions

View File

@ -1,7 +1,7 @@
"""nose-compatibility plugin: allow to run nose test suites natively. """nose-compatibility plugin: allow to run nose test suites natively.
This is an experimental plugin for allowing to run tests written This is an experimental plugin for allowing to run tests written
in 'nosetests' style with py.test. in 'nosetests style with py.test.
Usage Usage
------------- -------------
@ -10,26 +10,32 @@ type::
py.test # instead of 'nosetests' py.test # instead of 'nosetests'
and you should be able to run nose style tests. You will of course and you should be able to run nose style tests and at the same
get py.test style reporting and its feature set. time can make full use of py.test's capabilities.
Issues? Supported nose Idioms
---------------- ----------------------
If you find issues or have suggestions please run:: * 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
py.test --pastebin=all Unsupported idioms / issues
----------------------------------
and send the resulting URL to a some contact channel.
Known issues
------------------
- nose-style doctests are not collected and executed correctly, - nose-style doctests are not collected and executed correctly,
also fixtures don't work. also fixtures don't work.
- no nose-configuration is recognized - 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 py
import inspect import inspect
@ -66,11 +72,14 @@ def pytest_runtest_setup(item):
if isinstance(gen.parent, py.test.collect.Instance): if isinstance(gen.parent, py.test.collect.Instance):
call_optional(gen.parent.obj, 'setup') call_optional(gen.parent.obj, 'setup')
gen._nosegensetup = True gen._nosegensetup = True
call_optional(item.obj, 'setup') 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): def pytest_runtest_teardown(item):
if isinstance(item, py.test.collect.Function): if isinstance(item, py.test.collect.Function):
call_optional(item.obj, 'teardown') if not call_optional(item.obj, 'teardown'):
call_optional(item.parent.obj, 'teardown')
#if hasattr(item.parent, '_nosegensetup'): #if hasattr(item.parent, '_nosegensetup'):
# #call_optional(item._nosegensetup, 'teardown') # #call_optional(item._nosegensetup, 'teardown')
# del item.parent._nosegensetup # del item.parent._nosegensetup
@ -82,4 +91,9 @@ def pytest_make_collect_report(collector):
def call_optional(obj, name): def call_optional(obj, name):
method = getattr(obj, name, None) method = getattr(obj, name, None)
if method: if method:
method() argspec = inspect.getargspec(method)
if argspec[0] == ['self']:
argspec = argspec[1:]
if not any(argspec):
method()
return True

View File

@ -161,13 +161,24 @@ class Module(py.test.collect.File, PyCollectorMixin):
def setup(self): def setup(self):
if getattr(self.obj, 'disabled', 0): if getattr(self.obj, 'disabled', 0):
py.test.skip("%r is disabled" %(self.obj,)) py.test.skip("%r is disabled" %(self.obj,))
mod = self.obj if hasattr(self.obj, 'setup_module'):
if hasattr(mod, 'setup_module'): #XXX: nose compat hack, move to nose plugin
self.obj.setup_module(mod) # if it takes a positional arg, its probably a py.test style one
# so we pass the current module object
if inspect.getargspec(self.obj.setup_module)[0]:
self.obj.setup_module(self.obj)
else:
self.obj.setup_module()
def teardown(self): def teardown(self):
if hasattr(self.obj, 'teardown_module'): if hasattr(self.obj, 'teardown_module'):
self.obj.teardown_module(self.obj) #XXX: nose compat hack, move to nose plugin
# if it takes a positional arg, its probably a py.test style one
# so we pass the current module object
if inspect.getargspec(self.obj.teardown_module)[0]:
self.obj.teardown_module(self.obj)
else:
self.obj.teardown_module()
class Class(PyCollectorMixin, py.test.collect.Collector): class Class(PyCollectorMixin, py.test.collect.Collector):

View File

@ -1,6 +1,5 @@
import py import os, sys
import sys
WIDTH = 75 WIDTH = 75
plugins = [ plugins = [
@ -269,6 +268,9 @@ class PluginDoc(RestWriter):
self.Print(opt.help, indent=4) self.Print(opt.help, indent=4)
if __name__ == "__main__": if __name__ == "__main__":
if os.path.exists("py"):
sys.path.insert(0, os.getcwd())
import py
_config = py.test.config _config = py.test.config
_config.parse([]) _config.parse([])
_config.pluginmanager.do_configure(_config) _config.pluginmanager.do_configure(_config)

View File

@ -1,6 +1,10 @@
Changes between 1.0.2 and '1.1.0b1' Changes between 1.0.2 and '1.1.0b1'
===================================== =====================================
* merged Ronny's nose-compatibility hacks: now
nose-style setup_module() and setup() functions are
supported
* introduce generalized py.test.mark function marking * introduce generalized py.test.mark function marking
* reshuffle / refine command line grouping * reshuffle / refine command line grouping

View File

@ -8,7 +8,7 @@ nose-compatibility plugin: allow to run nose test suites natively.
:local: :local:
This is an experimental plugin for allowing to run tests written This is an experimental plugin for allowing to run tests written
in 'nosetests' style with py.test. in 'nosetests style with py.test.
Usage Usage
------------- -------------
@ -17,25 +17,32 @@ type::
py.test # instead of 'nosetests' py.test # instead of 'nosetests'
and you should be able to run nose style tests. You will of course and you should be able to run nose style tests and at the same
get py.test style reporting and its feature set. time can make full use of py.test's capabilities.
Issues? Supported nose Idioms
---------------- ----------------------
If you find issues or have suggestions please run:: * 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
py.test --pastebin=all Unsupported idioms / issues
----------------------------------
and send the resulting URL to a some contact channel.
Known issues
------------------
- nose-style doctests are not collected and executed correctly, - nose-style doctests are not collected and executed correctly,
also fixtures don't work. also fixtures don't work.
- no nose-configuration is recognized - 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.
Start improving this plugin in 30 seconds Start improving this plugin in 30 seconds
========================================= =========================================

View File

@ -85,3 +85,54 @@ def test_nose_test_generator_fixtures(testdir):
]) ])
def test_module_level_setup(testdir):
testdir.makepyfile("""
from nose.tools import with_setup
items = {}
def setup():
items[1]=1
def teardown():
del items[1]
def setup2():
items[2] = 2
def teardown2():
del items[2]
def test_setup_module_setup():
assert items[1] == 1
@with_setup(setup2, teardown2)
def test_local_setup():
assert items[2] == 2
assert 1 not in items
""")
result = testdir.runpytest('-p', 'nose')
result.stdout.fnmatch_lines([
"*2 passed*",
])
def test_nose_style_setup_teardown(testdir):
testdir.makepyfile("""
l = []
def setup_module():
l.append(1)
def teardown_module():
del l[0]
def test_hello():
assert l == [1]
def test_world():
assert l == [1]
""")
result = testdir.runpytest('-p', 'nose')
result.stdout.fnmatch_lines([
"*2 passed*",
])