[py-svn] r61424 - in py/branch/pytestplugin/py: doc test test/plugin test/testing

hpk at codespeak.net hpk at codespeak.net
Wed Jan 28 15:35:56 CET 2009


Author: hpk
Date: Wed Jan 28 15:35:54 2009
New Revision: 61424

Added:
   py/branch/pytestplugin/py/test/plugin/pytest_plugintester.py   (contents, props changed)
   py/branch/pytestplugin/py/test/plugin/pytest_pytester.py   (contents, props changed)
Modified:
   py/branch/pytestplugin/py/doc/impl-test.txt
   py/branch/pytestplugin/py/test/config.py
   py/branch/pytestplugin/py/test/conftesthandle.py
   py/branch/pytestplugin/py/test/plugin/conftest.py
   py/branch/pytestplugin/py/test/plugin/pytest_eventlog.py
   py/branch/pytestplugin/py/test/plugin/pytest_resultlog.py
   py/branch/pytestplugin/py/test/plugin/pytest_terminal.py
   py/branch/pytestplugin/py/test/plugin/pytest_tmpdir.py
   py/branch/pytestplugin/py/test/pmanage.py
   py/branch/pytestplugin/py/test/pycollect.py
   py/branch/pytestplugin/py/test/testing/test_conftesthandle.py
   py/branch/pytestplugin/py/test/testing/test_pmanage.py
Log:
introduce new plugins for testing py.test and its plugins
refine plugin initialization logic 



Modified: py/branch/pytestplugin/py/doc/impl-test.txt
==============================================================================
--- py/branch/pytestplugin/py/doc/impl-test.txt	(original)
+++ py/branch/pytestplugin/py/doc/impl-test.txt	Wed Jan 28 15:35:54 2009
@@ -311,7 +311,7 @@
 * pytest_unconfigure(self, config): called before the test process quits 
 * pytest_event(self, event): called for each `pytest event`_ 
 
-XXX document missing pytest_* hooks 
+XXX reference APIcheck'ed full documentation
 
 _`pytest event`: 
 
@@ -331,6 +331,8 @@
   pytest_eventlog: log all internal pytest events to a file 
   pytest_xfail: "expected to fail" test marker 
   pytest_tmpdir: provide temporary directories to test functions 
+  pytest_plugintester: generic apichecks, support for functional plugin tests 
+  pytest_pytester: support for testing py.test runs
 
 * extending test execution, e.g. 
   pytest_apigen: tracing values of function/method calls when running tests

Modified: py/branch/pytestplugin/py/test/config.py
==============================================================================
--- py/branch/pytestplugin/py/test/config.py	(original)
+++ py/branch/pytestplugin/py/test/config.py	Wed Jan 28 15:35:54 2009
@@ -35,9 +35,9 @@
         self.option = CmdOptions()
         self._parser = optparse.OptionParser(
             usage="usage: %prog [options] [query] [filenames of tests]")
-        self._conftest = Conftest()
         self.bus = EventBus()
         self.pluginmanager = PluginManager()
+        self._conftest = Conftest(onimport=self.pluginmanager.consider_module)
 
     def parse(self, args): 
         """ parse cmdline arguments into this config object. 
@@ -48,7 +48,6 @@
         self._initialized = True
         adddefaultoptions(self)
         self._conftest.setinitial(args)
-        self.pluginmanager.registerplugins(self._conftest.getconftestmodules(None))
         self.pluginmanager.add_cmdlineoptions(self)
         args = [str(x) for x in args]
         cmdlineoption, args = self._parser.parse_args(args) 
@@ -72,7 +71,6 @@
         self._initialized = True
         self.topdir = py.path.local(topdir)
         self._mergerepr(self._repr)
-        self.pluginmanager.registerplugins(self._conftest.getconftestmodules(None))
         del self._repr 
         self.pluginmanager.configure(self)
 

Modified: py/branch/pytestplugin/py/test/conftesthandle.py
==============================================================================
--- py/branch/pytestplugin/py/test/conftesthandle.py	(original)
+++ py/branch/pytestplugin/py/test/conftesthandle.py	Wed Jan 28 15:35:54 2009
@@ -9,8 +9,9 @@
         conftest.py files may result in added cmdline options. 
         XXX
     """ 
