Skip to content

Commit

Permalink
majorly refactor collection process
Browse files Browse the repository at this point in the history
- get rid of py.test.collect.Directory alltogether.
- introduce direct node.nodeid attribute
- remove now superflous attributes on collect and test reports
  • Loading branch information
hpk42 committed Nov 6, 2010
1 parent f181c70 commit 6dac774
Show file tree
Hide file tree
Showing 24 changed files with 698 additions and 751 deletions.
7 changes: 4 additions & 3 deletions CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ Changes between 1.3.4 and 2.0.0dev0
- new python invcation: pytest.main(args, plugins) to load
some custom plugins early.
- try harder to run unittest test suites in a more compatible manner
by deferring setup/teardown semantics to the unittest package.
by deferring setup/teardown semantics to the unittest package.
- introduce a new way to set config options via ini-style files,
by default setup.cfg and tox.ini files are searched. The old
ways (certain environment variables, dynamic conftest.py reading
ways (certain environment variables, dynamic conftest.py reading
is removed).
- add a new "-q" option which decreases verbosity and prints a more
nose/unittest-style "dot" output.
Expand All @@ -26,7 +26,8 @@ Changes between 1.3.4 and 2.0.0dev0
output on assertion failures for comparisons and other cases (Floris Bruynooghe)
- nose-plugin: pass through type-signature failures in setup/teardown
functions instead of not calling them (Ed Singleton)
- major refactoring of internal collection handling
- remove py.test.collect.Directory (follows from a major refactoring
and simplification of the collection process)
- majorly reduce py.test core code, shift function/python testing to own plugin
- fix issue88 (finding custom test nodes from command line arg)
- refine 'tmpdir' creation, will now create basenames better associated
Expand Down
4 changes: 2 additions & 2 deletions pytest/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
(c) Holger Krekel and others, 2004-2010
"""
__version__ = '2.0.0.dev18'
__version__ = '2.0.0.dev19'

__all__ = ['config', 'cmdline']

from pytest import main as cmdline
UsageError = cmdline.UsageError
main = cmdline.main
main = cmdline.main
2 changes: 1 addition & 1 deletion pytest/hookspec.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ def pytest_runtest_protocol(item):
"""
pytest_runtest_protocol.firstresult = True

def pytest_runtest_logstart(nodeid, location, fspath):
def pytest_runtest_logstart(nodeid, location):
""" signal the start of a test run. """

def pytest_runtest_setup(item):
Expand Down
15 changes: 12 additions & 3 deletions pytest/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,10 @@ def __init__(self, load=False):
self._hints = []
self.trace = TagTracer().get("pluginmanage")
if os.environ.get('PYTEST_DEBUG'):
self.trace.root.setwriter(sys.stderr.write)
err = sys.stderr
if hasattr(os, 'dup'):
err = py.io.dupfile(err)
self.trace.root.setwriter(err.write)
self.hook = HookRelay([hookspec], pm=self)
self.register(self)
if load:
Expand Down Expand Up @@ -370,6 +373,7 @@ def __init__(self, hookrelay, name, firstresult):
self.hookrelay = hookrelay
self.name = name
self.firstresult = firstresult
self.trace = self.hookrelay.trace

def __repr__(self):
return "<HookCaller %r>" %(self.name,)
Expand All @@ -380,10 +384,15 @@ def __call__(self, **kwargs):
return mc.execute()

def pcall(self, plugins, **kwargs):
self.hookrelay.trace(self.name, kwargs)
self.trace(self.name, kwargs)
self.trace.root.indent += 1
methods = self.hookrelay._pm.listattr(self.name, plugins=plugins)
mc = MultiCall(methods, kwargs, firstresult=self.firstresult)
return mc.execute()
res = mc.execute()
if res:
self.trace(res)
self.trace.root.indent -= 1
return res

_preinit = [PluginManager(load=True)] # triggers default plugin importing

Expand Down
6 changes: 5 additions & 1 deletion pytest/plugin/capture.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,11 @@ def deactivate_funcargs(self):

def pytest_make_collect_report(self, __multicall__, collector):
method = self._getmethod(collector.config, collector.fspath)
self.resumecapture(method)
try:
self.resumecapture(method)
except ValueError:
return # recursive collect, XXX refactor capturing
# to allow for more lightweight recursive capturing
try:
rep = __multicall__.execute()
finally:
Expand Down
2 changes: 1 addition & 1 deletion pytest/plugin/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ def __init__(self, pluginmanager=None):
)
#: a pluginmanager instance
self.pluginmanager = pluginmanager or PluginManager(load=True)
self.trace = self.pluginmanager.trace.get("config")
self.trace = self.pluginmanager.trace.root.get("config")
self._conftest = Conftest(onimport=self._onimportconftest)
self.hook = self.pluginmanager.hook

