2 new changesets in pytest: http://bitbucket.org/hpk42/pytest/changeset/d7cafb762307/ changeset: r2142:d7cafb762307 user: hpk42 date: 2011-01-18 12:47:31 summary: fix a pypy related regression - re-allow self.NAME style collection tree customization affected #: 3 files (1.3 KB)
--- a/_pytest/main.py Fri Jan 14 13:30:36 2011 +0100 +++ b/_pytest/main.py Tue Jan 18 12:47:31 2011 +0100 @@ -152,6 +152,7 @@ Module = compatproperty("Module") Class = compatproperty("Class") + Instance = compatproperty("Instance") Function = compatproperty("Function") File = compatproperty("File") Item = compatproperty("Item") --- a/_pytest/python.py Fri Jan 14 13:30:36 2011 +0100 +++ b/_pytest/python.py Tue Jan 18 12:47:31 2011 +0100 @@ -73,7 +73,7 @@ if collector._istestclasscandidate(name, obj): #if hasattr(collector.obj, 'unittest'): # return # we assume it's a mixin class for a TestCase derived one - return Class(name, parent=collector) + return collector.Class(name, parent=collector) elif collector.funcnamefilter(name) and hasattr(obj, '__call__'): if is_generator(obj): return Generator(name, parent=collector) @@ -160,7 +160,7 @@ for prefix in self.config.getini("python_functions"): if name.startswith(prefix): return True - + def classnamefilter(self, name): for prefix in self.config.getini("python_classes"): if name.startswith(prefix): @@ -214,11 +214,11 @@ plugins = self.getplugins() + extra gentesthook.pcall(plugins, metafunc=metafunc) if not metafunc._calls: - return Function(name, parent=self) + return self.Function(name, parent=self) l = [] for callspec in metafunc._calls: subname = "%s[%s]" %(name, callspec.id) - function = Function(name=subname, parent=self, + function = self.Function(name=subname, parent=self, callspec=callspec, callobj=funcobj, keywords={callspec.id:True}) l.append(function) return l @@ -272,7 +272,7 @@ class Class(PyCollectorMixin, pytest.Collector): def collect(self): - return [Instance(name="()", parent=self)] + return [self.Instance(name="()", parent=self)] def setup(self): setup_class = getattr(self.obj, 'setup_class', None) @@ -394,7 +394,7 @@ if name in seen: raise ValueError("%r generated tests with non-unique name %r" %(self, name)) seen[name] = True - l.append(Function(name, self, args=args, callobj=call)) + l.append(self.Function(name, self, args=args, callobj=call)) return l def getcallargs(self, obj): @@ -528,10 +528,10 @@ 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. - + :arg funcargs: argument keyword dictionary used when invoking the test function. - + :arg id: used for reporting and identification purposes. If you don't supply an `id` the length of the currently list of calls to the test function will be used. @@ -562,7 +562,7 @@ class LookupError(LookupError): """ error on performing funcarg request. """ - + def __init__(self, pyfuncitem): self._pyfuncitem = pyfuncitem if hasattr(pyfuncitem, '_requestparam'): @@ -590,7 +590,7 @@ def module(self): """ module where the test function was collected. """ return self._pyfuncitem.getparent(pytest.Module).obj - + @property def cls(self): """ class (can be None) where the test function was collected. """ @@ -606,7 +606,7 @@ def config(self): """ the pytest config object associated with this request. """ return self._pyfuncitem.config - + @property def fspath(self): """ the file system path of the test module which collected this test. """ @@ -780,7 +780,7 @@ def raises(ExpectedException, *args, **kwargs): """ assert that a code block/function call raises @ExpectedException and raise a failure exception otherwise. - + If using Python 2.5 or above, you may use this function as a context manager:: @@ -803,7 +803,7 @@ A third possibility is to use a string which which will be executed:: - + >>> raises(ZeroDivisionError, "f(0)") <ExceptionInfo ...> """ @@ -852,3 +852,4 @@ pytest.fail("DID NOT RAISE") self.excinfo.__init__(tp) return issubclass(self.excinfo.type, self.ExpectedException) + --- a/testing/test_python.py Fri Jan 14 13:30:36 2011 +0100 +++ b/testing/test_python.py Tue Jan 18 12:47:31 2011 +0100 @@ -1280,3 +1280,49 @@ result.stdout.fnmatch_lines([ "*2 passed*", ]) + +def test_collector_attributes(testdir): + testdir.makeconftest(""" + import pytest + def pytest_pycollect_makeitem(collector): + assert collector.Function == pytest.Function + assert collector.Class == pytest.Class + assert collector.Instance == pytest.Instance + assert collector.Module == pytest.Module + """) + testdir.makepyfile(""" + def test_hello(): + pass + """) + result = testdir.runpytest() + result.stdout.fnmatch_lines([ + "*1 passed*", + ]) + +def test_customize_through_attributes(testdir): + testdir.makeconftest(""" + import pytest + class MyFunction(pytest.Function): + pass + class MyInstance(pytest.Instance): + Function = MyFunction + class MyClass(pytest.Class): + Instance = MyInstance + + def pytest_pycollect_makeitem(collector, name, obj): + if name.startswith("MyTestClass"): + return MyClass(name, parent=collector) + """) + testdir.makepyfile(""" + class MyTestClass: + def test_hello(self): + pass + """) + result = testdir.runpytest("--collectonly") + result.stdout.fnmatch_lines([ + "*MyClass*", + "*MyInstance*", + "*MyFunction*test_hello*", + ]) + + http://bitbucket.org/hpk42/pytest/changeset/88c0e00cfe8b/ changeset: r2143:88c0e00cfe8b user: hpk42 date: 2011-01-18 12:51:21 summary: refine and unify initial capturing - now works also if the logging module is already used from an early-loaded conftest.py file (prior to option parsing) affected #: 6 files (1.7 KB) --- a/CHANGELOG Tue Jan 18 12:47:31 2011 +0100 +++ b/CHANGELOG Tue Jan 18 12:51:21 2011 +0100 @@ -1,6 +1,9 @@ Changes between 2.0.0 and 2.0.1.devX ---------------------------------------------- +- refine and unify initial capturing so that it works nicely + even if the logging module is used on an early-loaded conftest.py + file or plugin. - fix issue12 - show plugin versions with "--version" and "--traceconfig" and also document how to add extra information to reporting test header --- a/_pytest/capture.py Tue Jan 18 12:47:31 2011 +0100 +++ b/_pytest/capture.py Tue Jan 18 12:51:21 2011 +0100 @@ -19,10 +19,8 @@ if content: repr.addsection("Captured std%s" % secname, content.rstrip()) -def pytest_configure(config): - config.pluginmanager.register(CaptureManager(), 'capturemanager') - def pytest_unconfigure(config): + # registered in config.py during early conftest.py loading capman = config.pluginmanager.getplugin('capturemanager') while capman._method2capture: name, cap = capman._method2capture.popitem() @@ -67,6 +65,14 @@ else: raise ValueError("unknown capturing method: %r" % method) + def _getmethod_preoptionparse(self, args): + if '-s' in args or "--capture=no" in args: + return "no" + elif hasattr(os, 'dup') and '--capture=sys' not in args: + return "fd" + else: + return "sys" + def _getmethod(self, config, fspath): if config.option.capture: method = config.option.capture --- a/_pytest/config.py Tue Jan 18 12:47:31 2011 +0100 +++ b/_pytest/config.py Tue Jan 18 12:51:21 2011 +0100 @@ -34,7 +34,7 @@ def getgroup(self, name, description="", after=None): """ get (or create) a named option Group. - + :name: unique name of the option group. :description: long description for --help output. :after: name of other group, used for ordering --help output. @@ -270,13 +270,16 @@ def _setinitialconftest(self, args): # capture output during conftest init (#issue93) - name = hasattr(os, 'dup') and 'StdCaptureFD' or 'StdCapture' - cap = getattr(py.io, name)() + from _pytest.capture import CaptureManager + capman = CaptureManager() + self.pluginmanager.register(capman, 'capturemanager') + # will be unregistered in capture.py's unconfigure() + capman.resumecapture(capman._getmethod_preoptionparse(args)) try: try: self._conftest.setinitial(args) finally: - out, err = cap.reset() + out, err = capman.suspendcapture() # logging might have got it except: sys.stdout.write(out) sys.stderr.write(err) @@ -417,7 +420,7 @@ if 'pytest' in iniconfig.sections: return iniconfig['pytest'] return {} - + def findupwards(current, basename): current = py.path.local(current) while 1: --- a/pytest.py Tue Jan 18 12:47:31 2011 +0100 +++ b/pytest.py Tue Jan 18 12:51:21 2011 +0100 @@ -1,7 +1,7 @@ """ unit and functional testing with Python. """ -__version__ = '2.0.1.dev8' +__version__ = '2.0.1.dev9' __all__ = ['main'] from _pytest.core import main, UsageError, _preloadplugins --- a/setup.py Tue Jan 18 12:47:31 2011 +0100 +++ b/setup.py Tue Jan 18 12:51:21 2011 +0100 @@ -22,7 +22,7 @@ name='pytest', description='py.test: simple powerful testing with Python', long_description = long_description, - version='2.0.1.dev8', + version='2.0.1.dev9', url='http://pytest.org', license='MIT license', platforms=['unix', 'linux', 'osx', 'cygwin', 'win32'], @@ -67,4 +67,4 @@ return {'console_scripts': l} if __name__ == '__main__': - main() \ No newline at end of file + main() --- a/testing/test_capture.py Tue Jan 18 12:47:31 2011 +0100 +++ b/testing/test_capture.py Tue Jan 18 12:51:21 2011 +0100 @@ -325,6 +325,40 @@ ]) assert 'operation on closed file' not in result.stderr.str() + def test_conftestlogging_is_shown(self, testdir): + testdir.makeconftest(""" + import logging + logging.basicConfig() + logging.warn("hello435") + """) + # make sure that logging is still captured in tests + result = testdir.runpytest("-s", "-p", "no:capturelog") + assert result.ret == 0 + result.stderr.fnmatch_lines([ + "WARNING*hello435*", + ]) + assert 'operation on closed file' not in result.stderr.str() + + def test_conftestlogging_and_test_logging(self, testdir): + testdir.makeconftest(""" + import logging + logging.basicConfig() + """) + # make sure that logging is still captured in tests + p = testdir.makepyfile(""" + def test_hello(): + import logging + logging.warn("hello433") + assert 0 + """) + result = testdir.runpytest(p, "-p", "no:capturelog") + assert result.ret != 0 + result.stdout.fnmatch_lines([ + "WARNING*hello433*", + ]) + assert 'something' not in result.stderr.str() + assert 'operation on closed file' not in result.stderr.str() + class TestCaptureFuncarg: def test_std_functional(self, testdir): Repository URL: https://bitbucket.org/hpk42/pytest/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. _______________________________________________ py-svn mailing list py-svn@codespeak.net http://codespeak.net/mailman/listinfo/py-svn