-    def __init__(self, path=None):
+    def __init__(self, path=None, onimport=None):
         self._path2confmods = {}
+        self._onimport = onimport
         if path is not None:
             self.setinitial([path])
 
@@ -37,11 +38,11 @@
         except KeyError:
             dp = path.dirpath()
             if dp == path: 
-                return [importconfig(defaultconftestpath)]
+                return [self.importconftest(defaultconftestpath)]
             clist = self.getconftestmodules(dp)
             conftestpath = path.join("conftest.py")
             if conftestpath.check(file=1):
-                clist.append(importconfig(conftestpath))
+                clist.append(self.importconftest(conftestpath))
             self._path2confmods[path] = clist
         # be defensive: avoid changes from caller side to
         # affect us by always returning a copy of the actual list 
@@ -61,15 +62,17 @@
                 continue
         raise KeyError, name
 
-def importconfig(configpath):
-    # We could have used caching here, but it's redundant since
-    # they're cached on path anyway, so we use it only when doing rget_path
-    assert configpath.check(), configpath
-    if not configpath.dirpath('__init__.py').check(file=1): 
-        # HACK: we don't want any "globally" imported conftest.py, 
-        #       prone to conflicts and subtle problems 
-        modname = str(configpath).replace('.', configpath.sep)
-        mod = configpath.pyimport(modname=modname)
-    else:
-        mod = configpath.pyimport()
-    return mod
+    def importconftest(self, conftestpath):
+        # Using caching here looks redundant since ultimately
+        # sys.modules caches already 
+        assert conftestpath.check(), conftestpath
+        if not conftestpath.dirpath('__init__.py').check(file=1): 
+            # HACK: we don't want any "globally" imported conftest.py, 
+            #       prone to conflicts and subtle problems 
+            modname = str(conftestpath).replace('.', conftestpath.sep)
+            mod = conftestpath.pyimport(modname=modname)
+        else:
+            mod = conftestpath.pyimport()
+        if self._onimport:
+            self._onimport(mod)
+        return mod

Modified: py/branch/pytestplugin/py/test/plugin/conftest.py
==============================================================================
--- py/branch/pytestplugin/py/test/plugin/conftest.py	(original)
+++ py/branch/pytestplugin/py/test/plugin/conftest.py	Wed Jan 28 15:35:54 2009
@@ -1,5 +1,7 @@
 import py
 
+pytest_plugins = "pytest_pytester", "pytest_plugintester"
+
 class Directory(py.test.collect.Directory):
     def consider_file(self, path, usefilters):
         if path.basename.startswith("pytest_") and path.ext == ".py":

Modified: py/branch/pytestplugin/py/test/plugin/pytest_eventlog.py
==============================================================================
--- py/branch/pytestplugin/py/test/plugin/pytest_eventlog.py	(original)
+++ py/branch/pytestplugin/py/test/plugin/pytest_eventlog.py	Wed Jan 28 15:35:54 2009
@@ -23,19 +23,19 @@
             f.flush()
 
 # ===============================================================================
-#
 # plugin tests 
-#
 # ===============================================================================
 
-from py.__.test.testing import plugintester
+def test_generic(plugintester):
+    plugintester.apicheck()
 
-def test_generic():
-    impname = "py.__.test.plugin.pytest_eventlog"
-    plugintester.nocalls(impname) 
-    tmpdir = plugintester.functional(
-        "py.__.test.plugin.pytest_eventlog", '--eventlog=event.log')
-    s = tmpdir.join("event.log").read()
+    fstester = plugintester.fstester()
+    fstester.makepyfile(test_one="""
+        def test_pass():
+            pass
+    """)
+    fstester.runpytest("--eventlog=event.log")
+    s = fstester.tmpdir.join("event.log").read()
     assert s.find("TestrunStart") != -1
     assert s.find("ItemTestReport") != -1
     assert s.find("TestrunFinish") != -1