Expand Down
2 changes: 1 addition & 1 deletion pytest/plugin/doctest.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ def pytest_addoption(parser):
def pytest_collect_file(path, parent):
config = parent.config
if path.ext == ".py":
if config.getvalue("doctestmodules"):
if config.option.doctestmodules:
return DoctestModule(path, parent)
elif path.check(fnmatch=config.getvalue("doctestglob")):
return DoctestTextfile(path, parent)
Expand Down
5 changes: 4 additions & 1 deletion pytest/plugin/junitxml.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"""

import py
import os
import time

def pytest_addoption(parser):
Expand Down Expand Up @@ -36,7 +37,9 @@ def __init__(self, logfile, prefix):
self._durations = {}

def _opentestcase(self, report):
names = report.nodenames
names = report.nodeid.split("::")
names[0] = names[0].replace(os.sep, '.')
names = tuple(names)
d = {'time': self._durations.pop(names, "0")}
names = [x.replace(".py", "") for x in names if x != "()"]
classnames = names[:-1]
Expand Down
47 changes: 30 additions & 17 deletions pytest/plugin/pytester.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ def getcalls(self, names):
return l

def contains(self, entries):
__tracebackhide__ = True
from py.builtin import print_
i = 0
entries = list(entries)
Expand All @@ -123,8 +124,7 @@ def contains(self, entries):
break
print_("NONAMEMATCH", name, "with", call)
else:
raise AssertionError("could not find %r in %r" %(
name, self.calls[i:]))
py.test.fail("could not find %r check %r" % (name, check))

def popcall(self, name):
for i, call in enumerate(self.calls):
Expand Down Expand Up @@ -278,7 +278,16 @@ def mkpydir(self, name):
Collection = Collection
def getnode(self, config, arg):
collection = Collection(config)
return collection.getbyid(collection._normalizearg(arg))[0]
assert '::' not in str(arg)
p = py.path.local(arg)
x = collection.fspath.bestrelpath(p)
return collection.perform_collect([x], genitems=False)[0]

def getpathnode(self, path):
config = self.parseconfig(path)
collection = Collection(config)
x = collection.fspath.bestrelpath(path)
return collection.perform_collect([x], genitems=False)[0]

def genitems(self, colitems):
collection = colitems[0].collection
Expand All @@ -291,8 +300,9 @@ def inline_genitems(self, *args):
#config = self.parseconfig(*args)
config = self.parseconfigure(*args)
rec = self.getreportrecorder(config)
items = Collection(config).perform_collect()
return items, rec
collection = Collection(config)
collection.perform_collect()
return collection.items, rec

def runitem(self, source):
# used from runner functional tests
Expand Down Expand Up @@ -469,11 +479,12 @@ def runpytest(self, *args):
p = py.path.local.make_numbered_dir(prefix="runpytest-",
keep=None, rootdir=self.tmpdir)
args = ('--basetemp=%s' % p, ) + args
for x in args:
if '--confcutdir' in str(x):
break
else:
args = ('--confcutdir=.',) + args
#for x in args:
# if '--confcutdir' in str(x):
# break
#else:
# pass
# args = ('--confcutdir=.',) + args
plugins = [x for x in self.plugins if isinstance(x, str)]
if plugins:
args = ('-p', plugins[0]) + args
Expand Down Expand Up @@ -530,7 +541,7 @@ def matchreport(self, inamepart="", names="pytest_runtest_logreport pytest_colle
""" return a testreport whose dotted import path matches """
l = []
for rep in self.getreports(names=names):
if not inamepart or inamepart in rep.nodenames:
if not inamepart or inamepart in rep.nodeid.split("::"):
l.append(rep)
if not l:
raise ValueError("could not find test report matching %r: no test reports at all!" %
Expand Down Expand Up @@ -616,6 +627,8 @@ def fnmatch_lines_random(self, lines2):
raise ValueError("line %r not found in output" % line)

def fnmatch_lines(self, lines2):
def show(arg1, arg2):
py.builtin.print_(arg1, arg2, file=py.std.sys.stderr)
lines2 = self._getlines(lines2)
lines1 = self.lines[:]
nextline = None
Expand All @@ -626,17 +639,17 @@ def fnmatch_lines(self, lines2):
while lines1:
nextline = lines1.pop(0)
if line == nextline:
print_("exact match:", repr(line))
show("exact match:", repr(line))
break
elif fnmatch(nextline, line):
print_("fnmatch:", repr(line))
print_(" with:", repr(nextline))
show("fnmatch:", repr(line))
show(" with:", repr(nextline))
break
else:
if not nomatchprinted:
print_("nomatch:", repr(line))
show("nomatch:", repr(line))
nomatchprinted = True
print_(" and:", repr(nextline))
show(" and:", repr(nextline))
extralines.append(nextline)
else:
assert line == nextline
py.test.fail("remains unmatched: %r, see stderr" % (line,))
17 changes: 9 additions & 8 deletions pytest/plugin/python.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,10 @@ def pytest_pyfunc_call(__multicall__, pyfuncitem):
def pytest_collect_file(path, parent):
ext = path.ext
pb = path.purebasename
if pb.startswith("test_") or pb.endswith("_test") or \
path in parent.collection._argfspaths:
if ext == ".py":
return parent.ihook.pytest_pycollect_makemodule(
path=path, parent=parent)
if ext == ".py" and (pb.startswith("test_") or pb.endswith("_test") or
parent.collection.isinitpath(path)):
return parent.ihook.pytest_pycollect_makemodule(
path=path, parent=parent)

def pytest_pycollect_makemodule(path, parent):
return Module(path, parent)
Expand Down Expand Up @@ -713,11 +712,13 @@ def _raiselookupfailed(self, argname):
def showfuncargs(config):
from pytest.plugin.session import Collection
collection = Collection(config)
firstid = collection._normalizearg(config.args[0])
colitem = collection.getbyid(firstid)[0]
collection.perform_collect()
if collection.items:
plugins = getplugins(collection.items[0])
else:
plugins = getplugins(collection)
curdir = py.path.local()
tw = py.io.TerminalWriter()
plugins = getplugins(colitem, withpy=True)
verbose = config.getvalue("verbose")
for plugin in plugins:
available = []
Expand Down
Loading

0 comments on commit 6dac774

Please sign in to comment.