diff --git a/py/test/collect.py b/py/test/collect.py index cdfb982ba..d2041a357 100644 --- a/py/test/collect.py +++ b/py/test/collect.py @@ -120,7 +120,7 @@ class Node(object): #self.__init__(name=name, parent=parent) def __repr__(self): - if self._config.option.debug: + if getattr(self._config.option, 'debug', False): return "<%s %r %0x>" %(self.__class__.__name__, getattr(self, 'name', None), id(self)) else: @@ -153,6 +153,24 @@ class Node(object): def teardown(self): pass + def _memoizedcall(self, attrname, function): + exattrname = "_ex_" + attrname + failure = getattr(self, exattrname, None) + if failure is not None: + raise failure[0], failure[1], failure[2] + if hasattr(self, attrname): + return getattr(self, attrname) + try: + res = function() + except (KeyboardInterrupt, SystemExit): + raise + except: + failure = py.std.sys.exc_info() + setattr(self, exattrname, failure) + raise + setattr(self, attrname, res) + return res + def listchain(self): """ return list of all parent collectors up to self. """ l = [self] @@ -173,7 +191,7 @@ class Node(object): if name: next = cur.join(name) if next is None: - existingnames = cur.listdir() + existingnames = [x.name for x in self._memocollect()] msg = ("Collector %r does not have name %r " "existing names are: %s" % (cur, name, existingnames)) @@ -262,9 +280,8 @@ class Node(object): class Collector(Node): """ - Collector instances generate children through - their listdir() and join() methods and thus - form a tree. attributes:: + Collector instances create children through collect() + and thus iteratively build a tree. attributes:: parent: attribute pointing to the parent collector (or None if this is the root collector) @@ -274,31 +291,60 @@ class Collector(Node): Module = configproperty('Module') DoctestFile = configproperty('DoctestFile') - def run(self): - """ deprecated: use listdir(). """ - py.std.warnings.warn("deprecated: use listdir()", category=DeprecationWarning) - return self.listdir() - - def multijoin(self, namelist): - """ return a list of colitems for the given namelist. """ - return [self.join(name) for name in namelist] - - def listdir(self): - """ returns a list of names available from this collector. - You can return an empty list. Callers of this method - must take care to catch exceptions properly. - """ - raise NotImplementedError("abstract") - - def join(self, name): - """ return a child collector or item for the given name. - If the return value is None there is no such child. + def collect(self): + """ returns a list of children (items and collectors) + for this collection node. """ raise NotImplementedError("abstract") def repr_failure(self, excinfo, outerr): + """ represent a failure. """ return self._repr_failure_py(excinfo, outerr) + def _memocollect(self): + """ internal helper method to cache results of calling collect(). """ + return self._memoizedcall('_collected', self.collect) + + # ********************************************************************** + # DEPRECATED METHODS + # ********************************************************************** + + def _deprecated_collect(self): + # avoid recursion: + # collect -> _deprecated_collect -> custom run() -> + # super().run() -> collect + attrname = '_depcollectentered' + if hasattr(self, attrname): + return + setattr(self, attrname, True) + method = getattr(self.__class__, 'run', None) + if method is not None and method != Collector.run: + warnoldcollect() + names = self.run() + return filter(None, [self.join(name) for name in names]) + + def run(self): + """ DEPRECATED: returns a list of names available from this collector. + You can return an empty list. Callers of this method + must take care to catch exceptions properly. + """ + warnoldcollect() + return [colitem.name for colitem in self._memocollect()] + + def join(self, name): + """ DEPRECATED: return a child collector or item for the given name. + If the return value is None there is no such child. + """ + warnoldcollect() + for colitem in self._memocollect(): + if colitem.name == name: + return colitem + + def multijoin(self, namelist): + """ DEPRECATED: return a list of colitems for the given namelist. """ + warnoldcollect() + return [self.join(name) for name in namelist] + class FSCollector(Collector): def __init__(self, fspath, parent=None, config=None): fspath = py.path.local(fspath) @@ -336,49 +382,53 @@ class FSCollector(Collector): class Directory(FSCollector): - def filefilter(self, path): - if path.check(file=1): - b = path.purebasename - ext = path.ext - return (b.startswith('test_') or - b.endswith('_test')) and ext in ('.txt', '.py') - def recfilter(self, path): if path.check(dir=1, dotfile=0): return path.basename not in ('CVS', '_darcs', '{arch}') - def listdir(self): - files = [] - dirs = [] - for p in self.fspath.listdir(): - if self.filefilter(p): - files.append(p.basename) - elif self.recfilter(p): - dirs.append(p.basename) - files.sort() - dirs.sort() - return files + dirs + def collect(self): + l = self._deprecated_collect() + if l is not None: + return l + l = [] + for path in self.fspath.listdir(): # listdir() returns sorted order + res = self.consider(path, usefilters=True) + if res is not None: + l.append(res) + return l + + def consider(self, path, usefilters=True): + print "checking", path + if path.check(file=1): + return self.consider_file(path, usefilters=usefilters) + elif path.check(dir=1): + return self.consider_dir(path, usefilters=usefilters) + + def consider_file(self, path, usefilters=True): + ext = path.ext + pb = path.purebasename + if not usefilters or pb.startswith("test_") or pb.endswith("_test"): + if ext == ".py": + return self.Module(path, parent=self) + elif ext == ".txt": + return self.DoctestFile(path, parent=self) + + def consider_dir(self, path, usefilters=True): + if not usefilters or self.recfilter(path): + # not use self.Directory here as + # dir/conftest.py shall be able to + # define Directory(dir) already + Directory = self._config.getvalue('Directory', path) + return Directory(path, parent=self) + + # ********************************************************************** + # DEPRECATED METHODS + # ********************************************************************** def join(self, name): - name2items = self.__dict__.setdefault('_name2items', {}) - try: - res = name2items[name] - except KeyError: - p = self.fspath.join(name) - res = None - if p.check(file=1): - if p.ext == '.py': - res = self.Module(p, parent=self) - elif p.ext == '.txt': - res = self.DoctestFile(p, parent=self) - elif p.check(dir=1): - # not use self.Directory here as - # dir/conftest.py shall be able to - # define Directory(dir) already - Directory = self._config.getvalue('Directory', p) - res = Directory(p, parent=self) - name2items[name] = res - return res + """ get a child collector or item without using filters. """ + p = self.fspath.join(name) + return self.consider(p, usefilters=False) from py.__.test.runner import basic_run_report, forked_run_report class Item(Node): @@ -388,6 +438,24 @@ class Item(Node): return forked_run_report return basic_run_report + def _deprecated_testexecution(self): + if self.__class__.run != Item.run: + warnoldtestrun() + self.run() + return True + elif self.__class__.execute != Item.execute: + warnoldtestrun() + self.execute(self.obj, *self._args) + return True + + def run(self): + warnoldtestrun() + return self.execute(self.obj, *self._args) + + def execute(self, obj, *args): + warnoldtestrun() + return obj(*args) + def repr_metainfo(self): try: return self.ReprMetaInfo(self.fspath, modpath=self.__class__.__name__) @@ -395,7 +463,7 @@ class Item(Node): code = py.code.Code(self.execute) return self.ReprMetaInfo(code.path, code.firstlineno) - def execute(self): + def runtest(self): """ execute this test item.""" @@ -417,3 +485,13 @@ def getrelpath(curdir, dest): return target except AttributeError: return dest + + +def depwarn(msg): + py.std.warnings.warn(msg, DeprecationWarning) + +def warnoldcollect(): + return depwarn("implement collector.collect() instead of collector.run() and collector.join()") + +def warnoldtestrun(): + return depwarn("implement item.runtest() instead of item.run() and item.execute()") diff --git a/py/test/compat.py b/py/test/compat.py index 80c01d4b5..d44482ec9 100644 --- a/py/test/compat.py +++ b/py/test/compat.py @@ -6,7 +6,7 @@ class TestCaseUnit(Function): """ compatibility Unit executor for TestCase methods honouring setUp and tearDown semantics. """ - def execute(self, _deprecated=None): + def runtest(self, _deprecated=None): boundmethod = self.obj instance = boundmethod.im_self instance.setUp() diff --git a/py/test/dsession/testing/basetest.py b/py/test/dsession/testing/basetest.py index 5b07bdf6c..c45c979d0 100644 --- a/py/test/dsession/testing/basetest.py +++ b/py/test/dsession/testing/basetest.py @@ -15,7 +15,7 @@ class DirSetup(object): class BasicRsessionTest(object): def setup_class(cls): - path = getexamplefile("funcexamples.py") + path = getexamplefile("test_funcexamples.py") cls.config = py.test.config._reparse([path.dirpath()]) cls.modulecol = cls.config.getfsnode(path) @@ -23,7 +23,7 @@ class BasicRsessionTest(object): self.session = self.config.initsession() def getfunc(self, name): - funcname = "func" + name + funcname = "test_func" + name col = self.modulecol.join(funcname) assert col is not None, funcname return col diff --git a/py/test/dsession/testing/test_dsession.py b/py/test/dsession/testing/test_dsession.py index eba837403..ca9e9239c 100644 --- a/py/test/dsession/testing/test_dsession.py +++ b/py/test/dsession/testing/test_dsession.py @@ -157,7 +157,7 @@ class TestDSession(InlineCollection): def test_fail(): x """) - item1, item2 = [modcol.join(x) for x in modcol.listdir()] + item1, item2 = modcol.collect() # setup a session with two hosts session = DSession(item1._config) @@ -295,7 +295,7 @@ class TestDSession(InlineCollection): modcol._config.option.keyword = "nothing" dsel = session.filteritems([modcol]) assert dsel == [modcol] - items = [modcol.join(x) for x in modcol.listdir()] + items = modcol.collect() events = [] ; session.bus.subscribe(events.append) remaining = session.filteritems(items) assert remaining == [] diff --git a/py/test/outcome.py b/py/test/outcome.py index f3c5d80a2..81b5e6e77 100644 --- a/py/test/outcome.py +++ b/py/test/outcome.py @@ -118,7 +118,7 @@ def deprecated_call(func, *args, **kwargs): warningmodule.warn_explicit = warn_explicit warningmodule.warn = warn if not l: - print warningmodule + #print warningmodule raise AssertionError("%r did not produce DeprecationWarning" %(func,)) return ret diff --git a/py/test/pycollect.py b/py/test/pycollect.py index c07a07fed..e35c93354 100644 --- a/py/test/pycollect.py +++ b/py/test/pycollect.py @@ -18,6 +18,7 @@ a tree of collectors and test items that this modules provides:: """ import py from py.__.test.collect import Collector, FSCollector, Item, configproperty +from py.__.test.collect import warnoldcollect class PyobjMixin(object): def obj(): @@ -96,6 +97,15 @@ class PyCollectorMixin(PyobjMixin, Collector): def classnamefilter(self, name): return name.startswith('Test') + def collect(self): + l = self._deprecated_collect() + if l is not None: + return l + name2items = self._buildname2items() + colitems = name2items.values() + colitems.sort() + return colitems + def _buildname2items(self): # NB. we avoid random getattrs and peek in the __dict__ instead d = {} @@ -113,67 +123,37 @@ class PyCollectorMixin(PyobjMixin, Collector): d[name] = res return d + def _deprecated_join(self, name): + if self.__class__.join != py.test.collect.Collector.join: + warnoldcollect() + return self.join(name) + def makeitem(self, name, obj, usefilters=True): if (not usefilters or self.classnamefilter(name)) and \ py.std.inspect.isclass(obj): + res = self._deprecated_join(name) + if res is not None: + return res return self.Class(name, parent=self) elif (not usefilters or self.funcnamefilter(name)) and callable(obj): + res = self._deprecated_join(name) + if res is not None: + return res if obj.func_code.co_flags & 32: # generator function return self.Generator(name, parent=self) else: return self.Function(name, parent=self) - def _prepare(self): - if not hasattr(self, '_name2items'): - ex = getattr(self, '_name2items_exception', None) - if ex is not None: - raise ex[0], ex[1], ex[2] - try: - self._name2items = self._buildname2items() - except (SystemExit, KeyboardInterrupt): - raise - except: - self._name2items_exception = py.std.sys.exc_info() - raise - - def listdir(self): - self._prepare() - itemlist = self._name2items.values() - itemlist.sort() - return [x.name for x in itemlist] - - def join(self, name): - self._prepare() - return self._name2items.get(name, None) - class Module(FSCollector, PyCollectorMixin): _stickyfailure = None - def listdir(self): + def collect(self): if getattr(self.obj, 'disabled', 0): return [] - return super(Module, self).listdir() + return super(Module, self).collect() - def join(self, name): - res = super(Module, self).join(name) - if res is None: - attr = getattr(self.obj, name, None) - if attr is not None: - res = self.makeitem(name, attr, usefilters=False) - return res - def _getobj(self): - failure = self._stickyfailure - if failure is not None: - raise failure[0], failure[1], failure[2] - try: - self._obj = obj = self.fspath.pyimport() - except KeyboardInterrupt: - raise - except: - self._stickyfailure = py.std.sys.exc_info() - raise - return self._obj + return self._memoizedcall('_obj', self.fspath.pyimport) def setup(self): if not self._config.option.nomagic: @@ -191,14 +171,13 @@ class Module(FSCollector, PyCollectorMixin): class Class(PyCollectorMixin, Collector): - def listdir(self): + def collect(self): if getattr(self.obj, 'disabled', 0): return [] - return ["()"] - - def join(self, name): - assert name == '()' - return self.Instance(name, self) + l = self._deprecated_collect() + if l is not None: + return l + return [self.Instance(name="()", parent=self)] def setup(self): setup_class = getattr(self.obj, 'setup_class', None) @@ -215,7 +194,6 @@ class Class(PyCollectorMixin, Collector): def _getsortvalue(self): return self.getfslineno() - class Instance(PyCollectorMixin, Collector): def _getobj(self): return self.parent.obj() @@ -226,6 +204,10 @@ class Instance(PyCollectorMixin, Collector): return [] Function = property(Function) + #def __repr__(self): + # return "<%s of '%s'>" %(self.__class__.__name__, + # self.parent.obj.__name__) + def newinstance(self): self.obj = self._getobj() return self.obj @@ -278,24 +260,19 @@ class FunctionMixin(PyobjMixin): shortfailurerepr = "F" class Generator(FunctionMixin, PyCollectorMixin, Collector): - def listdir(self): - self._prepare() - itemlist = self._name2items - return [itemlist["[%d]" % num].name for num in xrange(len(itemlist))] - - def _buildname2items(self): - d = {} - # XXX test generators are collectors yet participate in - # the test-item setup and teardown protocol - # if not for this we could probably avoid global setupstate + def collect(self): + # test generators are collectors yet participate in + # the test-item setup and teardown protocol. + # otherwise we could avoid global setupstate self._setupstate.prepare(self) + l = [] for i, x in py.builtin.enumerate(self.obj()): call, args = self.getcallargs(x) if not callable(call): raise TypeError("%r yielded non callable test %r" %(self.obj, call,)) name = "[%d]" % i - d[name] = self.Function(name, self, args=args, callobj=call) - return d + l.append(self.Function(name, self, args=args, callobj=call)) + return l def getcallargs(self, obj): if isinstance(obj, (tuple, list)): @@ -318,9 +295,10 @@ class Function(FunctionMixin, Item): if callobj is not _dummy: self._obj = callobj - def execute(self): + def runtest(self): """ execute the given test function. """ - self.obj(*self._args) + if not self._deprecated_testexecution(): + self.obj(*self._args) def __eq__(self, other): try: @@ -335,12 +313,9 @@ class Function(FunctionMixin, Item): return not self == other class DoctestFile(FSCollector): - def listdir(self): - return [self.fspath.basename] - - def join(self, name): - if name == self.fspath.basename: - return DoctestFileContent(name, self) + + def collect(self): + return [DoctestFileContent(self.fspath.basename, parent=self)] from py.__.code.excinfo import Repr, ReprFileLocation @@ -378,8 +353,9 @@ class DoctestFileContent(Item): else: return super(DoctestFileContent, self).repr_failure(excinfo, outerr) - def execute(self): - failed, tot = py.compat.doctest.testfile( - str(self.fspath), module_relative=False, - raise_on_error=True, verbose=0) + def runtest(self): + if not self._deprecated_testexecution(): + failed, tot = py.compat.doctest.testfile( + str(self.fspath), module_relative=False, + raise_on_error=True, verbose=0) diff --git a/py/test/report/testing/test_basereporter.py b/py/test/report/testing/test_basereporter.py index 3ab37957b..4a455dce5 100644 --- a/py/test/report/testing/test_basereporter.py +++ b/py/test/report/testing/test_basereporter.py @@ -86,10 +86,10 @@ def test_getmodpath_cases(): assert getmodpath(fcol) == expected for names in ( - 'mod.py test_f1 mod.test_f1', - 'mod.py TestA () test_m1 mod.TestA().test_m1', - 'mod.py test_g1 mod.test_g1', - 'mod.py test_g1 [0] mod.test_g1[0]', + 'test_mod.py test_f1 test_mod.test_f1', + 'test_mod.py TestA () test_m1 test_mod.TestA().test_m1', + 'test_mod.py test_g1 test_mod.test_g1', + 'test_mod.py test_g1 [0] test_mod.test_g1[0]', ): names = names.split() expected = names.pop() diff --git a/py/test/report/testing/test_collectonly.py b/py/test/report/testing/test_collectonly.py index 44d7fb53d..9a34984b3 100644 --- a/py/test/report/testing/test_collectonly.py +++ b/py/test/report/testing/test_collectonly.py @@ -15,7 +15,7 @@ class TestCollectonly(InlineCollection): indent = rep.indent rep.processevent(event.CollectionStart(modcol)) s = popvalue(stringio) - assert s == "" + assert s == "" item = modcol.join("test_func") rep.processevent(event.ItemStart(item)) @@ -34,7 +34,7 @@ class TestCollectonly(InlineCollection): cols = list(self.session.genitems([modcol])) assert len(cols) == 0 assert_stringio_contains_lines(stringio, """ - + !!! Skipped: 'nomod' !!! """) @@ -47,7 +47,7 @@ class TestCollectonly(InlineCollection): cols = list(self.session.genitems([modcol])) assert len(cols) == 0 assert_stringio_contains_lines(stringio, """ - + !!! ValueError: 0 !!! """) diff --git a/py/test/report/testing/test_terminal.py b/py/test/report/testing/test_terminal.py index ac601d3fe..6d6ebf1c7 100644 --- a/py/test/report/testing/test_terminal.py +++ b/py/test/report/testing/test_terminal.py @@ -70,7 +70,7 @@ class TestTerminal(InlineCollection): stringio = py.std.cStringIO.StringIO() rep = TerminalReporter(modcol._config, file=stringio) rep.processevent(event.TestrunStart()) - items = [modcol.join(x) for x in modcol.listdir()] + items = modcol.collect() for item in items: rep.processevent(event.ItemStart(item)) s = stringio.getvalue().strip() @@ -153,8 +153,7 @@ class TestTerminal(InlineCollection): """) stringio = py.std.cStringIO.StringIO() rep = TerminalReporter(modcol._config, file=stringio) - reports = [basic_run_report(modcol.join(x)) - for x in modcol.listdir()] + reports = [basic_run_report(x) for x in modcol.collect()] rep.processevent(event.LooponfailingInfo(reports, [modcol._config.topdir])) assert_stringio_contains_lines(stringio, [ "*test_looponfailingreport.py:2: assert 0", diff --git a/py/test/runner.py b/py/test/runner.py index b8c60fdb1..25f0f8483 100644 --- a/py/test/runner.py +++ b/py/test/runner.py @@ -68,7 +68,7 @@ class ItemRunner(RobustRun): def teardown(self): self.colitem._setupstate.teardown_exact(self.colitem) def execute(self): - self.colitem.execute() + self.colitem.runtest() def makereport(self, res, when, excinfo, outerr): if excinfo: kw = self.getkw(when, excinfo, outerr) @@ -84,7 +84,7 @@ class CollectorRunner(RobustRun): def teardown(self): pass def execute(self): - return [self.colitem.join(x) for x in self.colitem.listdir()] + return self.colitem._memocollect() def makereport(self, res, when, excinfo, outerr): if excinfo: kw = self.getkw(when, excinfo, outerr) diff --git a/py/test/testing/acceptance_test.py b/py/test/testing/acceptance_test.py index bbf76513e..060949f74 100644 --- a/py/test/testing/acceptance_test.py +++ b/py/test/testing/acceptance_test.py @@ -211,7 +211,7 @@ class TestPyTest(AcceptBase): """) result = self.runpytest(p1) assert_lines_contain_lines(result.outlines, [ - "test_fail.py F", + ".*test_fail.py F", "====* FAILURES *====", "____*____", "", @@ -242,7 +242,7 @@ class TestPyTest(AcceptBase): """) result = self.runpytest(p1) assert_lines_contain_lines(result.outlines, [ - "test_one.py .F", + ".*test_one.py .F", "====* FAILURES *====", "____*____", "*test_one.py:8: ValueError", diff --git a/py/test/testing/setupdata.py b/py/test/testing/setupdata.py index b3113a123..2fa199ce1 100644 --- a/py/test/testing/setupdata.py +++ b/py/test/testing/setupdata.py @@ -81,7 +81,7 @@ namecontent = { 'failingimport.py': "import gruetzelmuetzel\n", - 'mod.py': """ + 'test_mod.py': """ class TestA: def test_m1(self): pass @@ -91,7 +91,7 @@ namecontent = { yield lambda x: None, 42 """, - 'filetest.py': """ + 'file_test.py': """ def test_one(): assert 42 == 43 @@ -125,60 +125,45 @@ namecontent = { pass """, - 'funcexamples.py': """ + 'test_funcexamples.py': """ import py import time - def funcpassed(): + def test_funcpassed(): pass - def funcfailed(): + def test_funcfailed(): raise AssertionError("hello world") - def funcskipped(): + def test_funcskipped(): py.test.skip("skipped") - def funcprint(): + def test_funcprint(): print "samfing" - def funcprinterr(): + def test_funcprinterr(): print >>py.std.sys.stderr, "samfing" - def funcprintfail(): + def test_funcprintfail(): print "samfing elz" asddsa - def funcexplicitfail(): + def test_funcexplicitfail(): py.test.fail("3") - def funcraisesfails(): + def test_funcraisesfails(): py.test.raises(ValueError, lambda: 123) - def funcoptioncustom(): + def test_funcoptioncustom(): assert py.test.config.getvalue("custom") - def funchang(): + def test_funchang(): import time time.sleep(1000) - def funckill15(): + def test_funckill15(): import os os.kill(os.getpid(), 15) """, - - 'test_generative.py': """ - from __future__ import generators # python2.2! - def func1(arg, arg2): - assert arg == arg2 - - def test_gen(): - yield func1, 17, 3*5 - yield func1, 42, 6*7 - - class TestGenMethods: - def test_gen(self): - yield func1, 17, 3*5 - yield func1, 42, 6*7 - """, 'docexample.txt': """ Aha!!!!!! @@ -186,56 +171,3 @@ namecontent = { """, } - -def setup_customconfigtest(tmpdir): - o = tmpdir.ensure('customconfigtest', dir=1) - o.ensure('conftest.py').write("""if 1: - import py - class MyFunction(py.test.collect.Function): - pass - class Directory(py.test.collect.Directory): - def filefilter(self, fspath): - return fspath.check(basestarts='check_', ext='.py') - class myfuncmixin: - Function = MyFunction - def funcnamefilter(self, name): - return name.startswith('check_') - - class Module(myfuncmixin, py.test.collect.Module): - def classnamefilter(self, name): - return name.startswith('CustomTestClass') - class Instance(myfuncmixin, py.test.collect.Instance): - pass - """) - checkfile = o.ensure('somedir', 'check_something.py') - checkfile.write("""if 1: - def check_func(): - assert 42 == 42 - class CustomTestClass: - def check_method(self): - assert 23 == 23 - """) - return checkfile - -def setup_non_python_dir(tmpdir): - o = tmpdir.ensure('customconfigtest_nonpython', dir=1) - o.ensure('conftest.py').write("""if 1: - import py - class CustomItem(py.test.collect.Item): - def run(self): - pass - - class Directory(py.test.collect.Directory): - def filefilter(self, fspath): - return fspath.check(basestarts='check_', ext='.txt') - def join(self, name): - if not name.endswith('.txt'): - return super(Directory, self).join(name) - p = self.fspath.join(name) - if p.check(file=1): - return CustomItem(p, parent=self) - """) - checkfile = o.ensure('somedir', 'moredir', 'check_something.txt') - return checkfile - - diff --git a/py/test/testing/suptest.py b/py/test/testing/suptest.py index 7ea4b508b..0202ce131 100644 --- a/py/test/testing/suptest.py +++ b/py/test/testing/suptest.py @@ -192,7 +192,7 @@ class InlineCollection(FileCreation): def getmodulecol(self, source, configargs=(), withsession=False): self.tmpdir.ensure("__init__.py") - kw = {self.tmpdir.basename: py.code.Source(source).strip()} + kw = {"test_" + self.tmpdir.basename: py.code.Source(source).strip()} path = self.makepyfile(**kw) self.config = self.parseconfig(path, *configargs) if withsession: @@ -204,7 +204,7 @@ class InlineCollection(FileCreation): def getitems(self, source): modulecol = self.getmodulecol(source) - return [modulecol.join(x) for x in modulecol.listdir()] + return modulecol.collect() def getitem(self, source, funcname="test_func"): modulecol = self.getmodulecol(source) diff --git a/py/test/testing/test_collect.py b/py/test/testing/test_collect.py index f0b37d8a9..f277e67dc 100644 --- a/py/test/testing/test_collect.py +++ b/py/test/testing/test_collect.py @@ -22,79 +22,9 @@ def setup_module(mod): mod.dummyconfig = DummyConfig() def test_collect_versus_item(): - path = setupdata.getexamplefile("filetest.py") - col = py.test.collect.Module(path, config=dummyconfig) - assert not isinstance(col, py.test.collect.Item) - item = col.join("test_one") - assert not hasattr(item, "join") - assert not isinstance(item, py.test.collect.Collector) - -def test_collector_deprecated_run_method(): - path = setupdata.getexamplefile("filetest.py") - col = py.test.collect.Module(path, config=dummyconfig) - res1 = py.test.deprecated_call(col.run) - res2 = col.listdir() - assert res1 == res2 - -def test_module_assertion_setup(): - path = setupdata.getexamplefile("filetest.py") - col = py.test.collect.Module(path, config=dummyconfig) - from py.__.magic import assertion - l = [] - py.magic.patch(assertion, "invoke", lambda: l.append(None)) - try: - col.setup() - finally: - py.magic.revert(assertion, "invoke") - x = l.pop() - assert x is None - py.magic.patch(assertion, "revoke", lambda: l.append(None)) - try: - col.teardown() - finally: - py.magic.revert(assertion, "revoke") - x = l.pop() - assert x is None - - -def test_failing_import_execfile(): - dest = setupdata.getexamplefile('failingimport.py') - col = py.test.collect.Module(dest, config=dummyconfig) - py.test.raises(ImportError, col.listdir) - py.test.raises(ImportError, col.listdir) - -def test_collect_listnames_and_back(): - path = setupdata.getexamplefile("filetest.py") - col1 = py.test.collect.Directory(path.dirpath().dirpath(), - config=dummyconfig) - col2 = col1.join(path.dirpath().basename) - col3 = col2.join(path.basename) - l = col3.listnames() - assert len(l) == 3 - x = col1._getitembynames(l[1:]) - assert x.name == "filetest.py" - l2 = x.listnames() - assert len(l2) == 3 - -def test_finds_tests(): - fn = setupdata.getexamplefile('filetest.py') - col = py.test.collect.Module(fn, config=dummyconfig) - l = col.listdir() - assert len(l) == 2 - assert l[0] == 'test_one' - assert l[1] == 'TestClass' - -def test_found_certain_testfiles(): - tmp = py.test.ensuretemp("found_certain_testfiles") - tmp.ensure('test_found.py') - tmp.ensure('found_test.py') - - col = py.test.collect.Directory(tmp, config=dummyconfig) - items = [col.join(x) for x in col.listdir()] - - assert len(items) == 2 - assert items[1].name == 'test_found.py' - assert items[0].name == 'found_test.py' + from py.__.test.collect import Collector, Item + assert not issubclass(Collector, Item) + assert not issubclass(Item, Collector) def test_ignored_certain_directories(): tmp = py.test.ensuretemp("ignore_certain_directories") @@ -107,80 +37,248 @@ def test_ignored_certain_directories(): tmp.ensure('test_found.py') col = py.test.collect.Directory(tmp, config=dummyconfig) - items = col.listdir() + items = col.collect() + names = [x.name for x in items] assert len(items) == 2 - assert 'normal' in items - assert 'test_found.py' in items + assert 'normal' in names + assert 'test_found.py' in names + +class TestCollect(suptest.InlineCollection): + def test_failing_import(self): + modcol = self.getmodulecol("import alksdjalskdjalkjals") + py.test.raises(ImportError, modcol.collect) + py.test.raises(ImportError, modcol.collect) + py.test.raises(ImportError, modcol.run) + + def test_syntax_error_in_module(self): + modcol = self.getmodulecol("this is a syntax error") + py.test.raises(SyntaxError, modcol.collect) + py.test.raises(SyntaxError, modcol.collect) + py.test.raises(SyntaxError, modcol.run) + + def test_listnames_and__getitembynames(self): + modcol = self.getmodulecol("pass") + names = modcol.listnames() + dircol = py.test.collect.Directory(modcol._config.topdir, config=modcol._config) + x = dircol._getitembynames(names) + assert modcol.name == x.name + assert modcol.name == x.name + + def test_found_certain_testfiles(self): + p1 = self.makepyfile(test_found = "pass", found_test="pass") + col = py.test.collect.Directory(p1.dirpath(), config=dummyconfig) + items = col.collect() + assert len(items) == 2 + assert items[1].name == 'test_found.py' + assert items[0].name == 'found_test.py' + + def test_disabled_class(self): + modcol = self.getmodulecol(""" + class TestClass: + disabled = True + def test_method(self): + pass + """) + l = modcol.collect() + assert len(l) == 1 + modcol = l[0] + assert isinstance(modcol, py.test.collect.Class) + assert not modcol.collect() + + def test_disabled_module(self): + modcol = self.getmodulecol(""" + disabled = True + def setup_module(mod): + raise ValueError + """) + assert not modcol.collect() + assert not modcol.run() + + def test_generative_functions(self): + modcol = self.getmodulecol(""" + def func1(arg, arg2): + assert arg == arg2 + + def test_gen(): + yield func1, 17, 3*5 + yield func1, 42, 6*7 + """) + colitems = modcol.collect() + assert len(colitems) == 1 + gencol = colitems[0] + assert isinstance(gencol, py.test.collect.Generator) + gencolitems = gencol.collect() + assert len(gencolitems) == 2 + assert isinstance(gencolitems[0], py.test.collect.Function) + assert isinstance(gencolitems[1], py.test.collect.Function) + assert gencolitems[0].name == '[0]' + assert gencolitems[0].obj.func_name == 'func1' + + def test_generative_methods(self): + modcol = self.getmodulecol(""" + def func1(arg, arg2): + assert arg == arg2 + class TestGenMethods: + def test_gen(self): + yield func1, 17, 3*5 + yield func1, 42, 6*7 + """) + gencol = modcol.collect()[0].collect()[0].collect()[0] + assert isinstance(gencol, py.test.collect.Generator) + gencolitems = gencol.collect() + assert len(gencolitems) == 2 + assert isinstance(gencolitems[0], py.test.collect.Function) + assert isinstance(gencolitems[1], py.test.collect.Function) + assert gencolitems[0].name == '[0]' + assert gencolitems[0].obj.func_name == 'func1' + + def test_module_assertion_setup(self): + modcol = self.getmodulecol("pass") + from py.__.magic import assertion + l = [] + py.magic.patch(assertion, "invoke", lambda: l.append(None)) + try: + modcol.setup() + finally: + py.magic.revert(assertion, "invoke") + x = l.pop() + assert x is None + py.magic.patch(assertion, "revoke", lambda: l.append(None)) + try: + modcol.teardown() + finally: + py.magic.revert(assertion, "revoke") + x = l.pop() + assert x is None + + def test_check_equality_and_cmp_basic(self): + modcol = self.getmodulecol(""" + def test_pass(): pass + def test_fail(): assert 0 + """) + fn1 = modcol.join("test_pass") + assert isinstance(fn1, py.test.collect.Function) + fn2 = modcol.join("test_pass") + assert isinstance(fn2, py.test.collect.Function) + + assert fn1 == fn2 + assert fn1 != modcol + assert cmp(fn1, fn2) == 0 + assert hash(fn1) == hash(fn2) + + fn3 = modcol.join("test_fail") + assert isinstance(fn3, py.test.collect.Function) + assert not (fn1 == fn3) + assert fn1 != fn3 + assert cmp(fn1, fn3) == -1 + + assert cmp(fn1, 10) == -1 + assert cmp(fn2, 10) == -1 + assert cmp(fn3, 10) == -1 + for fn in fn1,fn2,fn3: + assert fn != 3 + assert fn != modcol + assert fn != [1,2,3] + assert [1,2,3] != fn + assert modcol != fn + + def test_directory_file_sorting(self): + p1 = self.makepyfile(test_one="hello") + p1.dirpath().mkdir("x") + p1.dirpath().mkdir("dir1") + self.makepyfile(test_two="hello") + p1.dirpath().mkdir("dir2") + config = self.parseconfig() + col = config.getfsnode(p1.dirpath()) + names = [x.name for x in col.collect()] + assert names == ["dir1", "dir2", "test_one.py", "test_two.py", "x"] + + def test_collector_deprecated_run_method(self): + modcol = self.getmodulecol("pass") + res1 = py.test.deprecated_call(modcol.run) + res2 = modcol.collect() + assert res1 == [x.name for x in res2] + +class TestCustomConftests(suptest.InlineCollection): + def test_extra_python_files_and_functions(self): + self.makepyfile(conftest=""" + import py + class MyFunction(py.test.collect.Function): + pass + class Directory(py.test.collect.Directory): + def consider_file(self, path, usefilters=True): + if path.check(fnmatch="check_*.py"): + return self.Module(path, parent=self) + return super(Directory, self).consider_file(path, usefilters=usefilters) + class myfuncmixin: + Function = MyFunction + def funcnamefilter(self, name): + return name.startswith('check_') + class Module(myfuncmixin, py.test.collect.Module): + def classnamefilter(self, name): + return name.startswith('CustomTestClass') + class Instance(myfuncmixin, py.test.collect.Instance): + pass + """) + checkfile = self.makepyfile(check_file=""" + def check_func(): + assert 42 == 42 + class CustomTestClass: + def check_method(self): + assert 23 == 23 + """) + # check that directory collects "check_" files + config = self.parseconfig() + col = config.getfsnode(checkfile.dirpath()) + colitems = col.collect() + assert len(colitems) == 1 + assert isinstance(colitems[0], py.test.collect.Module) + + # check that module collects "check_" functions and methods + config = self.parseconfig(checkfile) + col = config.getfsnode(checkfile) + assert isinstance(col, py.test.collect.Module) + colitems = col.collect() + assert len(colitems) == 2 + funccol = colitems[0] + assert isinstance(funccol, py.test.collect.Function) + assert funccol.name == "check_func" + clscol = colitems[1] + assert isinstance(clscol, py.test.collect.Class) + colitems = clscol.collect()[0].collect() + assert len(colitems) == 1 + assert colitems[0].name == "check_method" + + def test_non_python_files(self): + self.makepyfile(conftest=""" + import py + class CustomItem(py.test.collect.Item): + def run(self): + pass + class Directory(py.test.collect.Directory): + def consider_file(self, fspath, usefilters=True): + if fspath.ext == ".xxx": + return CustomItem(fspath.basename, parent=self) + """) + checkfile = self._makefile(ext="xxx", hello="world") + self.makepyfile(x="") + self.maketxtfile(x="") + config = self.parseconfig() + dircol = config.getfsnode(checkfile.dirpath()) + colitems = dircol.collect() + assert len(colitems) == 1 + assert colitems[0].name == "hello.xxx" + assert colitems[0].__class__.__name__ == "CustomItem" + + item = config.getfsnode(checkfile) + assert item.name == "hello.xxx" + assert item.__class__.__name__ == "CustomItem" -def test_failing_import_directory(): - class MyDirectory(py.test.collect.Directory): - def filefilter(self, p): - return p.check(fnmatch='testspecial*.py') - filetest = setupdata.getexamplefile("testspecial_importerror.py") - mydir = MyDirectory(filetest.dirpath(), config=dummyconfig) - l = mydir.listdir() - assert len(l) == 1 - col = mydir.join(l[0]) - assert isinstance(col, py.test.collect.Module) - py.test.raises(ImportError, col.listdir) def test_module_file_not_found(): fn = tmpdir.join('nada','no') col = py.test.collect.Module(fn, config=dummyconfig) - py.test.raises(py.error.ENOENT, col.listdir) - -def test_syntax_error_in_module(): - modpath = setupdata.getexamplefile("syntax_error.py") - col = py.test.collect.Module(modpath, config=dummyconfig) - py.test.raises(SyntaxError, col.listdir) - -def test_disabled_class(): - p = setupdata.getexamplefile('disabled.py') - col = py.test.collect.Module(p, config=dummyconfig) - l = col.listdir() - assert len(l) == 1 - col = col.join(l[0]) - assert isinstance(col, py.test.collect.Class) - assert not col.listdir() - -def test_disabled_module(): - p = setupdata.getexamplefile("disabled_module.py") - col = py.test.collect.Module(p, config=dummyconfig) - l = col.listdir() - assert len(l) == 0 - -def test_generative_simple(): - tfile = setupdata.getexamplefile('test_generative.py') - col = py.test.collect.Module(tfile, config=dummyconfig) - l = col.listdir() - assert len(l) == 2 - l = col.multijoin(l) - - generator = l[0] - assert isinstance(generator, py.test.collect.Generator) - l2 = generator.listdir() - assert len(l2) == 2 - l2 = generator.multijoin(l2) - assert isinstance(l2[0], py.test.collect.Function) - assert isinstance(l2[1], py.test.collect.Function) - assert l2[0].name == '[0]' - assert l2[1].name == '[1]' - - assert l2[0].obj.func_name == 'func1' - - classlist = l[1].listdir() - assert len(classlist) == 1 - classlist = l[1].multijoin(classlist) - cls = classlist[0] - generator = cls.join(cls.listdir()[0]) - assert isinstance(generator, py.test.collect.Generator) - l2 = generator.listdir() - assert len(l2) == 2 - l2 = generator.multijoin(l2) - assert isinstance(l2[0], py.test.collect.Function) - assert isinstance(l2[1], py.test.collect.Function) - assert l2[0].name == '[0]' - assert l2[1].name == '[1]' + py.test.raises(py.error.ENOENT, col.collect) def test_order_of_execution_generator_same_codeline(): @@ -238,52 +336,6 @@ def test_order_of_execution_generator_different_codeline(): assert passed == 4 assert not skipped and not failed -def test_check_directory_ordered(): - tmpdir = py.test.ensuretemp("test_check_directory_ordered") - fnames = [] - for i in range(9, -1, -1): - x = tmpdir.ensure("xdir%d" %(i, ), dir=1) - fnames.append(x.basename) - for i in range(9, -1, -1): - x = tmpdir.ensure("test_file%d.py" % (i,)) - fnames.append(x.basename) - fnames.sort() - tmpdir.ensure('adir', dir=1) - fnames.insert(10, 'adir') - col = py.test.collect.Directory(tmpdir, config=dummyconfig) - names = col.listdir() - assert names == fnames - -def test_check_equality_and_cmp_basic(): - path = setupdata.getexamplefile("funcexamples.py") - col = py.test.collect.Module(path, config=dummyconfig) - fn1 = col.join("funcpassed") - assert isinstance(fn1, py.test.collect.Function) - fn2 = col.join("funcpassed") - assert isinstance(fn2, py.test.collect.Function) - - assert fn1 == fn2 - assert fn1 != col - assert cmp(fn1, fn2) == 0 - assert hash(fn1) == hash(fn2) - - fn3 = col.join("funcfailed") - assert isinstance(fn3, py.test.collect.Function) - assert not (fn1 == fn3) - assert fn1 != fn3 - assert cmp(fn1, fn3) == -1 - - assert cmp(fn1, 10) == -1 - assert cmp(fn2, 10) == -1 - assert cmp(fn3, 10) == -1 - for fn in fn1,fn2,fn3: - assert fn != 3 - assert fn != col - assert fn != [1,2,3] - assert [1,2,3] != fn - assert col != fn - - def test_function_equality(): config = py.test.config._reparse([tmpdir]) f1 = py.test.collect.Function(name="name", config=config, @@ -341,22 +393,6 @@ class Testgenitems: assert hash(i) != hash(j) assert i != j - def test_skip_by_conftest_directory(self): - from py.__.test import outcome - self.tmp.ensure("subdir", "conftest.py").write(py.code.Source(""" - import py - class Directory(py.test.collect.Directory): - def listdir(self): - py.test.skip("intentional") - """)) - items, events = self._genitems() - assert len(items) == 0 - skips = [x for x in events - if isinstance(x, event.CollectionReport) - and x.colitem.name == 'subdir'] - assert len(skips) == 1 - assert skips[0].skipped - def test_root_conftest_syntax_error(self): # do we want to unify behaviour with # test_subdir_conftest_error? @@ -407,57 +443,6 @@ class Testgenitems: assert items[1].name == 'test_method_one' assert items[2].name == 'test_method_one' - def test_custom_python_collection_from_conftest(self): - checkfile = setupdata.setup_customconfigtest(self.tmp) - for x in (self.tmp, checkfile, checkfile.dirpath()): - items, events = self._genitems(x) - assert len(items) == 2 - #assert items[1].__class__.__name__ == 'MyFunction' - - return None # XXX shift below to session test? - # test that running a session works from the directories - old = o.chdir() - try: - sorter = suptest.events_from_cmdline([]) - passed, skipped, failed = sorter.countoutcomes() - assert passed == 2 - assert skipped == failed == 0 - finally: - old.chdir() - - # test that running the file directly works - sorter = suptest.events_from_cmdline([str(checkfile)]) - passed, skipped, failed = sorter.countoutcomes() - assert passed == 2 - assert skipped == failed == 0 - - def test_custom_NONpython_collection_from_conftest(self): - checkfile = setupdata.setup_non_python_dir(self.tmp) - - for x in (self.tmp, checkfile, checkfile.dirpath()): - print "checking that %s returns custom items" % (x,) - items, events = self._genitems(x) - assert len(items) == 1 - assert items[0].__class__.__name__ == 'CustomItem' - - return None # XXX shift below to session tests? - - # test that running a session works from the directories - old = self.tmp.chdir() - try: - sorter = suptest.events_from_cmdline([]) - passed, skipped, failed = sorter.countoutcomes() - assert passed == 1 - assert skipped == failed == 0 - finally: - old.chdir() - - # test that running the file directly works - sorter = suptest.events_from_cmdline([str(checkfile)]) - passed, skipped, failed = sorter.countoutcomes() - assert passed == 1 - assert skipped == failed == 0 - def test_collect_doctest_files_with_test_prefix(self): self.tmp.ensure("whatever.txt") checkfile = self.tmp.ensure("test_something.txt") @@ -548,7 +533,7 @@ class TestCollectorReprs(suptest.InlineCollection): assert info.lineno == 1 assert info.modpath == "test_gen" - genitem = gencol.join(gencol.listdir()[0]) + genitem = gencol.collect()[0] info = genitem.repr_metainfo() assert info.fspath == modcol.fspath assert info.lineno == 2 diff --git a/py/test/testing/test_config.py b/py/test/testing/test_config.py index 12771811f..ce1769d08 100644 --- a/py/test/testing/test_config.py +++ b/py/test/testing/test_config.py @@ -74,32 +74,6 @@ def test_config_getvalue_honours_conftest(): py.test.raises(KeyError, 'config.getvalue("y", o)') -def test_siblingconftest_fails_maybe(): - from py.__.test import config - cfg = config.Config() - o = py.test.ensuretemp('siblingconftest') - o.ensure("__init__.py") - o.ensure("sister1", "__init__.py") - o.ensure("sister1", "conftest.py").write(py.code.Source(""" - x = 2 - """)) - - o.ensure("sister2", "__init__.py") - o.ensure("sister2", "conftest.py").write(py.code.Source(""" - raise SyntaxError - """)) - - assert cfg.getvalue(path=o.join('sister1'), name='x') == 2 - old = o.chdir() - try: - pytestpath = py.magic.autopath().dirpath().dirpath().dirpath().join( - 'bin/py.test') - print py.process.cmdexec('python "%s" sister1' % (pytestpath,)) - o.join('sister1').chdir() - print py.process.cmdexec('python "%s"' % (pytestpath,)) - finally: - old.chdir() - def test_config_overwrite(): o = py.test.ensuretemp('testconfigget') o.ensure("conftest.py").write("x=1") @@ -338,7 +312,7 @@ class TestSessionAndOptions: def test_conflict_options(self): def check_conflict_option(opts): print "testing if options conflict:", " ".join(opts) - path = setupdata.getexamplefile("filetest.py") + path = setupdata.getexamplefile("file_test.py") config = py.test.config._reparse(opts + [path]) py.test.raises((ValueError, SystemExit), """ config.initsession() @@ -355,7 +329,7 @@ class TestSessionAndOptions: def test_implied_options(self): def check_implied_option(opts, expr): - path = setupdata.getexamplefile("filetest.py") + path = setupdata.getexamplefile("file_test.py") config = py.test.config._reparse(opts + [path]) session = config.initsession() assert eval(expr, session.config.option.__dict__) @@ -374,14 +348,14 @@ class TestSessionAndOptions: passed, skipped, failed = sorter.countoutcomes() assert failed == 2 assert skipped == passed == 0 - path = setupdata.getexamplefile("filetest.py") + path = setupdata.getexamplefile("file_test.py") for opts in ([], ['-l'], ['-s'], ['--tb=no'], ['--tb=short'], ['--tb=long'], ['--fulltrace'], ['--nomagic'], ['--traceconfig'], ['-v'], ['-v', '-v']): yield runfiletest, opts + [path] def test_is_not_boxed_by_default(self): - path = setupdata.getexamplefile("filetest.py") + path = setupdata.getexamplefile("file_test.py") config = py.test.config._reparse([path]) assert not config.option.boxed diff --git a/py/test/testing/test_deprecated_api.py b/py/test/testing/test_deprecated_api.py new file mode 100644 index 000000000..667e51b3d --- /dev/null +++ b/py/test/testing/test_deprecated_api.py @@ -0,0 +1,137 @@ + +import py +from py.__.test.testing import suptest + +class TestCollectDeprecated(suptest.InlineCollection): + def test_directory_run_join_warnings(self): + p = self.makepyfile(test_one="") + config = self.parseconfig() + dirnode = config.getfsnode(p.dirpath()) + py.test.deprecated_call(dirnode.run) + # XXX for directories we still have join() + #py.test.deprecated_call(dirnode.join, 'test_one') + + def test_collect_with_deprecated_run_and_join(self): + self.makepyfile(conftest=""" + import py + + class MyInstance(py.test.collect.Instance): + def run(self): + return ['check2'] + def join(self, name): + if name == 'check2': + return self.Function(name=name, parent=self) + + class MyClass(py.test.collect.Class): + def run(self): + return ['check2'] + def join(self, name): + return MyInstance(name='i', parent=self) + + class MyModule(py.test.collect.Module): + def run(self): + return ['check', 'Cls'] + def join(self, name): + if name == 'check': + return self.Function(name, parent=self) + if name == 'Cls': + return MyClass(name, parent=self) + + class MyDirectory(py.test.collect.Directory): + Module = MyModule + def run(self): + return ['somefile.py'] + def join(self, name): + if name == "somefile.py": + return self.Module(self.fspath.join(name), parent=self) + Directory = MyDirectory + """) + p = self.makepyfile(somefile=""" + def check(): pass + class Cls: + def check2(self): pass + """) + config = self.parseconfig() + dirnode = config.getfsnode(p.dirpath()) + colitems = py.test.deprecated_call(dirnode.collect) + assert len(colitems) == 1 + modcol = colitems[0] + assert modcol.name == "somefile.py" + colitems = py.test.deprecated_call(modcol.collect) + assert len(colitems) == 2 + assert colitems[0].name == 'check' + assert colitems[1].name == 'Cls' + clscol = colitems[1] + colitems = py.test.deprecated_call(clscol.collect) + assert len(colitems) == 1 + icol = colitems[0] + colitems = py.test.deprecated_call(icol.collect) + assert len(colitems) == 1 + assert colitems[0].name == 'check2' + + def test_collect_with_deprecated_join_but_no_run(self): + self.makepyfile(conftest=""" + import py + + class Module(py.test.collect.Module): + def funcnamefilter(self, name): + if name.startswith("check_"): + return True + return super(Module, self).funcnamefilter(name) + def join(self, name): + if name.startswith("check_"): + return self.Function(name, parent=self) + assert name != "SomeClass", "join should not be called with this name" + """) + col = self.getmodulecol(""" + def somefunc(): pass + def check_one(): pass + class SomeClass: pass + """) + colitems = py.test.deprecated_call(col.collect) + assert len(colitems) == 1 + funcitem = colitems[0] + assert funcitem.name == "check_one" + + def test_function_custom_run(self): + self.makepyfile(conftest=""" + import py + class MyFunction(py.test.collect.Function): + def run(self): + pass + Function=MyFunction + """) + modcol = self.getmodulecol("def test_func(): pass") + funcitem = modcol.collect()[0] + assert funcitem.name == 'test_func' + py.test.deprecated_call(funcitem.runtest) + + def test_function_custom_execute(self): + self.makepyfile(conftest=""" + import py + class MyFunction(py.test.collect.Function): + def execute(self, obj, *args): + pass + Function=MyFunction + """) + modcol = self.getmodulecol("def test_func(): pass") + funcitem = modcol.collect()[0] + assert funcitem.name == 'test_func' + py.test.deprecated_call(funcitem.runtest) + + def test_function_deprecated_run_execute(self): + modcol = self.getmodulecol("def test_some(): pass") + funcitem = modcol.collect()[0] + py.test.deprecated_call(funcitem.run) + py.test.deprecated_call(funcitem.execute, funcitem.obj) + + def test_function_deprecated_run_recursive(self): + self.makepyfile(conftest=""" + import py + class Module(py.test.collect.Module): + def run(self): + return super(Module, self).run() + """) + modcol = self.getmodulecol("def test_some(): pass") + colitems = py.test.deprecated_call(modcol.collect) + funcitem = colitems[0] diff --git a/py/test/testing/test_doctest.py b/py/test/testing/test_doctest.py index 213f9a601..a19694795 100644 --- a/py/test/testing/test_doctest.py +++ b/py/test/testing/test_doctest.py @@ -16,7 +16,7 @@ class TestDoctests(InlineCollection): config = self.parseconfig(txtfile) col = config.getfsnode(txtfile) testitem = col.join(txtfile.basename) - res = testitem.execute() + res = testitem.runtest() assert res is None @@ -29,6 +29,6 @@ class TestDoctests(InlineCollection): 2 """)) testitem = py.test.collect.DoctestFile(p).join(p.basename) - excinfo = py.test.raises(Failed, "testitem.execute()") + excinfo = py.test.raises(Failed, "testitem.runtest()") repr = testitem.repr_failure(excinfo, ("", "")) assert repr.reprlocation diff --git a/py/test/testing/test_event.py b/py/test/testing/test_event.py index dcd4f1118..741e0544c 100644 --- a/py/test/testing/test_event.py +++ b/py/test/testing/test_event.py @@ -38,7 +38,7 @@ class TestEventBus: class TestItemTestReport(object): def test_toterminal(self): - sorter = suptest.events_run_example("filetest.py") + sorter = suptest.events_run_example("file_test.py") reports = sorter.get(event.ItemTestReport) ev = reports[0] assert ev.failed @@ -54,5 +54,5 @@ class TestItemTestReport(object): ##assert ev.repr_run.find("AssertionError") != -1 filepath = ev.colitem.fspath #filepath , modpath = ev.itemrepr_path - assert str(filepath).endswith("filetest.py") - #assert modpath.endswith("filetest.test_one") + assert str(filepath).endswith("file_test.py") + #assert modpath.endswith("file_test.test_one") diff --git a/py/test/testing/test_repevent.py b/py/test/testing/test_repevent.py index 31ba9f657..088b0b840 100644 --- a/py/test/testing/test_repevent.py +++ b/py/test/testing/test_repevent.py @@ -8,7 +8,7 @@ from py.__.code.testing.test_excinfo import TWMock class TestItemTestReport(object): def test_toterminal(self): - sorter = suptest.events_run_example("filetest.py") + sorter = suptest.events_run_example("file_test.py") reports = sorter.get(event.ItemTestReport) ev = reports[0] assert ev.failed @@ -24,7 +24,7 @@ class TestItemTestReport(object): ##assert ev.repr_run.find("AssertionError") != -1 filepath = ev.colitem.fspath #filepath , modpath = ev.itemrepr_path - assert str(filepath).endswith("filetest.py") - #assert modpath.endswith("filetest.test_one") + assert str(filepath).endswith("file_test.py") + #assert modpath.endswith("file_test.test_one") diff --git a/py/test/testing/test_session.py b/py/test/testing/test_session.py index 7b450ba7c..437826450 100644 --- a/py/test/testing/test_session.py +++ b/py/test/testing/test_session.py @@ -8,7 +8,7 @@ def setup_module(mod): class TestKeywordSelection: def test_select_simple(self): def check(keyword, name): - sorter = suptest.events_run_example("filetest.py", + sorter = suptest.events_run_example("file_test.py", '-s', '-k', keyword) passed, skipped, failed = sorter.listoutcomes() assert len(failed) == 1 @@ -190,6 +190,21 @@ class SessionTests(suptest.InlineCollection): assert (out.find("[unknown exception raised in repr()]") != -1 or out.find("TypeError") != -1) + def test_skip_by_conftest_directory(self): + from py.__.test import outcome + self.makepyfile(conftest=""" + import py + class Directory(py.test.collect.Directory): + def collect(self): + py.test.skip("intentional") + """, test_file=""" + def test_one(): pass + """) + sorter = self.events_from_cmdline() + skips = sorter.get(event.CollectionReport) + assert len(skips) == 1 + assert skips[0].skipped + class TestNewSession(SessionTests): def test_pdb_run(self): tfile = self.makepyfile(test_one="""