Added: py/branch/pytestplugin/py/test/plugin/pytest_plugintester.py
==============================================================================
--- (empty file)
+++ py/branch/pytestplugin/py/test/plugin/pytest_plugintester.py	Wed Jan 28 15:35:54 2009
@@ -0,0 +1,127 @@
+"""
+plugin with support classes and functions for testing pytest functionality 
+"""
+import py
+
+class Plugintester:
+    def pytest_itemexecute_arg(self, pyfuncitem, argname):
+        if argname == "plugintester":
+            suptest = PluginTester(pyfuncitem) 
+        else:
+            return None
+        return suptest, suptest.finalize 
+
+class Support(object):
+    def __init__(self, pyfuncitem):
+        """ instantiated per function that requests it. """
+        self.pyfuncitem = pyfuncitem
+
+    def getmoditem(self):
+        for colitem in self.pyfuncitem.listchain():
+            if isinstance(colitem, colitem.Module):
+                return colitem 
+    def _getimpname(self):
+        return self.getmoditem().obj.__name__
+
+    def finalize(self):
+        """ called after test function finished execution"""
+
+class PluginTester(Support):
+    def fstester(self, cmdlineargs=()):
+        # XXX import differently, eg. 
+        #     FSTester = self.pyfuncitem._config.pluginmanager.getpluginattr("pytester", "FSTester")
+        from pytest_pytester import FSTester
+        impname = self._getimpname()
+        tmpdir = py.test.ensuretemp(impname) 
+        crunner = FSTester(tmpdir)
+        crunner.ensureplugin(impname) 
+        return crunner 
+
+    def apicheck(self, impname=None):
+        from py.__.test.pmanage import PluginManager
+        if not impname:
+            impname = self.getmoditem().obj.__name__
+        print "loading and checking", impname 
+        fail = False 
+        pm = PluginManager()
+        plugin = pm.import_plugin(impname) 
+        methods = collectattr(plugin.__class__)
+        hooks = collectattr(PytestPluginHooks)
+        getargs = py.std.inspect.getargs
+        while methods:
+            name, method = methods.popitem()
+            if name not in hooks:
+                print "definition of unknown hook: %s" % name 
+                fail = True
+            else:
+                hook = hooks[name]
+                if not hasattr(hook, 'func_code'):
+                    continue # XXX do some checks on attributes as well? 
+                method_args = getargs(method.func_code) 
+                hookargs = getargs(hook.func_code)
+                for arg, hookarg in zip(method_args[0], hookargs[0]):
+                    if arg != hookarg: 
+                        print "argument mismatch:" 
+                        print "required:", formatdef(method)
+                        print "actual  :", formatdef(hook)
+                        fail = True
+                        break 
+                if not fail:
+                    print "matching hook:", formatdef(method)
+        if fail:
+            py.test.fail("Plugin API error")
+
+def collectattr(obj, prefix="pytest_"):
+    methods = {}
+    for apiname in vars(obj): 
+        if apiname.startswith(prefix):
+            methods[apiname] = getattr(obj, apiname) 
+    return methods 
+
+def formatdef(func):
+    formatargspec = py.std.inspect.formatargspec
+    getargspec = py.std.inspect.formatargspec
+    return "%s%s" %(
+        func.func_name, 
+        py.std.inspect.formatargspec(*py.std.inspect.getargspec(func))
+    )
+
+
+class PytestPluginHooks:
+    def __init__(self):
+        """ usually called only once per test process. """ 
+
+    pytest_cmdlineoptions = []
+
+    def pytest_configure(self, config):
+        """ called after command line options have been parsed. 
+            and all plugins and initial conftest files been loaded. 
+            ``config`` provides access to all such configuration values. 
+        """
+    def pytest_unconfigure(self, config):
+        """ called before test process is exited. 
+        """
+
+    def pytest_event(self, event):
+        """ called for each internal py.test event.  """
+
+    def pytest_itemexecute_arg(self, pyfuncitem, argname):
+        """ provide (value, finalizer) for an open test function argument. 
+
+            the finalizer (if not None) will be called after the test 
+            function has been executed (i.e. pyfuncitem.execute() returns). 
+        """ 
+    def pytest_termreport_result(self, event):
+        """ return (category, short, verbose) information about the given result event. 
+            ``category`` will be used for counting tests and 
+            pytest_termreport_summary will be called for each category. 
+            ``short`` will be used for printing progress info like "...F.."
+            ``verbose`` is used for printing verbose information. 
+        """ 
+   
+# ===============================================================================
+# plugin tests 
+# ===============================================================================
+
+def test_generic(plugintester):
+    plugintester.apicheck()

