From 318e8a404be53763ac952515ca78af041878a1a0 Mon Sep 17 00:00:00 2001 From: holger krekel Date: Sat, 5 Mar 2011 12:11:35 +0100 Subject: [PATCH] fix and improve error reporting for parametrizing funcargs (originally reported by antlong) --- _pytest/python.py | 21 +++++++++++++++------ pytest.py | 2 +- setup.py | 2 +- testing/test_python.py | 20 +++++++++++++++++--- 4 files changed, 34 insertions(+), 11 deletions(-) diff --git a/_pytest/python.py b/_pytest/python.py index c0e150e39..7a8c41723 100644 --- a/_pytest/python.py +++ b/_pytest/python.py @@ -486,10 +486,11 @@ def hasinit(obj): return True -def getfuncargnames(function): +def getfuncargnames(function, startindex=None): # XXX merge with main.py's varnames argnames = py.std.inspect.getargs(py.code.getrawcode(function))[0] - startindex = py.std.inspect.ismethod(function) and 1 or 0 + if startindex is None: + startindex = py.std.inspect.ismethod(function) and 1 or 0 defaults = getattr(function, 'func_defaults', getattr(function, '__defaults__', None)) or () numdefaults = len(defaults) @@ -518,7 +519,8 @@ class Metafunc: self.config = config self.module = module self.function = function - self.funcargnames = getfuncargnames(function) + self.funcargnames = getfuncargnames(function, + startindex=int(cls is not None)) self.cls = cls self.module = module self._calls = [] @@ -526,7 +528,11 @@ class Metafunc: def addcall(self, funcargs=None, id=_notexists, param=_notexists): """ add a new call to the underlying test function during the - collection phase of a test run. + collection phase of a test run. Note that request.addcall() is + called during the test collection phase prior and independently + to actual test execution. Therefore you should perform setup + of resources in a funcarg factory which can be instrumented + with the ``param``. :arg funcargs: argument keyword dictionary used when invoking the test function. @@ -538,10 +544,13 @@ class Metafunc: :arg param: will be exposed to a later funcarg factory invocation through the ``request.param`` attribute. It allows to defer test fixture setup activities to when an actual - test is run. Note that request.addcall() is called during - the collection phase of a test run. + test is run. """ assert funcargs is None or isinstance(funcargs, dict) + if funcargs is not None: + for name in funcargs: + if name not in self.funcargnames: + pytest.fail("funcarg %r not used in this function." % name) if id is None: raise ValueError("id=None not allowed") if id is _notexists: diff --git a/pytest.py b/pytest.py index 3c26a9d34..03658acb2 100644 --- a/pytest.py +++ b/pytest.py @@ -1,7 +1,7 @@ """ unit and functional testing with Python. """ -__version__ = '2.0.2.dev2' +__version__ = '2.0.2.dev3' __all__ = ['main'] from _pytest.core import main, UsageError, _preloadplugins diff --git a/setup.py b/setup.py index c3988957a..25bbb893d 100644 --- a/setup.py +++ b/setup.py @@ -22,7 +22,7 @@ def main(): name='pytest', description='py.test: simple powerful testing with Python', long_description = long_description, - version='2.0.2.dev2', + version='2.0.2.dev3', url='http://pytest.org', license='MIT license', platforms=['unix', 'linux', 'osx', 'cygwin', 'win32'], diff --git a/testing/test_python.py b/testing/test_python.py index 31a11d71f..fe24e443c 100644 --- a/testing/test_python.py +++ b/testing/test_python.py @@ -915,11 +915,12 @@ class TestMetafunc: assert metafunc._calls[2].param == 1 def test_addcall_funcargs(self): - def func(arg1): pass + def func(x): pass metafunc = funcargs.Metafunc(func) class obj: pass metafunc.addcall(funcargs={"x": 2}) metafunc.addcall(funcargs={"x": 3}) + pytest.raises(pytest.fail.Exception, "metafunc.addcall({'xyz': 0})") assert len(metafunc._calls) == 2 assert metafunc._calls[0].funcargs == {'x': 2} assert metafunc._calls[1].funcargs == {'x': 3} @@ -1003,6 +1004,21 @@ class TestGenfuncFunctional: "*1 failed, 3 passed*" ]) + def test_noself_in_method(self, testdir): + p = testdir.makepyfile(""" + def pytest_generate_tests(metafunc): + assert 'xyz' not in metafunc.funcargnames + + class TestHello: + def test_hello(xyz): + pass + """) + result = testdir.runpytest(p) + result.stdout.fnmatch_lines([ + "*1 pass*", + ]) + + def test_generate_plugin_and_module(self, testdir): testdir.makeconftest(""" def pytest_generate_tests(metafunc): @@ -1339,5 +1355,3 @@ def test_customize_through_attributes(testdir): "*MyInstance*", "*MyFunction*test_hello*", ]) - -