Added: py/branch/pytestplugin/py/test/plugin/pytest_pytester.py
==============================================================================
--- (empty file)
+++ py/branch/pytestplugin/py/test/plugin/pytest_pytester.py	Wed Jan 28 15:35:54 2009
@@ -0,0 +1,138 @@
+"""
+pytes plugin for easing testing of pytest runs themselves. 
+"""
+
+import py
+
+class RunResult:
+    def __init__(self, ret, outlines, errlines):
+        self.ret = ret
+        self.outlines = outlines
+        self.errlines = errlines
+
+class FileCreation(object):
+    def makepyfile(self, **kwargs):
+        return self._makefile('.py', **kwargs)
+    def maketxtfile(self, **kwargs):
+        return self._makefile('.txt', **kwargs)
+    def _makefile(self, ext, **kwargs):
+        ret = None
+        for name, value in kwargs.iteritems():
+            p = self.tmpdir.join(name).new(ext=ext)
+            source = py.code.Source(value)
+            p.write(str(py.code.Source(value)).lstrip())
+            if ret is None:
+                ret = p
+        return ret 
+
+class FSTester(FileCreation):
+    def __init__(self, tmpdir):
+        self.tmpdir = tmpdir
+        self._plugins = []
+
+    def ensureplugin(self, impname):
+        assert isinstance(impname, str)
+        if not impname in self._plugins:
+            self._plugins.append(impname)
+
+    def _writeconftest(self):
+        p = self.tmpdir.join("conftest.py") 
+        pstring = repr(self._plugins)
+        p.write("import py ; pytest_plugins = %s" % pstring)
+        #else:
+        #    lines = p.readlines(cr=0)
+        #    for i, line in py.builtin.enumerate(lines):
+        #        if line.find("pytest_plugins") != -1:
+        #            lines[i] = line + ", %s" % pstring
+        #            break
+        #    else:
+        #        lines.append(pstring)
+        #    p.write("\n".join(lines))
+            
+    def prepare(self):
+        self._writeconftest()
+
+    def popen(self, cmdargs, stdout, stderr, **kw):
+        if not hasattr(py.std, 'subprocess'):
+            py.test.skip("no subprocess module")
+        return py.std.subprocess.Popen(cmdargs, stdout=stdout, stderr=stderr, **kw)
+
+    def run(self, *cmdargs):
+        self.prepare()
+        old = self.tmpdir.chdir()
+        #print "chdir", self.tmpdir
+        try:
+            return self._run(*cmdargs)
+        finally:
+            old.chdir()
+
+    def _run(self, *cmdargs):
+        cmdargs = map(str, cmdargs)
+        p1 = py.path.local("stdout")
+        p2 = py.path.local("stderr")
+        print "running", cmdargs, "curdir=", py.path.local()
+        popen = self.popen(cmdargs, stdout=p1.open("w"), stderr=p2.open("w"))
+        ret = popen.wait()
+        out, err = p1.readlines(cr=0), p2.readlines(cr=0)
+        if err:
+            for line in err: 
+                print >>py.std.sys.stderr, line
+        return RunResult(ret, out, err)
+
+    def runpybin(self, scriptname, *args):
+        bindir = py.path.local(py.__file__).dirpath("bin")
+        if py.std.sys.platform == "win32":
+            script = bindir.join("win32", scriptname + ".cmd")
+        else:
+            script = bindir.join(scriptname)
+        assert script.check()
+        return self.run(script, *args)
+
+    def runpytest(self, *args):
+        return self.runpybin("py.test", *args)
+
+class Pytester:
+    def pytest_itemexecute_arg(self, pyfuncitem, argname):
+        if argname == "linecomp":
+            return LineComp(), None
+
+class LineComp:
+    def assert_contains_lines(self, lines1, lines2):
+        """ assert that lines2 are contained (linearly) in lines1. 
+            return a list of extralines found.
+        """
+        from fnmatch import fnmatch
+        __tracebackhide__ = True
+        if hasattr(lines1, "getvalue"):
+            lines1 = lines1.getvalue().split("\n")
+        if isinstance(lines2, str):
+            lines2 = py.code.Source(lines2)
+        if isinstance(lines2, py.code.Source):
+            lines2 = lines2.strip().lines
+
+        extralines = []
+        lines1 = lines1[:]
+        nextline = None
+        for line in lines2:
+            nomatchprinted = False
+            while lines1:
+                nextline = lines1.pop(0)
+                if line == nextline:
+                    print "exact match:", repr(line)
+                    break 
+                elif fnmatch(nextline, line):
+                    print "fnmatch:", repr(line)
+                    print "   with:", repr(nextline)
+                    break
+                else:
+                    if not nomatchprinted:
+                        print "nomatch:", repr(line)
+                        nomatchprinted = True
+                    print "    and:", repr(nextline)
+                extralines.append(nextline)
+            else:
+                if line != nextline:
+                    #__tracebackhide__ = True
+                    raise AssertionError("expected line not found: %r" % line)
+        extralines.extend(lines1)
+        return extralines 

Modified: py/branch/pytestplugin/py/test/plugin/pytest_resultlog.py
==============================================================================
--- py/branch/pytestplugin/py/test/plugin/pytest_resultlog.py	(original)
+++ py/branch/pytestplugin/py/test/plugin/pytest_resultlog.py	Wed Jan 28 15:35:54 2009
@@ -99,8 +99,7 @@
 # ===============================================================================
 
 import os, StringIO
-from py.__.test.testing import plugintester, suptest
-from py.__.test import event
+from py.__.test.testing import suptest
 
 def test_generic_path():
     from py.__.test.collect import Node, Item, FSCollector
@@ -123,18 +122,6 @@
     res = generic_path(item)
     assert res == 'test/a:B().c[1]'
 
-def test_generic():
-    plugintester.nocalls("py.__.test.plugin.pytest_resultlog")
-    tmpdir = plugintester.functional("py.__.test.plugin.pytest_resultlog", 
-        '--resultlog=resultlog')
-    resultlog = tmpdir.join("resultlog") 
-    s = resultlog.readlines(cr=0)
-    suptest.assert_lines_contain_lines(s, [
-        ". *:test_pass", 
-        "F *:test_fail", 
-        "s *:test_skip", 
-    ])
-    
 def test_write_log_entry():
     reslog = ResultLog(None)
     reslog.logfile = StringIO.StringIO()
@@ -172,6 +159,7 @@
     assert len(entry_lines) == 5
     assert entry_lines[0] == 'F name'
     assert entry_lines[1:] == [' '+line for line in longrepr.splitlines()]
+
     
 class TestWithFunctionIntegration(suptest.InlineSession):
     # XXX (hpk) i think that the resultlog plugin should
@@ -228,6 +216,7 @@
     def test_internal_exception(self):
         # they are produced for example by a teardown failing
         # at the end of the run
+        from py.__.test import event
         bus = event.EventBus()
         reslog = ResultLog(StringIO.StringIO())        
         bus.subscribe(reslog.log_event_to_file)
@@ -249,3 +238,24 @@
         assert entry_lines[-1][0] == ' '
         assert 'ValueError' in entry  
 
+def test_generic(plugintester, linecomp):
+    plugintester.apicheck()
+    fstester = plugintester.fstester()
+    fstester.makepyfile(test_one="""
+        import py
+        def test_pass():
+            pass
+        def test_fail():
+            assert 0
+        def test_skip():
+            py.test.skip("")
+    """)
+    fstester.runpytest("--resultlog=result.log")
+    s = fstester.tmpdir.join("result.log").readlines(cr=0)
+   
+    linecomp.assert_contains_lines(s, [
+        ". *:test_pass", 
+        "F *:test_fail", 
+        "s *:test_skip", 
+    ])
+    

Modified: py/branch/pytestplugin/py/test/plugin/pytest_terminal.py
==============================================================================
--- py/branch/pytestplugin/py/test/plugin/pytest_terminal.py	(original)
+++ py/branch/pytestplugin/py/test/plugin/pytest_terminal.py	Wed Jan 28 15:35:54 2009
@@ -1,6 +1,5 @@
 import py
 import sys
-from py.__.test import event
 from py.__.test.collect import getrelpath
 
 class Terminal(object):
@@ -298,10 +297,6 @@
                         py.std.sys.executable, 
                         repr_pythonversion()))
 
-
-
-import py
-
 class CollectonlyReporter(BaseReporter):
     INDENT = "  "
 
@@ -372,7 +367,7 @@
             sys.executable, repr_pythonversion(sys.version_info))
         assert s.find(expect) != -1
 
-    def test_pass_skip_fail(self):
+    def test_pass_skip_fail(self, linecomp):
         modcol = self.getmodulecol("""
             import py
             def test_ok():
@@ -391,7 +386,7 @@
         s = popvalue(stringio)
         assert s.find("test_pass_skip_fail.py .sF") != -1
         rep.processevent(event.TestrunFinish())
-        assert_stringio_contains_lines(stringio, [
+        linecomp.assert_contains_lines(stringio, [
             "    def test_func():",
             ">       assert 0",
             "E       assert 0",
@@ -548,7 +543,7 @@
         print s
         assert s.find("test_show_path_before_running_test.py") != -1
 
-    def test_keyboard_interrupt(self, verbose=False):
+    def pseudo_keyboard_interrupt(self, verbose=False):
         modcol = self.getmodulecol("""
             def test_foobar():
                 assert 0
@@ -584,8 +579,11 @@
         see_details = "raise KeyboardInterrupt   # simulating the user" in text
         assert see_details == verbose
 
+    def test_keyboard_interrupt(self):
+        self.pseudo_keyboard_interrupt()
+        
     def test_verbose_keyboard_interrupt(self):
-        self.test_keyboard_interrupt(verbose=True)
+        self.pseudo_keyboard_interrupt(verbose=True)
 
 class TestCollectonly(suptest.InlineCollection):
     def test_collectonly_basic(self):

Modified: py/branch/pytestplugin/py/test/plugin/pytest_tmpdir.py
==============================================================================
--- py/branch/pytestplugin/py/test/plugin/pytest_tmpdir.py	(original)
+++ py/branch/pytestplugin/py/test/plugin/pytest_tmpdir.py	Wed Jan 28 15:35:54 2009
@@ -14,12 +14,6 @@
         to test functions and methods. 
     """ 
     def pytest_pyitemexecute_arg(self, pyfuncitem, argname):
-        """ return (value, finalizer) tuple or None. 
-            
-            the value will be provided to the test function. 
-            the finalizer (if not None) will be called after the test 
-            function has been executed (i.e. pyfuncitem.execute() returns). 
-        """ 
         if argname == "tmpdir":
             basename = "_".join(pyfuncitem.listnames())
             # move to config 

Modified: py/branch/pytestplugin/py/test/pmanage.py
==============================================================================
--- py/branch/pytestplugin/py/test/pmanage.py	(original)
+++ py/branch/pytestplugin/py/test/pmanage.py	Wed Jan 28 15:35:54 2009
@@ -24,6 +24,7 @@
         else:
             self.trace("instantiating plugin: %s" %(pluginclass,))
         self._plugins[name] = plugin
+        return plugin 
 
     def trace(self, msg): 
         if DEBUG:
@@ -31,7 +32,7 @@
 
     def import_plugin(self, importspec):
         if not isinstance(importspec, basestring):
-           self.addpluginclass(importspec)
+           return self.addpluginclass(importspec)
         else:
             lastpart = importspec.split(".")[-1]
             modprefix = "pytest_"
@@ -44,8 +45,9 @@
                 mod = __import__("py.__.test.plugin.%s" %(importspec), None, None, '__doc__')
             clsname = lastpart[len(modprefix):].capitalize()
             pluginclass = getattr(mod, clsname) 
+            result = self.addpluginclass(pluginclass)
             self.consider_module(mod)
-            self.addpluginclass(pluginclass)
+            return result
 
     def getplugin(self, pname):
         return self._plugins[pname.lower()] 
@@ -58,10 +60,6 @@
             if spec:
                 self.import_plugin(spec) 
 
-    def registerplugins(self, conftestmodules):
-        for mod in conftestmodules:
-            self.consider_module(mod)
-
     #
     # API for interacting with registered and instantiated plugin objects 
     #

Modified: py/branch/pytestplugin/py/test/pycollect.py
==============================================================================
--- py/branch/pytestplugin/py/test/pycollect.py	(original)
+++ py/branch/pytestplugin/py/test/pycollect.py	Wed Jan 28 15:35:54 2009
@@ -164,7 +164,7 @@
     def _importtestmodule(self):
         # we assume we are only called once per module 
         mod = self.fspath.pyimport()
-        print "imported test module", mod
+        #print "imported test module", mod
         self._config.pluginmanager.consider_module(mod)
         return mod
 
@@ -354,9 +354,10 @@
             if argfinalizer is not None:
                 self._argfinalizers.append(argfinalizer)
         else:
-            self._config.pluginmanager.trace(
-                "could not find argument %r, plugins=%r" %(
-                argname,self._config.pluginmanager._plugins))
+            #self._config.pluginmanager.trace(
+            #    "could not find argument %r, plugins=%r" %(
+            #    argname,self._config.pluginmanager._plugins))
+            raise TypeError("could not provide funcargument %r" %(argname,))
 
     def __eq__(self, other):
         try:

Modified: py/branch/pytestplugin/py/test/testing/test_conftesthandle.py
==============================================================================
--- py/branch/pytestplugin/py/test/testing/test_conftesthandle.py	(original)
+++ py/branch/pytestplugin/py/test/testing/test_conftesthandle.py	Wed Jan 28 15:35:54 2009
@@ -16,6 +16,16 @@
         conftest.setinitial([self.basedir.join("adir")])
         assert conftest.rget("a") == 1
 
+    def test_onimport(self):
+        l = []
+        conftest = Conftest(onimport=l.append)
+        conftest.setinitial([self.basedir.join("adir")])
+        assert len(l) == 2 # default + the one 
+        assert conftest.rget("a") == 1
+        assert conftest.rget("b", self.basedir.join("adir", "b")) == 2
+        assert len(l) == 3
+        
+
     def test_immediate_initialiation_and_incremental_are_the_same(self):
         conftest = Conftest()
         snap0 = len(conftest._path2confmods)

Modified: py/branch/pytestplugin/py/test/testing/test_pmanage.py
==============================================================================
--- py/branch/pytestplugin/py/test/testing/test_pmanage.py	(original)
+++ py/branch/pytestplugin/py/test/testing/test_pmanage.py	Wed Jan 28 15:35:54 2009
@@ -86,17 +86,6 @@
         finally:
             sys.path.remove(str(self.tmpdir))
 
-    def test_register_plugins(self):
-        pm = PluginManager()
-        sys.path.insert(0, str(self.tmpdir))
-        try:
-            self.tmpdir.join("pytest_rplug.py").write("class Rplug: pass")
-            mod = py.std.new.module("temp")
-            mod.pytest_plugins = ["pytest_rplug"]
-            pm.registerplugins([mod])
-            assert pm.getplugin("rplug").__class__.__name__ == "Rplug"
-        finally:
-            sys.path.remove(str(self.tmpdir))
 
     def test_addpluginclass(self):
         pm = PluginManager()



More information about the pytest-commit mailing list