* refactor plugin support to work directly with
modules, no classes required anymore. * call funcarg hook if defined on class --HG-- branch : trunk
This commit is contained in:
parent
4035fa6326
commit
191d02aef2
|
@ -3,25 +3,23 @@ pytest_plugins = '_pytest doctest pytester'.split()
|
||||||
rsyncdirs = ['../doc']
|
rsyncdirs = ['../doc']
|
||||||
|
|
||||||
import py
|
import py
|
||||||
class PylibTestconfigPlugin:
|
def pytest_addoption(parser):
|
||||||
def pytest_funcarg__specssh(self, request):
|
group = parser.addgroup("pylib", "py lib testing options")
|
||||||
return getspecssh(request.config)
|
group.addoption('--sshhost',
|
||||||
def pytest_funcarg__specsocket(self, request):
|
action="store", dest="sshhost", default=None,
|
||||||
return getsocketspec(request.config)
|
help=("ssh xspec for ssh functional tests. "))
|
||||||
|
group.addoption('--gx',
|
||||||
|
action="append", dest="gspecs", default=None,
|
||||||
|
help=("add a global test environment, XSpec-syntax. "))
|
||||||
|
group.addoption('--runslowtests',
|
||||||
|
action="store_true", dest="runslowtests", default=False,
|
||||||
|
help=("run slow tests"))
|
||||||
|
|
||||||
def pytest_addoption(self, parser):
|
def pytest_funcarg__specssh(request):
|
||||||
group = parser.addgroup("pylib", "py lib testing options")
|
return getspecssh(request.config)
|
||||||
group.addoption('--sshhost',
|
def pytest_funcarg__specsocket(request):
|
||||||
action="store", dest="sshhost", default=None,
|
return getsocketspec(request.config)
|
||||||
help=("ssh xspec for ssh functional tests. "))
|
|
||||||
group.addoption('--gx',
|
|
||||||
action="append", dest="gspecs", default=None,
|
|
||||||
help=("add a global test environment, XSpec-syntax. "))
|
|
||||||
group.addoption('--runslowtests',
|
|
||||||
action="store_true", dest="runslowtests", default=False,
|
|
||||||
help=("run slow tests"))
|
|
||||||
|
|
||||||
ConftestPlugin = PylibTestconfigPlugin
|
|
||||||
|
|
||||||
# configuration information for tests
|
# configuration information for tests
|
||||||
def getgspecs(config=None):
|
def getgspecs(config=None):
|
||||||
|
|
|
@ -78,12 +78,15 @@ class FuncargRequest:
|
||||||
self.function = pyfuncitem.obj
|
self.function = pyfuncitem.obj
|
||||||
self.module = pyfuncitem._getparent(py.test.collect.Module).obj
|
self.module = pyfuncitem._getparent(py.test.collect.Module).obj
|
||||||
self.cls = getattr(self.function, 'im_class', None)
|
self.cls = getattr(self.function, 'im_class', None)
|
||||||
|
self.instance = getattr(self.function, 'im_self', None)
|
||||||
self.config = pyfuncitem.config
|
self.config = pyfuncitem.config
|
||||||
self.fspath = pyfuncitem.fspath
|
self.fspath = pyfuncitem.fspath
|
||||||
if hasattr(pyfuncitem, '_requestparam'):
|
if hasattr(pyfuncitem, '_requestparam'):
|
||||||
self.param = pyfuncitem._requestparam
|
self.param = pyfuncitem._requestparam
|
||||||
self._plugins = self.config.pluginmanager.getplugins()
|
self._plugins = self.config.pluginmanager.getplugins()
|
||||||
self._plugins.append(self.module)
|
self._plugins.append(self.module)
|
||||||
|
if self.instance is not None:
|
||||||
|
self._plugins.append(self.instance)
|
||||||
self._provider = self.config.pluginmanager.listattr(
|
self._provider = self.config.pluginmanager.listattr(
|
||||||
plugins=self._plugins,
|
plugins=self._plugins,
|
||||||
attrname=self._argprefix + str(argname)
|
attrname=self._argprefix + str(argname)
|
||||||
|
@ -126,7 +129,7 @@ class FuncargRequest:
|
||||||
def _raiselookupfailed(self):
|
def _raiselookupfailed(self):
|
||||||
available = []
|
available = []
|
||||||
for plugin in self._plugins:
|
for plugin in self._plugins:
|
||||||
for name in vars(plugin.__class__):
|
for name in vars(plugin):
|
||||||
if name.startswith(self._argprefix):
|
if name.startswith(self._argprefix):
|
||||||
name = name[len(self._argprefix):]
|
name = name[len(self._argprefix):]
|
||||||
if name not in available:
|
if name not in available:
|
||||||
|
|
|
@ -2,9 +2,23 @@ import py
|
||||||
|
|
||||||
pytest_plugins = "pytester", "plugintester"
|
pytest_plugins = "pytester", "plugintester"
|
||||||
|
|
||||||
class ConftestPlugin:
|
def pytest_collect_file(path, parent):
|
||||||
def pytest_collect_file(self, path, parent):
|
if path.basename.startswith("pytest_") and path.ext == ".py":
|
||||||
if path.basename.startswith("pytest_") and path.ext == ".py":
|
mod = parent.Module(path, parent=parent)
|
||||||
mod = parent.Module(path, parent=parent)
|
return mod
|
||||||
return mod
|
|
||||||
|
# decorate testdir to contain plugin under test
|
||||||
|
def pytest_funcarg__testdir(request):
|
||||||
|
testdir = request.call_next_provider()
|
||||||
|
#for obj in (request.cls, request.module):
|
||||||
|
# if hasattr(obj, 'testplugin'):
|
||||||
|
# testdir.plugins.append(obj.testplugin)
|
||||||
|
# break
|
||||||
|
#else:
|
||||||
|
basename = request.module.__name__.split(".")[-1]
|
||||||
|
if basename.startswith("pytest_"):
|
||||||
|
testdir.plugins.append(vars(request.module))
|
||||||
|
else:
|
||||||
|
pass # raise ValueError("need better support code")
|
||||||
|
return testdir
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
import py
|
import py
|
||||||
|
|
||||||
class _pytestPlugin:
|
def pytest_funcarg___pytest(request):
|
||||||
def pytest_funcarg___pytest(self, request):
|
return PytestArg(request)
|
||||||
return PytestArg(request)
|
|
||||||
|
|
||||||
class PytestArg:
|
class PytestArg:
|
||||||
def __init__(self, request):
|
def __init__(self, request):
|
||||||
|
@ -97,7 +96,7 @@ class CallRecorder:
|
||||||
return l
|
return l
|
||||||
|
|
||||||
def test_generic(plugintester):
|
def test_generic(plugintester):
|
||||||
plugintester.hookcheck(_pytestPlugin)
|
plugintester.hookcheck()
|
||||||
|
|
||||||
def test_callrecorder_basic():
|
def test_callrecorder_basic():
|
||||||
comregistry = py._com.Registry()
|
comregistry = py._com.Registry()
|
||||||
|
|
|
@ -1,179 +1,178 @@
|
||||||
|
""" Plugin implementing defaults and general options. """
|
||||||
|
|
||||||
import py
|
import py
|
||||||
|
|
||||||
class DefaultPlugin:
|
def pytest_itemrun(item, pdb=None):
|
||||||
""" Plugin implementing defaults and general options. """
|
from py.__.test.runner import basic_run_report, forked_run_report
|
||||||
|
if item.config.option.boxed:
|
||||||
|
runner = forked_run_report
|
||||||
|
else:
|
||||||
|
runner = basic_run_report
|
||||||
|
report = runner(item, pdb=pdb)
|
||||||
|
item.config.hook.pytest_itemtestreport(rep=report)
|
||||||
|
return True
|
||||||
|
|
||||||
def pytest_itemrun(self, item, pdb=None):
|
def pytest_item_makereport(item, excinfo, when, outerr):
|
||||||
from py.__.test.runner import basic_run_report, forked_run_report
|
from py.__.test import runner
|
||||||
if item.config.option.boxed:
|
return runner.ItemTestReport(item, excinfo, when, outerr)
|
||||||
runner = forked_run_report
|
|
||||||
|
def pytest_item_runtest_finished(item, excinfo, outerr):
|
||||||
|
from py.__.test import runner
|
||||||
|
rep = runner.ItemTestReport(item, excinfo, "execute", outerr)
|
||||||
|
item.config.hook.pytest_itemtestreport(rep=rep)
|
||||||
|
|
||||||
|
def pytest_pyfunc_call(pyfuncitem, args, kwargs):
|
||||||
|
pyfuncitem.obj(*args, **kwargs)
|
||||||
|
|
||||||
|
def pytest_collect_file(path, parent):
|
||||||
|
ext = path.ext
|
||||||
|
pb = path.purebasename
|
||||||
|
if pb.startswith("test_") or pb.endswith("_test") or \
|
||||||
|
path in parent.config.args:
|
||||||
|
if ext == ".py":
|
||||||
|
return parent.Module(path, parent=parent)
|
||||||
|
|
||||||
|
def pytest_collect_recurse(path, parent):
|
||||||
|
#excludelist = parent._config.getvalue_pathlist('dir_exclude', path)
|
||||||
|
#if excludelist and path in excludelist:
|
||||||
|
# return
|
||||||
|
if not parent.recfilter(path):
|
||||||
|
# check if cmdline specified this dir or a subdir directly
|
||||||
|
for arg in parent.config.args:
|
||||||
|
if path == arg or arg.relto(path):
|
||||||
|
break
|
||||||
else:
|
else:
|
||||||
runner = basic_run_report
|
return False
|
||||||
report = runner(item, pdb=pdb)
|
return True
|
||||||
item.config.hook.pytest_itemtestreport(rep=report)
|
|
||||||
return True
|
def pytest_collect_directory(path, parent):
|
||||||
|
# XXX reconsider the following comment
|
||||||
|
# not use parent.Directory here as we generally
|
||||||
|
# want dir/conftest.py to be able to
|
||||||
|
# define Directory(dir) already
|
||||||
|
Directory = parent.config.getvalue('Directory', path)
|
||||||
|
return Directory(path, parent=parent)
|
||||||
|
|
||||||
def pytest_item_makereport(self, item, excinfo, when, outerr):
|
def pytest_report_iteminfo(item):
|
||||||
from py.__.test import runner
|
return item.reportinfo()
|
||||||
return runner.ItemTestReport(item, excinfo, when, outerr)
|
|
||||||
|
|
||||||
def pytest_item_runtest_finished(self, item, excinfo, outerr):
|
def pytest_addoption(parser):
|
||||||
from py.__.test import runner
|
group = parser.addgroup("general", "test collection and failure interaction options")
|
||||||
rep = runner.ItemTestReport(item, excinfo, "execute", outerr)
|
group._addoption('-v', '--verbose', action="count",
|
||||||
item.config.hook.pytest_itemtestreport(rep=rep)
|
dest="verbose", default=0, help="increase verbosity."),
|
||||||
|
group._addoption('-x', '--exitfirst',
|
||||||
|
action="store_true", dest="exitfirst", default=False,
|
||||||
|
help="exit instantly on first error or failed test."),
|
||||||
|
group._addoption('-k',
|
||||||
|
action="store", dest="keyword", default='',
|
||||||
|
help="only run test items matching the given "
|
||||||
|
"space separated keywords. precede a keyword with '-' to negate. "
|
||||||
|
"Terminate the expression with ':' to treat a match as a signal "
|
||||||
|
"to run all subsequent tests. ")
|
||||||
|
group._addoption('-l', '--showlocals',
|
||||||
|
action="store_true", dest="showlocals", default=False,
|
||||||
|
help="show locals in tracebacks (disabled by default).")
|
||||||
|
#group._addoption('--showskipsummary',
|
||||||
|
# action="store_true", dest="showskipsummary", default=False,
|
||||||
|
# help="always show summary of skipped tests")
|
||||||
|
group._addoption('--pdb',
|
||||||
|
action="store_true", dest="usepdb", default=False,
|
||||||
|
help="start pdb (the Python debugger) on errors.")
|
||||||
|
group._addoption('--tb', metavar="style",
|
||||||
|
action="store", dest="tbstyle", default='long',
|
||||||
|
type="choice", choices=['long', 'short', 'no'],
|
||||||
|
help="traceback verboseness (long/short/no).")
|
||||||
|
group._addoption('-s',
|
||||||
|
action="store_true", dest="nocapture", default=False,
|
||||||
|
help="disable catching of stdout/stderr during test run.")
|
||||||
|
group.addoption('--boxed',
|
||||||
|
action="store_true", dest="boxed", default=False,
|
||||||
|
help="box each test run in a separate process")
|
||||||
|
group._addoption('-p', action="append", dest="plugin", default = [],
|
||||||
|
help=("load the specified plugin after command line parsing. "
|
||||||
|
"Example: '-p hello' will trigger 'import pytest_hello' "
|
||||||
|
"and instantiate 'HelloPlugin' from the module."))
|
||||||
|
group._addoption('-f', '--looponfail',
|
||||||
|
action="store_true", dest="looponfail", default=False,
|
||||||
|
help="run tests, re-run failing test set until all pass.")
|
||||||
|
|
||||||
def pytest_pyfunc_call(self, pyfuncitem, args, kwargs):
|
group = parser.addgroup("test process debugging")
|
||||||
pyfuncitem.obj(*args, **kwargs)
|
group.addoption('--collectonly',
|
||||||
|
action="store_true", dest="collectonly",
|
||||||
|
help="only collect tests, don't execute them."),
|
||||||
|
group.addoption('--traceconfig',
|
||||||
|
action="store_true", dest="traceconfig", default=False,
|
||||||
|
help="trace considerations of conftest.py files."),
|
||||||
|
group._addoption('--nomagic',
|
||||||
|
action="store_true", dest="nomagic", default=False,
|
||||||
|
help="don't reinterpret asserts, no traceback cutting. ")
|
||||||
|
group._addoption('--fulltrace',
|
||||||
|
action="store_true", dest="fulltrace", default=False,
|
||||||
|
help="don't cut any tracebacks (default is to cut).")
|
||||||
|
group.addoption('--basetemp', dest="basetemp", default=None, metavar="dir",
|
||||||
|
help="base temporary directory for this test run.")
|
||||||
|
group._addoption('--iocapture', action="store", default="fd", metavar="method",
|
||||||
|
type="choice", choices=['fd', 'sys', 'no'],
|
||||||
|
help="set iocapturing method: fd|sys|no.")
|
||||||
|
group.addoption('--debug',
|
||||||
|
action="store_true", dest="debug", default=False,
|
||||||
|
help="generate and show debugging information.")
|
||||||
|
|
||||||
def pytest_collect_file(self, path, parent):
|
group = parser.addgroup("dist", "distributed testing") # see http://pytest.org/help/dist")
|
||||||
ext = path.ext
|
group._addoption('--dist', metavar="distmode",
|
||||||
pb = path.purebasename
|
action="store", choices=['load', 'each', 'no'],
|
||||||
if pb.startswith("test_") or pb.endswith("_test") or \
|
type="choice", dest="dist", default="no",
|
||||||
path in parent.config.args:
|
help=("set mode for distributing tests to exec environments.\n\n"
|
||||||
if ext == ".py":
|
"each: send each test to each available environment.\n\n"
|
||||||
return parent.Module(path, parent=parent)
|
"load: send each test to available environment.\n\n"
|
||||||
|
"(default) no: run tests inprocess, don't distribute."))
|
||||||
|
group._addoption('--tx', dest="tx", action="append", default=[], metavar="xspec",
|
||||||
|
help=("add a test execution environment. some examples: "
|
||||||
|
"--tx popen//python=python2.5 --tx socket=192.168.1.102:8888 "
|
||||||
|
"--tx ssh=user@codespeak.net//chdir=testcache"))
|
||||||
|
group._addoption('-d',
|
||||||
|
action="store_true", dest="distload", default=False,
|
||||||
|
help="load-balance tests. shortcut for '--dist=load'")
|
||||||
|
group._addoption('-n', dest="numprocesses", metavar="numprocesses",
|
||||||
|
action="store", type="int",
|
||||||
|
help="shortcut for '--dist=load --tx=NUM*popen'")
|
||||||
|
group.addoption('--rsyncdir', action="append", default=[], metavar="dir1",
|
||||||
|
help="add directory for rsyncing to remote tx nodes.")
|
||||||
|
|
||||||
def pytest_collect_recurse(self, path, parent):
|
def pytest_configure(config):
|
||||||
#excludelist = parent._config.getvalue_pathlist('dir_exclude', path)
|
fixoptions(config)
|
||||||
#if excludelist and path in excludelist:
|
setsession(config)
|
||||||
# return
|
loadplugins(config)
|
||||||
if not parent.recfilter(path):
|
|
||||||
# check if cmdline specified this dir or a subdir directly
|
|
||||||
for arg in parent.config.args:
|
|
||||||
if path == arg or arg.relto(path):
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
def pytest_collect_directory(self, path, parent):
|
|
||||||
# XXX reconsider the following comment
|
|
||||||
# not use parent.Directory here as we generally
|
|
||||||
# want dir/conftest.py to be able to
|
|
||||||
# define Directory(dir) already
|
|
||||||
Directory = parent.config.getvalue('Directory', path)
|
|
||||||
return Directory(path, parent=parent)
|
|
||||||
|
|
||||||
def pytest_report_iteminfo(self, item):
|
def fixoptions(config):
|
||||||
return item.reportinfo()
|
if config.option.numprocesses:
|
||||||
|
config.option.dist = "load"
|
||||||
|
config.option.tx = ['popen'] * int(config.option.numprocesses)
|
||||||
|
if config.option.distload:
|
||||||
|
config.option.dist = "load"
|
||||||
|
if config.getvalue("usepdb"):
|
||||||
|
if config.getvalue("looponfail"):
|
||||||
|
raise config.Error("--pdb incompatible with --looponfail.")
|
||||||
|
if config.option.dist != "no":
|
||||||
|
raise config.Error("--pdb incomptaible with distributing tests.")
|
||||||
|
|
||||||
def pytest_addoption(self, parser):
|
def loadplugins(config):
|
||||||
group = parser.addgroup("general", "test collection and failure interaction options")
|
for name in config.getvalue("plugin"):
|
||||||
group._addoption('-v', '--verbose', action="count",
|
print "importing", name
|
||||||
dest="verbose", default=0, help="increase verbosity."),
|
config.pluginmanager.import_plugin(name)
|
||||||
group._addoption('-x', '--exitfirst',
|
|
||||||
action="store_true", dest="exitfirst", default=False,
|
|
||||||
help="exit instantly on first error or failed test."),
|
|
||||||
group._addoption('-k',
|
|
||||||
action="store", dest="keyword", default='',
|
|
||||||
help="only run test items matching the given "
|
|
||||||
"space separated keywords. precede a keyword with '-' to negate. "
|
|
||||||
"Terminate the expression with ':' to treat a match as a signal "
|
|
||||||
"to run all subsequent tests. ")
|
|
||||||
group._addoption('-l', '--showlocals',
|
|
||||||
action="store_true", dest="showlocals", default=False,
|
|
||||||
help="show locals in tracebacks (disabled by default).")
|
|
||||||
#group._addoption('--showskipsummary',
|
|
||||||
# action="store_true", dest="showskipsummary", default=False,
|
|
||||||
# help="always show summary of skipped tests")
|
|
||||||
group._addoption('--pdb',
|
|
||||||
action="store_true", dest="usepdb", default=False,
|
|
||||||
help="start pdb (the Python debugger) on errors.")
|
|
||||||
group._addoption('--tb', metavar="style",
|
|
||||||
action="store", dest="tbstyle", default='long',
|
|
||||||
type="choice", choices=['long', 'short', 'no'],
|
|
||||||
help="traceback verboseness (long/short/no).")
|
|
||||||
group._addoption('-s',
|
|
||||||
action="store_true", dest="nocapture", default=False,
|
|
||||||
help="disable catching of stdout/stderr during test run.")
|
|
||||||
group.addoption('--boxed',
|
|
||||||
action="store_true", dest="boxed", default=False,
|
|
||||||
help="box each test run in a separate process")
|
|
||||||
group._addoption('-p', action="append", dest="plugin", default = [],
|
|
||||||
help=("load the specified plugin after command line parsing. "
|
|
||||||
"Example: '-p hello' will trigger 'import pytest_hello' "
|
|
||||||
"and instantiate 'HelloPlugin' from the module."))
|
|
||||||
group._addoption('-f', '--looponfail',
|
|
||||||
action="store_true", dest="looponfail", default=False,
|
|
||||||
help="run tests, re-run failing test set until all pass.")
|
|
||||||
|
|
||||||
group = parser.addgroup("test process debugging")
|
def setsession(config):
|
||||||
group.addoption('--collectonly',
|
val = config.getvalue
|
||||||
action="store_true", dest="collectonly",
|
if val("collectonly"):
|
||||||
help="only collect tests, don't execute them."),
|
from py.__.test.session import Session
|
||||||
group.addoption('--traceconfig',
|
config.setsessionclass(Session)
|
||||||
action="store_true", dest="traceconfig", default=False,
|
else:
|
||||||
help="trace considerations of conftest.py files."),
|
if val("looponfail"):
|
||||||
group._addoption('--nomagic',
|
from py.__.test.looponfail.remote import LooponfailingSession
|
||||||
action="store_true", dest="nomagic", default=False,
|
config.setsessionclass(LooponfailingSession)
|
||||||
help="don't reinterpret asserts, no traceback cutting. ")
|
elif val("dist") != "no":
|
||||||
group._addoption('--fulltrace',
|
from py.__.test.dist.dsession import DSession
|
||||||
action="store_true", dest="fulltrace", default=False,
|
config.setsessionclass(DSession)
|
||||||
help="don't cut any tracebacks (default is to cut).")
|
|
||||||
group.addoption('--basetemp', dest="basetemp", default=None, metavar="dir",
|
|
||||||
help="base temporary directory for this test run.")
|
|
||||||
group._addoption('--iocapture', action="store", default="fd", metavar="method",
|
|
||||||
type="choice", choices=['fd', 'sys', 'no'],
|
|
||||||
help="set iocapturing method: fd|sys|no.")
|
|
||||||
group.addoption('--debug',
|
|
||||||
action="store_true", dest="debug", default=False,
|
|
||||||
help="generate and show debugging information.")
|
|
||||||
|
|
||||||
group = parser.addgroup("dist", "distributed testing") # see http://pytest.org/help/dist")
|
|
||||||
group._addoption('--dist', metavar="distmode",
|
|
||||||
action="store", choices=['load', 'each', 'no'],
|
|
||||||
type="choice", dest="dist", default="no",
|
|
||||||
help=("set mode for distributing tests to exec environments.\n\n"
|
|
||||||
"each: send each test to each available environment.\n\n"
|
|
||||||
"load: send each test to available environment.\n\n"
|
|
||||||
"(default) no: run tests inprocess, don't distribute."))
|
|
||||||
group._addoption('--tx', dest="tx", action="append", default=[], metavar="xspec",
|
|
||||||
help=("add a test execution environment. some examples: "
|
|
||||||
"--tx popen//python=python2.5 --tx socket=192.168.1.102:8888 "
|
|
||||||
"--tx ssh=user@codespeak.net//chdir=testcache"))
|
|
||||||
group._addoption('-d',
|
|
||||||
action="store_true", dest="distload", default=False,
|
|
||||||
help="load-balance tests. shortcut for '--dist=load'")
|
|
||||||
group._addoption('-n', dest="numprocesses", metavar="numprocesses",
|
|
||||||
action="store", type="int",
|
|
||||||
help="shortcut for '--dist=load --tx=NUM*popen'")
|
|
||||||
group.addoption('--rsyncdir', action="append", default=[], metavar="dir1",
|
|
||||||
help="add directory for rsyncing to remote tx nodes.")
|
|
||||||
|
|
||||||
def pytest_configure(self, config):
|
|
||||||
self.fixoptions(config)
|
|
||||||
self.setsession(config)
|
|
||||||
self.loadplugins(config)
|
|
||||||
|
|
||||||
def fixoptions(self, config):
|
|
||||||
if config.option.numprocesses:
|
|
||||||
config.option.dist = "load"
|
|
||||||
config.option.tx = ['popen'] * int(config.option.numprocesses)
|
|
||||||
if config.option.distload:
|
|
||||||
config.option.dist = "load"
|
|
||||||
if config.getvalue("usepdb"):
|
|
||||||
if config.getvalue("looponfail"):
|
|
||||||
raise config.Error("--pdb incompatible with --looponfail.")
|
|
||||||
if config.option.dist != "no":
|
|
||||||
raise config.Error("--pdb incomptaible with distributing tests.")
|
|
||||||
|
|
||||||
def loadplugins(self, config):
|
|
||||||
for name in config.getvalue("plugin"):
|
|
||||||
print "importing", name
|
|
||||||
config.pluginmanager.import_plugin(name)
|
|
||||||
|
|
||||||
def setsession(self, config):
|
|
||||||
val = config.getvalue
|
|
||||||
if val("collectonly"):
|
|
||||||
from py.__.test.session import Session
|
|
||||||
config.setsessionclass(Session)
|
|
||||||
else:
|
|
||||||
if val("looponfail"):
|
|
||||||
from py.__.test.looponfail.remote import LooponfailingSession
|
|
||||||
config.setsessionclass(LooponfailingSession)
|
|
||||||
elif val("dist") != "no":
|
|
||||||
from py.__.test.dist.dsession import DSession
|
|
||||||
config.setsessionclass(DSession)
|
|
||||||
|
|
||||||
def test_implied_different_sessions(tmpdir):
|
def test_implied_different_sessions(tmpdir):
|
||||||
def x(*args):
|
def x(*args):
|
||||||
|
@ -190,7 +189,7 @@ def test_implied_different_sessions(tmpdir):
|
||||||
assert x('-f') == 'LooponfailingSession'
|
assert x('-f') == 'LooponfailingSession'
|
||||||
|
|
||||||
def test_generic(plugintester):
|
def test_generic(plugintester):
|
||||||
plugintester.hookcheck(DefaultPlugin)
|
plugintester.hookcheck()
|
||||||
|
|
||||||
def test_plugin_specify(testdir):
|
def test_plugin_specify(testdir):
|
||||||
testdir.chdir()
|
testdir.chdir()
|
||||||
|
@ -253,14 +252,10 @@ def test_dist_options(testdir):
|
||||||
assert config.option.dist == "load"
|
assert config.option.dist == "load"
|
||||||
|
|
||||||
def test_pytest_report_iteminfo():
|
def test_pytest_report_iteminfo():
|
||||||
plugin = DefaultPlugin()
|
|
||||||
|
|
||||||
class FakeItem(object):
|
class FakeItem(object):
|
||||||
|
|
||||||
def reportinfo(self):
|
def reportinfo(self):
|
||||||
return "-reportinfo-"
|
return "-reportinfo-"
|
||||||
|
|
||||||
res = plugin.pytest_report_iteminfo(FakeItem())
|
res = pytest_report_iteminfo(FakeItem())
|
||||||
|
|
||||||
assert res == "-reportinfo-"
|
assert res == "-reportinfo-"
|
||||||
|
|
||||||
|
|
|
@ -1,18 +1,17 @@
|
||||||
import py
|
import py
|
||||||
|
|
||||||
class DoctestPlugin:
|
def pytest_addoption(parser):
|
||||||
def pytest_addoption(self, parser):
|
group = parser.addgroup("doctest options")
|
||||||
group = parser.addgroup("doctest options")
|
group.addoption("--doctest-modules",
|
||||||
group.addoption("--doctest-modules",
|
action="store_true", default=False,
|
||||||
action="store_true", default=False,
|
dest="doctestmodules")
|
||||||
dest="doctestmodules")
|
|
||||||
|
|
||||||
def pytest_collect_file(self, path, parent):
|
def pytest_collect_file(path, parent):
|
||||||
if path.ext == ".py":
|
if path.ext == ".py":
|
||||||
if parent.config.getvalue("doctestmodules"):
|
if parent.config.getvalue("doctestmodules"):
|
||||||
return DoctestModule(path, parent)
|
return DoctestModule(path, parent)
|
||||||
if path.check(fnmatch="test_*.txt"):
|
if path.check(fnmatch="test_*.txt"):
|
||||||
return DoctestTextfile(path, parent)
|
return DoctestTextfile(path, parent)
|
||||||
|
|
||||||
from py.__.code.excinfo import Repr, ReprFileLocation
|
from py.__.code.excinfo import Repr, ReprFileLocation
|
||||||
|
|
||||||
|
@ -76,8 +75,8 @@ class DoctestModule(DoctestItem):
|
||||||
#
|
#
|
||||||
|
|
||||||
class TestDoctests:
|
class TestDoctests:
|
||||||
|
|
||||||
def test_collect_testtextfile(self, testdir):
|
def test_collect_testtextfile(self, testdir):
|
||||||
testdir.plugins.append(DoctestPlugin())
|
|
||||||
testdir.maketxtfile(whatever="")
|
testdir.maketxtfile(whatever="")
|
||||||
checkfile = testdir.maketxtfile(test_something="""
|
checkfile = testdir.maketxtfile(test_something="""
|
||||||
alskdjalsdk
|
alskdjalsdk
|
||||||
|
@ -92,7 +91,6 @@ class TestDoctests:
|
||||||
assert isinstance(items[0], DoctestTextfile)
|
assert isinstance(items[0], DoctestTextfile)
|
||||||
|
|
||||||
def test_collect_module(self, testdir):
|
def test_collect_module(self, testdir):
|
||||||
testdir.plugins.append(DoctestPlugin())
|
|
||||||
path = testdir.makepyfile(whatever="#")
|
path = testdir.makepyfile(whatever="#")
|
||||||
for p in (path, testdir.tmpdir):
|
for p in (path, testdir.tmpdir):
|
||||||
items, evrec = testdir.inline_genitems(p, '--doctest-modules')
|
items, evrec = testdir.inline_genitems(p, '--doctest-modules')
|
||||||
|
@ -100,7 +98,6 @@ class TestDoctests:
|
||||||
assert isinstance(items[0], DoctestModule)
|
assert isinstance(items[0], DoctestModule)
|
||||||
|
|
||||||
def test_simple_doctestfile(self, testdir):
|
def test_simple_doctestfile(self, testdir):
|
||||||
testdir.plugins.append(DoctestPlugin())
|
|
||||||
p = testdir.maketxtfile(test_doc="""
|
p = testdir.maketxtfile(test_doc="""
|
||||||
>>> x = 1
|
>>> x = 1
|
||||||
>>> x == 1
|
>>> x == 1
|
||||||
|
@ -112,7 +109,6 @@ class TestDoctests:
|
||||||
def test_doctest_unexpected_exception(self, testdir):
|
def test_doctest_unexpected_exception(self, testdir):
|
||||||
from py.__.test.outcome import Failed
|
from py.__.test.outcome import Failed
|
||||||
|
|
||||||
testdir.plugins.append(DoctestPlugin())
|
|
||||||
p = testdir.maketxtfile("""
|
p = testdir.maketxtfile("""
|
||||||
>>> i = 0
|
>>> i = 0
|
||||||
>>> i = 1
|
>>> i = 1
|
||||||
|
@ -130,7 +126,6 @@ class TestDoctests:
|
||||||
#assert repr.reprlocation
|
#assert repr.reprlocation
|
||||||
|
|
||||||
def test_doctestmodule(self, testdir):
|
def test_doctestmodule(self, testdir):
|
||||||
testdir.plugins.append(DoctestPlugin())
|
|
||||||
p = testdir.makepyfile("""
|
p = testdir.makepyfile("""
|
||||||
'''
|
'''
|
||||||
>>> x = 1
|
>>> x = 1
|
||||||
|
@ -143,7 +138,7 @@ class TestDoctests:
|
||||||
sorter.assertoutcome(failed=1)
|
sorter.assertoutcome(failed=1)
|
||||||
|
|
||||||
def test_txtfile_failing(self, testdir):
|
def test_txtfile_failing(self, testdir):
|
||||||
testdir.plugins.append('pytest_doctest')
|
testdir.plugins.append("doctest")
|
||||||
p = testdir.maketxtfile("""
|
p = testdir.maketxtfile("""
|
||||||
>>> i = 0
|
>>> i = 0
|
||||||
>>> i + 1
|
>>> i + 1
|
||||||
|
@ -162,5 +157,5 @@ class TestDoctests:
|
||||||
|
|
||||||
|
|
||||||
def test_generic(plugintester):
|
def test_generic(plugintester):
|
||||||
plugintester.hookcheck(DoctestPlugin)
|
plugintester.hookcheck()
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
import py
|
import py
|
||||||
|
|
||||||
|
""" expected to fail.
|
||||||
|
"""
|
||||||
|
|
||||||
class EventlogPlugin:
|
class EventlogPlugin:
|
||||||
""" log pytest events to a file. """
|
""" log pytest events to a file. """
|
||||||
def pytest_addoption(self, parser):
|
def pytest_addoption(self, parser):
|
||||||
|
@ -28,7 +31,7 @@ class EventlogPlugin:
|
||||||
|
|
||||||
@py.test.mark.xfail
|
@py.test.mark.xfail
|
||||||
def test_generic(plugintester):
|
def test_generic(plugintester):
|
||||||
plugintester.hookcheck(EventlogPlugin)
|
plugintester.hookcheck()
|
||||||
|
|
||||||
testdir = plugintester.testdir()
|
testdir = plugintester.testdir()
|
||||||
testdir.makepyfile("""
|
testdir.makepyfile("""
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
import py
|
import py
|
||||||
|
|
||||||
class ExecnetcleanupPlugin:
|
def pytest_configure(config):
|
||||||
_gateways = None
|
debug = config.option.debug
|
||||||
_debug = None
|
config.pluginmanager.register(Execnetcleanup(debug))
|
||||||
|
|
||||||
def pytest_configure(self, config):
|
class Execnetcleanup:
|
||||||
self._debug = config.option.debug
|
_gateways = None
|
||||||
|
def __init__(self, debug=False):
|
||||||
|
self._debug = debug
|
||||||
|
|
||||||
def trace(self, msg, *args):
|
def trace(self, msg, *args):
|
||||||
if self._debug:
|
if self._debug:
|
||||||
|
@ -43,7 +45,8 @@ class ExecnetcleanupPlugin:
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def test_generic(plugintester):
|
def test_generic(plugintester):
|
||||||
plugintester.hookcheck(ExecnetcleanupPlugin)
|
plugintester.hookcheck(cls=Execnetcleanup)
|
||||||
|
plugintester.hookcheck()
|
||||||
|
|
||||||
@py.test.mark.xfail("clarify plugin registration/unregistration")
|
@py.test.mark.xfail("clarify plugin registration/unregistration")
|
||||||
def test_execnetplugin(testdir):
|
def test_execnetplugin(testdir):
|
||||||
|
|
|
@ -1,65 +1,58 @@
|
||||||
import py
|
import py
|
||||||
|
|
||||||
class FigleafPlugin:
|
figleaf = py.test.importorskip("figleaf")
|
||||||
def pytest_addoption(self, parser):
|
import figleaf.annotate_html
|
||||||
group = parser.addgroup('figleaf options')
|
|
||||||
group.addoption('-F', action='store_true', default=False,
|
|
||||||
dest = 'figleaf',
|
|
||||||
help=('trace coverage with figleaf and write HTML '
|
|
||||||
'for files below the current working dir'))
|
|
||||||
group.addoption('--figleaf-data', action='store', default='.figleaf',
|
|
||||||
dest='figleafdata',
|
|
||||||
help='path coverage tracing file.')
|
|
||||||
group.addoption('--figleaf-html', action='store', default='html',
|
|
||||||
dest='figleafhtml',
|
|
||||||
help='path to the coverage html dir.')
|
|
||||||
|
|
||||||
def pytest_configure(self, config):
|
def pytest_addoption(parser):
|
||||||
if config.getvalue('figleaf'):
|
group = parser.addgroup('figleaf options')
|
||||||
try:
|
group.addoption('-F', action='store_true', default=False,
|
||||||
import figleaf
|
dest = 'figleaf',
|
||||||
import figleaf.annotate_html
|
help=('trace coverage with figleaf and write HTML '
|
||||||
except ImportError:
|
'for files below the current working dir'))
|
||||||
raise config.Error('Could not import figleaf module')
|
group.addoption('--figleaf-data', action='store', default='.figleaf',
|
||||||
self.figleaf = figleaf
|
dest='figleafdata',
|
||||||
self.figleaf.start()
|
help='path coverage tracing file.')
|
||||||
|
group.addoption('--figleaf-html', action='store', default='html',
|
||||||
|
dest='figleafhtml',
|
||||||
|
help='path to the coverage html dir.')
|
||||||
|
|
||||||
def pytest_terminal_summary(self, terminalreporter):
|
def pytest_configure(config):
|
||||||
if hasattr(self, 'figleaf'):
|
figleaf.start()
|
||||||
config = terminalreporter.config
|
|
||||||
datafile = py.path.local(config.getvalue('figleafdata'))
|
|
||||||
tw = terminalreporter._tw
|
|
||||||
tw.sep('-', 'figleaf')
|
|
||||||
tw.line('Writing figleaf data to %s' % (datafile))
|
|
||||||
self.figleaf.stop()
|
|
||||||
self.figleaf.write_coverage(str(datafile))
|
|
||||||
coverage = self.get_coverage(datafile, config)
|
|
||||||
|
|
||||||
reportdir = py.path.local(config.getvalue('figleafhtml'))
|
def pytest_terminal_summary(terminalreporter):
|
||||||
tw.line('Writing figleaf html to file://%s' % (reportdir))
|
config = terminalreporter.config
|
||||||
self.figleaf.annotate_html.prepare_reportdir(str(reportdir))
|
datafile = py.path.local(config.getvalue('figleafdata'))
|
||||||
exclude = []
|
tw = terminalreporter._tw
|
||||||
self.figleaf.annotate_html.report_as_html(coverage,
|
tw.sep('-', 'figleaf')
|
||||||
str(reportdir), exclude, {})
|
tw.line('Writing figleaf data to %s' % (datafile))
|
||||||
|
figleaf.stop()
|
||||||
|
figleaf.write_coverage(str(datafile))
|
||||||
|
coverage = get_coverage(datafile, config)
|
||||||
|
reportdir = py.path.local(config.getvalue('figleafhtml'))
|
||||||
|
tw.line('Writing figleaf html to file://%s' % (reportdir))
|
||||||
|
figleaf.annotate_html.prepare_reportdir(str(reportdir))
|
||||||
|
exclude = []
|
||||||
|
figleaf.annotate_html.report_as_html(coverage,
|
||||||
|
str(reportdir), exclude, {})
|
||||||
|
|
||||||
def get_coverage(self, datafile, config):
|
def get_coverage(datafile, config):
|
||||||
# basepath = config.topdir
|
# basepath = config.topdir
|
||||||
basepath = py.path.local()
|
basepath = py.path.local()
|
||||||
data = self.figleaf.read_coverage(str(datafile))
|
data = figleaf.read_coverage(str(datafile))
|
||||||
d = {}
|
d = {}
|
||||||
coverage = self.figleaf.combine_coverage(d, data)
|
coverage = figleaf.combine_coverage(d, data)
|
||||||
for path in coverage.keys():
|
for path in coverage.keys():
|
||||||
if not py.path.local(path).relto(basepath):
|
if not py.path.local(path).relto(basepath):
|
||||||
del coverage[path]
|
del coverage[path]
|
||||||
return coverage
|
return coverage
|
||||||
|
|
||||||
|
|
||||||
def test_generic(plugintester):
|
def test_generic(plugintester):
|
||||||
plugintester.hookcheck(FigleafPlugin)
|
plugintester.hookcheck()
|
||||||
|
|
||||||
def test_functional(testdir):
|
def test_functional(testdir):
|
||||||
py.test.importorskip("figleaf")
|
py.test.importorskip("figleaf")
|
||||||
testdir.plugins.append('figleaf')
|
testdir.plugins.append("figleaf")
|
||||||
testdir.makepyfile("""
|
testdir.makepyfile("""
|
||||||
def f():
|
def f():
|
||||||
x = 42
|
x = 42
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
import py
|
import py
|
||||||
|
|
||||||
class IocapturePlugin:
|
def pytest_funcarg__stdcapture(request):
|
||||||
""" capture sys.stdout/sys.stderr / fd1/fd2. """
|
""" capture writes to sys.stdout/sys.stderr. """
|
||||||
def pytest_funcarg__stdcapture(self, request):
|
capture = Capture(py.io.StdCapture)
|
||||||
capture = Capture(py.io.StdCapture)
|
request.addfinalizer(capture.finalize)
|
||||||
request.addfinalizer(capture.finalize)
|
return capture
|
||||||
return capture
|
|
||||||
|
|
||||||
def pytest_funcarg__stdcapturefd(self, request):
|
def pytest_funcarg__stdcapturefd(request):
|
||||||
capture = Capture(py.io.StdCaptureFD)
|
""" capture writes to filedescriptors 1 and 2"""
|
||||||
request.addfinalizer(capture.finalize)
|
capture = Capture(py.io.StdCaptureFD)
|
||||||
return capture
|
request.addfinalizer(capture.finalize)
|
||||||
|
return capture
|
||||||
|
|
||||||
class Capture:
|
class Capture:
|
||||||
def __init__(self, captureclass):
|
def __init__(self, captureclass):
|
||||||
|
@ -26,11 +26,10 @@ class Capture:
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def test_generic(plugintester):
|
def test_generic(plugintester):
|
||||||
plugintester.hookcheck(IocapturePlugin)
|
plugintester.hookcheck()
|
||||||
|
|
||||||
class TestCapture:
|
class TestCapture:
|
||||||
def test_std_functional(self, testdir):
|
def test_std_functional(self, testdir):
|
||||||
testdir.plugins.append(IocapturePlugin())
|
|
||||||
evrec = testdir.inline_runsource("""
|
evrec = testdir.inline_runsource("""
|
||||||
def test_hello(stdcapture):
|
def test_hello(stdcapture):
|
||||||
print 42
|
print 42
|
||||||
|
@ -40,7 +39,6 @@ class TestCapture:
|
||||||
evrec.assertoutcome(passed=1)
|
evrec.assertoutcome(passed=1)
|
||||||
|
|
||||||
def test_stdfd_functional(self, testdir):
|
def test_stdfd_functional(self, testdir):
|
||||||
testdir.plugins.append(IocapturePlugin())
|
|
||||||
evrec = testdir.inline_runsource("""
|
evrec = testdir.inline_runsource("""
|
||||||
def test_hello(stdcapturefd):
|
def test_hello(stdcapturefd):
|
||||||
import os
|
import os
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
import os
|
import os
|
||||||
|
|
||||||
class MonkeypatchPlugin:
|
def pytest_funcarg__monkeypatch(request):
|
||||||
""" setattr-monkeypatching with automatical reversal after test. """
|
monkeypatch = MonkeyPatch()
|
||||||
def pytest_funcarg__monkeypatch(self, request):
|
request.addfinalizer(monkeypatch.finalize)
|
||||||
monkeypatch = MonkeyPatch()
|
return monkeypatch
|
||||||
request.addfinalizer(monkeypatch.finalize)
|
|
||||||
return monkeypatch
|
|
||||||
|
|
||||||
notset = object()
|
notset = object()
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
from py.__.test.custompdb import post_mortem
|
from py.__.test.custompdb import post_mortem
|
||||||
|
|
||||||
class PdbPlugin:
|
def pytest_item_runtest_finished(item, excinfo, outerr):
|
||||||
def pytest_item_runtest_finished(self, item, excinfo, outerr):
|
if excinfo and item.config.option.usepdb:
|
||||||
if excinfo and item.config.option.usepdb:
|
tw = py.io.TerminalWriter()
|
||||||
tw = py.io.TerminalWriter()
|
repr = excinfo.getrepr()
|
||||||
repr = excinfo.getrepr()
|
repr.toterminal(tw)
|
||||||
repr.toterminal(tw)
|
post_mortem(excinfo._excinfo[2])
|
||||||
post_mortem(excinfo._excinfo[2])
|
|
||||||
|
|
|
@ -4,32 +4,39 @@ plugin with support classes and functions for testing pytest functionality
|
||||||
import py
|
import py
|
||||||
from py.__.test.plugin import api
|
from py.__.test.plugin import api
|
||||||
|
|
||||||
class PlugintesterPlugin:
|
def pytest_funcarg__plugintester(request):
|
||||||
""" test support code for testing pytest plugins. """
|
return PluginTester(request)
|
||||||
def pytest_funcarg__plugintester(self, request):
|
|
||||||
return PluginTester(request)
|
|
||||||
|
|
||||||
class PluginTester:
|
class PluginTester:
|
||||||
def __init__(self, request):
|
def __init__(self, request):
|
||||||
self.request = request
|
self.request = request
|
||||||
|
|
||||||
def testdir(self):
|
def testdir(self, globs=None):
|
||||||
from pytest_pytester import TmpTestdir
|
from pytest_pytester import TmpTestdir
|
||||||
crunner = TmpTestdir(self.request)
|
testdir = TmpTestdir(self.request)
|
||||||
self.request.addfinalizer(crunner.finalize)
|
self.request.addfinalizer(testdir.finalize)
|
||||||
|
if globs is None:
|
||||||
|
globs = py.std.sys._getframe(-1).f_globals
|
||||||
|
testdir.plugins.append(globs)
|
||||||
#
|
#
|
||||||
#for colitem in self.request.listchain():
|
#for colitem in self.request.listchain():
|
||||||
# if isinstance(colitem, py.test.collect.Module) and \
|
# if isinstance(colitem, py.test.collect.Module) and \
|
||||||
# colitem.name.startswith("pytest_"):
|
# colitem.name.startswith("pytest_"):
|
||||||
# crunner.plugins.append(colitem.fspath.purebasename)
|
# crunner.plugins.append(colitem.fspath.purebasename)
|
||||||
# break
|
# break
|
||||||
return crunner
|
return testdir
|
||||||
|
|
||||||
def hookcheck(self, pluginclass):
|
def hookcheck(self, name=None, cls=None):
|
||||||
print "loading and checking", pluginclass
|
if cls is None:
|
||||||
|
if name is None:
|
||||||
|
name = py.std.sys._getframe(-1).f_globals['__name__']
|
||||||
|
plugin = __import__(name)
|
||||||
|
else:
|
||||||
|
plugin = cls
|
||||||
|
print "checking", plugin
|
||||||
fail = False
|
fail = False
|
||||||
pm = py.test._PluginManager()
|
pm = py.test._PluginManager()
|
||||||
methods = collectattr(pluginclass)
|
methods = collectattr(plugin)
|
||||||
hooks = collectattr(api.PluginHooks)
|
hooks = collectattr(api.PluginHooks)
|
||||||
getargs = py.std.inspect.getargs
|
getargs = py.std.inspect.getargs
|
||||||
|
|
||||||
|
@ -84,4 +91,4 @@ def formatdef(func):
|
||||||
# ===============================================================================
|
# ===============================================================================
|
||||||
|
|
||||||
def test_generic(plugintester):
|
def test_generic(plugintester):
|
||||||
plugintester.hookcheck(PlugintesterPlugin)
|
plugintester.hookcheck()
|
||||||
|
|
|
@ -8,50 +8,46 @@ class url:
|
||||||
xmlrpc = base + "/xmlrpc/"
|
xmlrpc = base + "/xmlrpc/"
|
||||||
show = base + "/show/"
|
show = base + "/show/"
|
||||||
|
|
||||||
class PocooPlugin:
|
def pytest_addoption(parser):
|
||||||
""" report URLs from sending test failures to the pocoo paste service. """
|
group = parser.addgroup("pocoo plugin")
|
||||||
|
group.addoption('-P', '--pocoo-sendfailures',
|
||||||
|
action='store_true', dest="pocoo_sendfailures",
|
||||||
|
help="send failures to %s paste service" %(url.base,))
|
||||||
|
|
||||||
def pytest_addoption(self, parser):
|
def getproxy():
|
||||||
group = parser.addgroup("pocoo plugin")
|
return py.std.xmlrpclib.ServerProxy(url.xmlrpc).pastes
|
||||||
group.addoption('-P', '--pocoo-sendfailures',
|
|
||||||
action='store_true', dest="pocoo_sendfailures",
|
|
||||||
help="send failures to %s paste service" %(url.base,))
|
|
||||||
|
|
||||||
def getproxy(self):
|
def pytest_terminal_summary(terminalreporter):
|
||||||
return py.std.xmlrpclib.ServerProxy(url.xmlrpc).pastes
|
if terminalreporter.config.option.pocoo_sendfailures:
|
||||||
|
tr = terminalreporter
|
||||||
def pytest_terminal_summary(self, terminalreporter):
|
if 'failed' in tr.stats and tr.config.option.tbstyle != "no":
|
||||||
if terminalreporter.config.option.pocoo_sendfailures:
|
terminalreporter.write_sep("=", "Sending failures to %s" %(url.base,))
|
||||||
tr = terminalreporter
|
terminalreporter.write_line("xmlrpcurl: %s" %(url.xmlrpc,))
|
||||||
if 'failed' in tr.stats and tr.config.option.tbstyle != "no":
|
#print self.__class__.getproxy
|
||||||
terminalreporter.write_sep("=", "Sending failures to %s" %(url.base,))
|
#print self.__class__, id(self.__class__)
|
||||||
terminalreporter.write_line("xmlrpcurl: %s" %(url.xmlrpc,))
|
serverproxy = getproxy()
|
||||||
#print self.__class__.getproxy
|
for ev in terminalreporter.stats.get('failed'):
|
||||||
#print self.__class__, id(self.__class__)
|
tw = py.io.TerminalWriter(stringio=True)
|
||||||
serverproxy = self.getproxy()
|
ev.toterminal(tw)
|
||||||
for ev in terminalreporter.stats.get('failed'):
|
s = tw.stringio.getvalue()
|
||||||
tw = py.io.TerminalWriter(stringio=True)
|
# XXX add failure summary
|
||||||
ev.toterminal(tw)
|
assert len(s)
|
||||||
s = tw.stringio.getvalue()
|
terminalreporter.write_line("newpaste() ...")
|
||||||
# XXX add failure summary
|
proxyid = serverproxy.newPaste("python", s)
|
||||||
assert len(s)
|
terminalreporter.write_line("%s%s\n" % (url.show, proxyid))
|
||||||
terminalreporter.write_line("newpaste() ...")
|
break
|
||||||
proxyid = serverproxy.newPaste("python", s)
|
|
||||||
terminalreporter.write_line("%s%s\n" % (url.show, proxyid))
|
|
||||||
break
|
|
||||||
|
|
||||||
|
|
||||||
def test_apicheck(plugintester):
|
def test_apicheck(plugintester):
|
||||||
plugintester.hookcheck(PocooPlugin)
|
plugintester.hookcheck()
|
||||||
|
|
||||||
def test_toproxy(testdir, monkeypatch):
|
def test_toproxy(testdir, monkeypatch):
|
||||||
l = []
|
l = []
|
||||||
class MockProxy:
|
class MockProxy:
|
||||||
def newPaste(self, language, code):
|
def newPaste(self, language, code):
|
||||||
l.append((language, code))
|
l.append((language, code))
|
||||||
monkeypatch.setattr(PocooPlugin, 'getproxy', MockProxy)
|
monkeypatch.setitem(globals(), 'getproxy', MockProxy)
|
||||||
testdir.plugins.insert(0, PocooPlugin())
|
testdir.plugins.insert(0, globals())
|
||||||
testdir.chdir()
|
|
||||||
testpath = testdir.makepyfile("""
|
testpath = testdir.makepyfile("""
|
||||||
import py
|
import py
|
||||||
def test_pass():
|
def test_pass():
|
||||||
|
|
|
@ -5,32 +5,21 @@ XXX: Currently in progress, NOT IN WORKING STATE.
|
||||||
"""
|
"""
|
||||||
import py
|
import py
|
||||||
|
|
||||||
class PylintPlugin:
|
lint = py.test.importorskip("pylint")
|
||||||
def pytest_addoption(self, parser):
|
|
||||||
group = parser.addgroup('pylint options')
|
|
||||||
group.addoption('--pylint', action='store_true',
|
|
||||||
default=False, dest='pylint',
|
|
||||||
help='Pylint coverate of test files.')
|
|
||||||
|
|
||||||
def pytest_configure(self, config):
|
def pytest_addoption(parser):
|
||||||
if config.getvalue('pylint'):
|
group = parser.addgroup('pylint options')
|
||||||
try:
|
group.addoption('--pylint', action='store_true',
|
||||||
from pylint import lint
|
default=False, dest='pylint',
|
||||||
self.lint = lint
|
help='Pylint coverate of test files.')
|
||||||
except ImportError:
|
|
||||||
raise config.Error('Could not import pylint module')
|
|
||||||
print "trying to configure pytest"
|
|
||||||
|
|
||||||
def pytest_collect_file(self, path, parent):
|
|
||||||
if path.ext == ".py":
|
|
||||||
if parent.config.getvalue('pylint'):
|
|
||||||
return PylintItem(path, parent, self.lint)
|
|
||||||
|
|
||||||
def pytest_terminal_summary(self, terminalreporter):
|
|
||||||
if hasattr(self, 'lint'):
|
|
||||||
print 'placeholder for pylint output'
|
|
||||||
|
|
||||||
|
def pytest_collect_file(path, parent):
|
||||||
|
if path.ext == ".py":
|
||||||
|
if parent.config.getvalue('pylint'):
|
||||||
|
return PylintItem(path, parent, self.lint)
|
||||||
|
|
||||||
|
def pytest_terminal_summary(terminalreporter):
|
||||||
|
print 'placeholder for pylint output'
|
||||||
|
|
||||||
class PylintItem(py.test.collect.Item):
|
class PylintItem(py.test.collect.Item):
|
||||||
def __init__(self, path, parent, lintlib):
|
def __init__(self, path, parent, lintlib):
|
||||||
|
|
|
@ -10,25 +10,23 @@ from py.__.test.config import Config as pytestConfig
|
||||||
from pytest__pytest import CallRecorder
|
from pytest__pytest import CallRecorder
|
||||||
import api
|
import api
|
||||||
|
|
||||||
|
def pytest_funcarg__linecomp(request):
|
||||||
|
return LineComp()
|
||||||
|
|
||||||
class PytesterPlugin:
|
def pytest_funcarg__LineMatcher(request):
|
||||||
def pytest_funcarg__linecomp(self, request):
|
return LineMatcher
|
||||||
return LineComp()
|
|
||||||
|
|
||||||
def pytest_funcarg__LineMatcher(self, request):
|
def pytest_funcarg__testdir(request):
|
||||||
return LineMatcher
|
tmptestdir = TmpTestdir(request)
|
||||||
|
return tmptestdir
|
||||||
|
|
||||||
def pytest_funcarg__testdir(self, request):
|
def pytest_funcarg__eventrecorder(request):
|
||||||
tmptestdir = TmpTestdir(request)
|
evrec = EventRecorder(py._com.comregistry)
|
||||||
return tmptestdir
|
request.addfinalizer(lambda: evrec.comregistry.unregister(evrec))
|
||||||
|
return evrec
|
||||||
def pytest_funcarg__eventrecorder(self, request):
|
|
||||||
evrec = EventRecorder(py._com.comregistry)
|
|
||||||
request.addfinalizer(lambda: evrec.comregistry.unregister(evrec))
|
|
||||||
return evrec
|
|
||||||
|
|
||||||
def test_generic(plugintester):
|
def test_generic(plugintester):
|
||||||
plugintester.hookcheck(PytesterPlugin)
|
plugintester.hookcheck()
|
||||||
|
|
||||||
class RunResult:
|
class RunResult:
|
||||||
def __init__(self, ret, outlines, errlines):
|
def __init__(self, ret, outlines, errlines):
|
||||||
|
@ -163,7 +161,9 @@ class TmpTestdir:
|
||||||
for plugin in self.plugins:
|
for plugin in self.plugins:
|
||||||
if isinstance(plugin, str):
|
if isinstance(plugin, str):
|
||||||
config.pluginmanager.import_plugin(plugin)
|
config.pluginmanager.import_plugin(plugin)
|
||||||
else:
|
elif plugin:
|
||||||
|
if isinstance(plugin, dict):
|
||||||
|
plugin = PseudoPlugin(plugin)
|
||||||
config.pluginmanager.register(plugin)
|
config.pluginmanager.register(plugin)
|
||||||
return config
|
return config
|
||||||
|
|
||||||
|
@ -280,6 +280,11 @@ class TmpTestdir:
|
||||||
child.timeout = expect_timeout
|
child.timeout = expect_timeout
|
||||||
return child
|
return child
|
||||||
|
|
||||||
|
class PseudoPlugin:
|
||||||
|
def __init__(self, vars):
|
||||||
|
self.__dict__.update(vars)
|
||||||
|
|
||||||
|
|
||||||
class Event:
|
class Event:
|
||||||
def __init__(self, name, args, kwargs):
|
def __init__(self, name, args, kwargs):
|
||||||
self.name = name
|
self.name = name
|
||||||
|
|
|
@ -7,12 +7,11 @@ to a user. See the test at the bottom for an example.
|
||||||
import py
|
import py
|
||||||
import os
|
import os
|
||||||
|
|
||||||
class RecwarnPlugin:
|
def pytest_funcarg__recwarn(request):
|
||||||
def pytest_funcarg__recwarn(self, request):
|
""" check that warnings have been raised. """
|
||||||
""" check that warnings have been raised. """
|
warnings = WarningsRecorder()
|
||||||
warnings = WarningsRecorder()
|
request.addfinalizer(warnings.finalize)
|
||||||
request.addfinalizer(warnings.finalize)
|
return warnings
|
||||||
return warnings
|
|
||||||
|
|
||||||
class RecordedWarning:
|
class RecordedWarning:
|
||||||
def __init__(self, message, category, filename, lineno, line):
|
def __init__(self, message, category, filename, lineno, line):
|
||||||
|
|
|
@ -1,23 +1,22 @@
|
||||||
import py
|
import py
|
||||||
|
|
||||||
class RestdocPlugin:
|
def pytest_addoption(parser):
|
||||||
def pytest_addoption(self, parser):
|
group = parser.addgroup("ReST", "ReST documentation check options")
|
||||||
group = parser.addgroup("ReST", "ReST documentation check options")
|
group.addoption('-R', '--urlcheck',
|
||||||
group.addoption('-R', '--urlcheck',
|
action="store_true", dest="urlcheck", default=False,
|
||||||
action="store_true", dest="urlcheck", default=False,
|
help="urlopen() remote links found in ReST text files.")
|
||||||
help="urlopen() remote links found in ReST text files.")
|
group.addoption('--urltimeout', action="store", metavar="secs",
|
||||||
group.addoption('--urltimeout', action="store", metavar="secs",
|
type="int", dest="urlcheck_timeout", default=5,
|
||||||
type="int", dest="urlcheck_timeout", default=5,
|
help="timeout in seconds for remote urlchecks")
|
||||||
help="timeout in seconds for remote urlchecks")
|
group.addoption('--forcegen',
|
||||||
group.addoption('--forcegen',
|
action="store_true", dest="forcegen", default=False,
|
||||||
action="store_true", dest="forcegen", default=False,
|
help="force generation of html files.")
|
||||||
help="force generation of html files.")
|
|
||||||
|
|
||||||
def pytest_collect_file(self, path, parent):
|
def pytest_collect_file(path, parent):
|
||||||
if path.ext == ".txt":
|
if path.ext == ".txt":
|
||||||
project = getproject(path)
|
project = getproject(path)
|
||||||
if project is not None:
|
if project is not None:
|
||||||
return ReSTFile(path, parent=parent, project=project)
|
return ReSTFile(path, parent=parent, project=project)
|
||||||
|
|
||||||
def getproject(path):
|
def getproject(path):
|
||||||
for parent in path.parts(reverse=True):
|
for parent in path.parts(reverse=True):
|
||||||
|
@ -346,7 +345,7 @@ def localrefcheck(tryfn, path, lineno):
|
||||||
# PLUGIN tests
|
# PLUGIN tests
|
||||||
#
|
#
|
||||||
def test_generic(plugintester):
|
def test_generic(plugintester):
|
||||||
plugintester.hookcheck(RestdocPlugin)
|
plugintester.hookcheck()
|
||||||
|
|
||||||
def test_deindent():
|
def test_deindent():
|
||||||
assert deindent('foo') == 'foo'
|
assert deindent('foo') == 'foo'
|
||||||
|
@ -388,18 +387,18 @@ class TestApigenLinkRole:
|
||||||
"resolve_linkrole('source', 'py/foo/bar.py')")
|
"resolve_linkrole('source', 'py/foo/bar.py')")
|
||||||
|
|
||||||
|
|
||||||
def pytest_funcarg__testdir(request):
|
|
||||||
testdir = request.call_next_provider()
|
|
||||||
testdir.makepyfile(confrest="from py.__.misc.rest import Project")
|
|
||||||
testdir.plugins.append(RestdocPlugin())
|
|
||||||
count = 0
|
|
||||||
for p in testdir.plugins:
|
|
||||||
if isinstance(p, RestdocPlugin):
|
|
||||||
count += 1
|
|
||||||
assert count < 2
|
|
||||||
return testdir
|
|
||||||
|
|
||||||
class TestDoctest:
|
class TestDoctest:
|
||||||
|
def pytest_funcarg__testdir(self, request):
|
||||||
|
testdir = request.call_next_provider()
|
||||||
|
assert request.module.__name__ == __name__
|
||||||
|
testdir.makepyfile(confrest="from py.__.misc.rest import Project")
|
||||||
|
for p in testdir.plugins:
|
||||||
|
if p == globals():
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
testdir.plugins.append(globals())
|
||||||
|
return testdir
|
||||||
|
|
||||||
def test_doctest_extra_exec(self, testdir):
|
def test_doctest_extra_exec(self, testdir):
|
||||||
xtxt = testdir.maketxtfile(x="""
|
xtxt = testdir.maketxtfile(x="""
|
||||||
hello::
|
hello::
|
||||||
|
|
|
@ -365,7 +365,7 @@ class TestWithFunctionIntegration:
|
||||||
assert 'ValueError' in entry
|
assert 'ValueError' in entry
|
||||||
|
|
||||||
def test_generic(plugintester):
|
def test_generic(plugintester):
|
||||||
plugintester.hookcheck(ResultdbPlugin)
|
plugintester.hookcheck()
|
||||||
testdir = plugintester.testdir()
|
testdir = plugintester.testdir()
|
||||||
testdir.makepyfile("""
|
testdir.makepyfile("""
|
||||||
import py
|
import py
|
||||||
|
|
|
@ -1,26 +1,27 @@
|
||||||
|
"""resultlog plugin for machine-readable logging of test results.
|
||||||
|
Useful for buildbot integration code.
|
||||||
|
"""
|
||||||
|
|
||||||
import py
|
import py
|
||||||
|
|
||||||
class ResultlogPlugin:
|
def pytest_addoption(parser):
|
||||||
"""resultlog plugin for machine-readable logging of test results.
|
group = parser.addgroup("resultlog", "resultlog plugin options")
|
||||||
Useful for buildbot integration code.
|
group.addoption('--resultlog', action="store", dest="resultlog", metavar="path",
|
||||||
"""
|
help="path for machine-readable result log.")
|
||||||
def pytest_addoption(self, parser):
|
|
||||||
group = parser.addgroup("resultlog", "resultlog plugin options")
|
|
||||||
group.addoption('--resultlog', action="store", dest="resultlog", metavar="path",
|
|
||||||
help="path for machine-readable result log.")
|
|
||||||
|
|
||||||
def pytest_configure(self, config):
|
|
||||||
resultlog = config.option.resultlog
|
|
||||||
if resultlog:
|
|
||||||
logfile = open(resultlog, 'w', 1) # line buffered
|
|
||||||
self.resultlog = ResultLog(logfile)
|
|
||||||
config.pluginmanager.register(self.resultlog)
|
|
||||||
|
|
||||||
def pytest_unconfigure(self, config):
|
def pytest_configure(config):
|
||||||
if hasattr(self, 'resultlog'):
|
resultlog = config.option.resultlog
|
||||||
self.resultlog.logfile.close()
|
if resultlog:
|
||||||
del self.resultlog
|
logfile = open(resultlog, 'w', 1) # line buffered
|
||||||
#config.pluginmanager.unregister(self.resultlog)
|
config._resultlog = ResultLog(logfile)
|
||||||
|
config.pluginmanager.register(config._resultlog)
|
||||||
|
|
||||||
|
def pytest_unconfigure(config):
|
||||||
|
resultlog = getattr(config, '_resultlog', None)
|
||||||
|
if resultlog:
|
||||||
|
resultlog.logfile.close()
|
||||||
|
del config.resultlog
|
||||||
|
config.pluginmanager.unregister(resultlog)
|
||||||
|
|
||||||
def generic_path(item):
|
def generic_path(item):
|
||||||
chain = item.listchain()
|
chain = item.listchain()
|
||||||
|
@ -224,7 +225,7 @@ class TestWithFunctionIntegration:
|
||||||
assert 'ValueError' in entry
|
assert 'ValueError' in entry
|
||||||
|
|
||||||
def test_generic(plugintester, LineMatcher):
|
def test_generic(plugintester, LineMatcher):
|
||||||
plugintester.hookcheck(ResultlogPlugin)
|
plugintester.hookcheck()
|
||||||
testdir = plugintester.testdir()
|
testdir = plugintester.testdir()
|
||||||
testdir.plugins.append("resultlog")
|
testdir.plugins.append("resultlog")
|
||||||
testdir.makepyfile("""
|
testdir.makepyfile("""
|
||||||
|
|
|
@ -146,7 +146,7 @@ class SetupState(object):
|
||||||
# ===============================================================================
|
# ===============================================================================
|
||||||
|
|
||||||
def test_generic(plugintester):
|
def test_generic(plugintester):
|
||||||
plugintester.hookcheck(RunnerPlugin())
|
plugintester.hookcheck()
|
||||||
|
|
||||||
class TestSetupState:
|
class TestSetupState:
|
||||||
def test_setup_prepare(self, testdir):
|
def test_setup_prepare(self, testdir):
|
||||||
|
|
|
@ -1,21 +1,19 @@
|
||||||
import py
|
import py
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
class TerminalPlugin(object):
|
def pytest_configure(config):
|
||||||
""" Report a test run to a terminal. """
|
if config.option.collectonly:
|
||||||
def pytest_configure(self, config):
|
reporter = CollectonlyReporter(config)
|
||||||
if config.option.collectonly:
|
else:
|
||||||
self.reporter = CollectonlyReporter(config)
|
reporter = TerminalReporter(config)
|
||||||
else:
|
# XXX see remote.py's XXX
|
||||||
self.reporter = TerminalReporter(config)
|
for attr in 'pytest_terminal_hasmarkup', 'pytest_terminal_fullwidth':
|
||||||
# XXX see remote.py's XXX
|
if hasattr(config, attr):
|
||||||
for attr in 'pytest_terminal_hasmarkup', 'pytest_terminal_fullwidth':
|
#print "SETTING TERMINAL OPTIONS", attr, getattr(config, attr)
|
||||||
if hasattr(config, attr):
|
name = attr.split("_")[-1]
|
||||||
#print "SETTING TERMINAL OPTIONS", attr, getattr(config, attr)
|
assert hasattr(self.reporter._tw, name), name
|
||||||
name = attr.split("_")[-1]
|
setattr(reporter._tw, name, getattr(config, attr))
|
||||||
assert hasattr(self.reporter._tw, name), name
|
config.pluginmanager.register(reporter)
|
||||||
setattr(self.reporter._tw, name, getattr(config, attr))
|
|
||||||
config.pluginmanager.register(self.reporter)
|
|
||||||
|
|
||||||
class TerminalReporter:
|
class TerminalReporter:
|
||||||
def __init__(self, config, file=None):
|
def __init__(self, config, file=None):
|
||||||
|
@ -142,7 +140,6 @@ class TerminalReporter:
|
||||||
|
|
||||||
def pytest_deselected(self, items):
|
def pytest_deselected(self, items):
|
||||||
self.stats.setdefault('deselected', []).append(items)
|
self.stats.setdefault('deselected', []).append(items)
|
||||||
|
|
||||||
|
|
||||||
def pytest_itemstart(self, item, node=None):
|
def pytest_itemstart(self, item, node=None):
|
||||||
if self.config.option.dist != "no":
|
if self.config.option.dist != "no":
|
||||||
|
@ -749,6 +746,6 @@ def test_repr_python_version(monkeypatch):
|
||||||
assert repr_pythonversion() == str(x)
|
assert repr_pythonversion() == str(x)
|
||||||
|
|
||||||
def test_generic(plugintester):
|
def test_generic(plugintester):
|
||||||
plugintester.hookcheck(TerminalPlugin)
|
plugintester.hookcheck()
|
||||||
plugintester.hookcheck(TerminalReporter)
|
plugintester.hookcheck(cls=TerminalReporter)
|
||||||
plugintester.hookcheck(CollectonlyReporter)
|
plugintester.hookcheck(cls=CollectonlyReporter)
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
"""
|
"""
|
||||||
|
provide temporary directories to test functions and methods.
|
||||||
|
|
||||||
example:
|
example:
|
||||||
|
|
||||||
pytest_plugins = "pytest_tmpdir"
|
pytest_plugins = "pytest_tmpdir"
|
||||||
|
@ -9,13 +11,9 @@ example:
|
||||||
"""
|
"""
|
||||||
import py
|
import py
|
||||||
|
|
||||||
class TmpdirPlugin:
|
def pytest_funcarg__tmpdir(request):
|
||||||
""" provide temporary directories to test functions and methods.
|
name = request.function.__name__
|
||||||
"""
|
return request.config.mktemp(name, numbered=True)
|
||||||
|
|
||||||
def pytest_funcarg__tmpdir(self, request):
|
|
||||||
name = request.function.__name__
|
|
||||||
return request.config.mktemp(name, numbered=True)
|
|
||||||
|
|
||||||
# ===============================================================================
|
# ===============================================================================
|
||||||
#
|
#
|
||||||
|
@ -24,13 +22,12 @@ class TmpdirPlugin:
|
||||||
# ===============================================================================
|
# ===============================================================================
|
||||||
#
|
#
|
||||||
def test_generic(plugintester):
|
def test_generic(plugintester):
|
||||||
plugintester.hookcheck(TmpdirPlugin)
|
plugintester.hookcheck()
|
||||||
|
|
||||||
def test_funcarg(testdir):
|
def test_funcarg(testdir):
|
||||||
from py.__.test.funcargs import FuncargRequest
|
from py.__.test.funcargs import FuncargRequest
|
||||||
item = testdir.getitem("def test_func(tmpdir): pass")
|
item = testdir.getitem("def test_func(tmpdir): pass")
|
||||||
plugin = TmpdirPlugin()
|
p = pytest_funcarg__tmpdir(FuncargRequest(item, "tmpdir"))
|
||||||
p = plugin.pytest_funcarg__tmpdir(FuncargRequest(item, "tmpdir"))
|
|
||||||
assert p.check()
|
assert p.check()
|
||||||
bn = p.basename.strip("0123456789-")
|
bn = p.basename.strip("0123456789-")
|
||||||
assert bn.endswith("test_func")
|
assert bn.endswith("test_func")
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
"""
|
"""
|
||||||
automatically collect and run traditional "unittest.py" style tests.
|
automatically discover and run traditional "unittest.py" style tests.
|
||||||
|
|
||||||
you can mix unittest TestCase subclasses and
|
you can mix unittest TestCase subclasses and
|
||||||
py.test style tests in one test module.
|
py.test style tests in one test module.
|
||||||
|
@ -15,12 +15,9 @@ $Id: conftest.py 60979 2009-01-14 22:29:32Z hpk $
|
||||||
"""
|
"""
|
||||||
import py
|
import py
|
||||||
|
|
||||||
class UnittestPlugin:
|
def pytest_pycollect_obj(collector, name, obj):
|
||||||
""" discover and integrate traditional ``unittest.py`` tests.
|
if py.std.inspect.isclass(obj) and issubclass(obj, py.std.unittest.TestCase):
|
||||||
"""
|
return UnitTestCase(name, parent=collector)
|
||||||
def pytest_pycollect_obj(self, collector, name, obj):
|
|
||||||
if py.std.inspect.isclass(obj) and issubclass(obj, py.std.unittest.TestCase):
|
|
||||||
return UnitTestCase(name, parent=collector)
|
|
||||||
|
|
||||||
class UnitTestCase(py.test.collect.Class):
|
class UnitTestCase(py.test.collect.Class):
|
||||||
def collect(self):
|
def collect(self):
|
||||||
|
@ -71,7 +68,7 @@ class UnitTestFunction(py.test.collect.Function):
|
||||||
|
|
||||||
|
|
||||||
def test_generic(plugintester):
|
def test_generic(plugintester):
|
||||||
plugintester.hookcheck(UnittestPlugin)
|
plugintester.hookcheck()
|
||||||
|
|
||||||
def test_simple_unittest(testdir):
|
def test_simple_unittest(testdir):
|
||||||
testpath = testdir.makepyfile("""
|
testpath = testdir.makepyfile("""
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
"""
|
"""
|
||||||
|
mark and report specially about "expected to fail" tests.
|
||||||
|
|
||||||
for marking and reporting "expected to fail" tests.
|
for marking and reporting "expected to fail" tests.
|
||||||
@py.test.mark.xfail("needs refactoring")
|
@py.test.mark.xfail("needs refactoring")
|
||||||
def test_hello():
|
def test_hello():
|
||||||
|
@ -7,48 +9,45 @@ for marking and reporting "expected to fail" tests.
|
||||||
"""
|
"""
|
||||||
import py
|
import py
|
||||||
|
|
||||||
class XfailPlugin(object):
|
def pytest_item_makereport(__call__, item, excinfo, when, outerr):
|
||||||
""" mark and report specially about "expected to fail" tests. """
|
if hasattr(item, 'obj') and hasattr(item.obj, 'func_dict'):
|
||||||
|
if 'xfail' in item.obj.func_dict:
|
||||||
|
res = __call__.execute(firstresult=True)
|
||||||
|
if excinfo:
|
||||||
|
res.skipped = True
|
||||||
|
res.failed = res.passed = False
|
||||||
|
else:
|
||||||
|
res.skipped = res.passed = False
|
||||||
|
res.failed = True
|
||||||
|
return res
|
||||||
|
|
||||||
def pytest_item_makereport(self, __call__, item, excinfo, when, outerr):
|
def pytest_report_teststatus(rep):
|
||||||
if hasattr(item, 'obj') and hasattr(item.obj, 'func_dict'):
|
""" return shortletter and verbose word. """
|
||||||
if 'xfail' in item.obj.func_dict:
|
if 'xfail' in rep.keywords:
|
||||||
res = __call__.execute(firstresult=True)
|
if rep.skipped:
|
||||||
if excinfo:
|
return "xfailed", "x", "xfail"
|
||||||
res.skipped = True
|
elif rep.failed:
|
||||||
res.failed = res.passed = False
|
return "xpassed", "P", "xpass"
|
||||||
else:
|
|
||||||
res.skipped = res.passed = False
|
|
||||||
res.failed = True
|
|
||||||
return res
|
|
||||||
|
|
||||||
def pytest_report_teststatus(self, rep):
|
# a hook implemented called by the terminalreporter instance/plugin
|
||||||
""" return shortletter and verbose word. """
|
def pytest_terminal_summary(terminalreporter):
|
||||||
if 'xfail' in rep.keywords:
|
tr = terminalreporter
|
||||||
if rep.skipped:
|
xfailed = tr.stats.get("xfailed")
|
||||||
return "xfailed", "x", "xfail"
|
if xfailed:
|
||||||
elif rep.failed:
|
tr.write_sep("_", "expected failures")
|
||||||
return "xpassed", "P", "xpass"
|
for event in xfailed:
|
||||||
|
entry = event.longrepr.reprcrash
|
||||||
|
key = entry.path, entry.lineno, entry.message
|
||||||
|
reason = event.longrepr.reprcrash.message
|
||||||
|
modpath = event.colitem.getmodpath(includemodule=True)
|
||||||
|
#tr._tw.line("%s %s:%d: %s" %(modpath, entry.path, entry.lineno, entry.message))
|
||||||
|
tr._tw.line("%s %s:%d: " %(modpath, entry.path, entry.lineno))
|
||||||
|
|
||||||
# a hook implemented called by the terminalreporter instance/plugin
|
xpassed = terminalreporter.stats.get("xpassed")
|
||||||
def pytest_terminal_summary(self, terminalreporter):
|
if xpassed:
|
||||||
tr = terminalreporter
|
tr.write_sep("_", "UNEXPECTEDLY PASSING TESTS")
|
||||||
xfailed = tr.stats.get("xfailed")
|
for event in xpassed:
|
||||||
if xfailed:
|
tr._tw.line("%s: xpassed" %(event.colitem,))
|
||||||
tr.write_sep("_", "expected failures")
|
|
||||||
for event in xfailed:
|
|
||||||
entry = event.longrepr.reprcrash
|
|
||||||
key = entry.path, entry.lineno, entry.message
|
|
||||||
reason = event.longrepr.reprcrash.message
|
|
||||||
modpath = event.colitem.getmodpath(includemodule=True)
|
|
||||||
#tr._tw.line("%s %s:%d: %s" %(modpath, entry.path, entry.lineno, entry.message))
|
|
||||||
tr._tw.line("%s %s:%d: " %(modpath, entry.path, entry.lineno))
|
|
||||||
|
|
||||||
xpassed = terminalreporter.stats.get("xpassed")
|
|
||||||
if xpassed:
|
|
||||||
tr.write_sep("_", "UNEXPECTEDLY PASSING TESTS")
|
|
||||||
for event in xpassed:
|
|
||||||
tr._tw.line("%s: xpassed" %(event.colitem,))
|
|
||||||
|
|
||||||
# ===============================================================================
|
# ===============================================================================
|
||||||
#
|
#
|
||||||
|
@ -57,7 +56,7 @@ class XfailPlugin(object):
|
||||||
# ===============================================================================
|
# ===============================================================================
|
||||||
|
|
||||||
def test_generic(plugintester):
|
def test_generic(plugintester):
|
||||||
plugintester.hookcheck(XfailPlugin)
|
plugintester.hookcheck()
|
||||||
|
|
||||||
def test_xfail(plugintester, linecomp):
|
def test_xfail(plugintester, linecomp):
|
||||||
testdir = plugintester.testdir()
|
testdir = plugintester.testdir()
|
||||||
|
|
|
@ -4,6 +4,10 @@ managing loading and interacting with pytest plugins.
|
||||||
import py
|
import py
|
||||||
from py.__.test.plugin import api
|
from py.__.test.plugin import api
|
||||||
|
|
||||||
|
def check_old_use(mod, modname):
|
||||||
|
clsname = modname[len('pytest_'):].capitalize() + "Plugin"
|
||||||
|
assert not hasattr(mod, clsname), (mod, clsname)
|
||||||
|
|
||||||
class PluginManager(object):
|
class PluginManager(object):
|
||||||
def __init__(self, comregistry=None):
|
def __init__(self, comregistry=None):
|
||||||
if comregistry is None:
|
if comregistry is None:
|
||||||
|
@ -16,14 +20,21 @@ class PluginManager(object):
|
||||||
hookspecs=api.PluginHooks,
|
hookspecs=api.PluginHooks,
|
||||||
registry=self.comregistry)
|
registry=self.comregistry)
|
||||||
|
|
||||||
def register(self, plugin):
|
def register(self, plugin, name=None):
|
||||||
self.hook.pytest_plugin_registered(plugin=plugin)
|
if name is None:
|
||||||
import types
|
name = getattr(plugin, '__name__', id(plugin))
|
||||||
self.comregistry.register(plugin)
|
if name not in self.impname2plugin:
|
||||||
|
self.impname2plugin[name] = plugin
|
||||||
|
self.hook.pytest_plugin_registered(plugin=plugin)
|
||||||
|
self.comregistry.register(plugin)
|
||||||
|
return True
|
||||||
|
|
||||||
def unregister(self, plugin):
|
def unregister(self, plugin):
|
||||||
self.hook.pytest_plugin_unregistered(plugin=plugin)
|
self.hook.pytest_plugin_unregistered(plugin=plugin)
|
||||||
self.comregistry.unregister(plugin)
|
self.comregistry.unregister(plugin)
|
||||||
|
for name, value in self.impname2plugin.items():
|
||||||
|
if value == plugin:
|
||||||
|
del self.impname2plugin[name]
|
||||||
|
|
||||||
def isregistered(self, plugin):
|
def isregistered(self, plugin):
|
||||||
return self.comregistry.isregistered(plugin)
|
return self.comregistry.isregistered(plugin)
|
||||||
|
@ -34,7 +45,7 @@ class PluginManager(object):
|
||||||
# API for bootstrapping
|
# API for bootstrapping
|
||||||
#
|
#
|
||||||
def getplugin(self, importname):
|
def getplugin(self, importname):
|
||||||
impname, clsname = canonical_names(importname)
|
impname = canonical_importname(importname)
|
||||||
return self.impname2plugin[impname]
|
return self.impname2plugin[impname]
|
||||||
|
|
||||||
def _envlist(self, varname):
|
def _envlist(self, varname):
|
||||||
|
@ -54,10 +65,11 @@ class PluginManager(object):
|
||||||
|
|
||||||
def consider_conftest(self, conftestmodule):
|
def consider_conftest(self, conftestmodule):
|
||||||
cls = getattr(conftestmodule, 'ConftestPlugin', None)
|
cls = getattr(conftestmodule, 'ConftestPlugin', None)
|
||||||
if cls is not None and cls not in self.impname2plugin:
|
if cls is not None:
|
||||||
self.impname2plugin[cls] = True
|
raise ValueError("%r: 'ConftestPlugins' only existed till 1.0.0b1, "
|
||||||
self.register(cls())
|
"were removed in 1.0.0b2" % (cls,))
|
||||||
self.consider_module(conftestmodule)
|
if self.register(conftestmodule, name=conftestmodule.__file__):
|
||||||
|
self.consider_module(conftestmodule)
|
||||||
|
|
||||||
def consider_module(self, mod):
|
def consider_module(self, mod):
|
||||||
attr = getattr(mod, "pytest_plugins", ())
|
attr = getattr(mod, "pytest_plugins", ())
|
||||||
|
@ -69,12 +81,12 @@ class PluginManager(object):
|
||||||
|
|
||||||
def import_plugin(self, spec):
|
def import_plugin(self, spec):
|
||||||
assert isinstance(spec, str)
|
assert isinstance(spec, str)
|
||||||
modname, clsname = canonical_names(spec)
|
modname = canonical_importname(spec)
|
||||||
if modname in self.impname2plugin:
|
if modname in self.impname2plugin:
|
||||||
return
|
return
|
||||||
mod = importplugin(modname)
|
mod = importplugin(modname)
|
||||||
plugin = registerplugin(self.register, mod, clsname)
|
check_old_use(mod, modname)
|
||||||
self.impname2plugin[modname] = plugin
|
self.register(mod)
|
||||||
self.consider_module(mod)
|
self.consider_module(mod)
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
|
@ -131,19 +143,12 @@ class PluginManager(object):
|
||||||
#
|
#
|
||||||
# XXX old code to automatically load classes
|
# XXX old code to automatically load classes
|
||||||
#
|
#
|
||||||
def canonical_names(importspec):
|
def canonical_importname(name):
|
||||||
importspec = importspec.lower()
|
name = name.lower()
|
||||||
modprefix = "pytest_"
|
modprefix = "pytest_"
|
||||||
if not importspec.startswith(modprefix):
|
if not name.startswith(modprefix):
|
||||||
importspec = modprefix + importspec
|
name = modprefix + name
|
||||||
clsname = importspec[len(modprefix):].capitalize() + "Plugin"
|
return name
|
||||||
return importspec, clsname
|
|
||||||
|
|
||||||
def registerplugin(registerfunc, mod, clsname):
|
|
||||||
pluginclass = getattr(mod, clsname)
|
|
||||||
plugin = pluginclass()
|
|
||||||
registerfunc(plugin)
|
|
||||||
return plugin
|
|
||||||
|
|
||||||
def importplugin(importspec):
|
def importplugin(importspec):
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -5,9 +5,8 @@ EXPECTTIMEOUT=10.0
|
||||||
class TestGeneralUsage:
|
class TestGeneralUsage:
|
||||||
def test_config_error(self, testdir):
|
def test_config_error(self, testdir):
|
||||||
testdir.makeconftest("""
|
testdir.makeconftest("""
|
||||||
class ConftestPlugin:
|
def pytest_configure(config):
|
||||||
def pytest_configure(self, config):
|
raise config.Error("hello")
|
||||||
raise config.Error("hello")
|
|
||||||
""")
|
""")
|
||||||
result = testdir.runpytest(testdir.tmpdir)
|
result = testdir.runpytest(testdir.tmpdir)
|
||||||
assert result.ret != 0
|
assert result.ret != 0
|
||||||
|
@ -17,9 +16,8 @@ class TestGeneralUsage:
|
||||||
|
|
||||||
def test_config_preparse_plugin_option(self, testdir):
|
def test_config_preparse_plugin_option(self, testdir):
|
||||||
testdir.makepyfile(pytest_xyz="""
|
testdir.makepyfile(pytest_xyz="""
|
||||||
class XyzPlugin:
|
def pytest_addoption(parser):
|
||||||
def pytest_addoption(self, parser):
|
parser.addoption("--xyz", dest="xyz", action="store")
|
||||||
parser.addoption("--xyz", dest="xyz", action="store")
|
|
||||||
""")
|
""")
|
||||||
testdir.makepyfile(test_one="""
|
testdir.makepyfile(test_one="""
|
||||||
import py
|
import py
|
||||||
|
|
|
@ -193,11 +193,10 @@ class TestCustomConftests:
|
||||||
|
|
||||||
def test_avoid_directory_on_option(self, testdir):
|
def test_avoid_directory_on_option(self, testdir):
|
||||||
testdir.makeconftest("""
|
testdir.makeconftest("""
|
||||||
class ConftestPlugin:
|
def pytest_addoption(parser):
|
||||||
def pytest_addoption(self, parser):
|
parser.addoption("--XX", action="store_true", default=False)
|
||||||
parser.addoption("--XX", action="store_true", default=False)
|
def pytest_collect_recurse(path, parent):
|
||||||
def pytest_collect_recurse(self, path, parent):
|
return parent.config.getvalue("XX")
|
||||||
return parent.config.getvalue("XX")
|
|
||||||
""")
|
""")
|
||||||
testdir.mkdir("hello")
|
testdir.mkdir("hello")
|
||||||
sorter = testdir.inline_run(testdir.tmpdir)
|
sorter = testdir.inline_run(testdir.tmpdir)
|
||||||
|
|
|
@ -19,9 +19,8 @@ def test_getfuncargnames():
|
||||||
class TestFillFuncArgs:
|
class TestFillFuncArgs:
|
||||||
def test_funcarg_lookupfails(self, testdir):
|
def test_funcarg_lookupfails(self, testdir):
|
||||||
testdir.makeconftest("""
|
testdir.makeconftest("""
|
||||||
class ConftestPlugin:
|
def pytest_funcarg__xyzsomething(request):
|
||||||
def pytest_funcarg__xyzsomething(self, request):
|
return 42
|
||||||
return 42
|
|
||||||
""")
|
""")
|
||||||
item = testdir.getitem("def test_func(some): pass")
|
item = testdir.getitem("def test_func(some): pass")
|
||||||
exc = py.test.raises(LookupError, "funcargs.fillfuncargs(item)")
|
exc = py.test.raises(LookupError, "funcargs.fillfuncargs(item)")
|
||||||
|
@ -67,6 +66,19 @@ class TestFillFuncArgs:
|
||||||
funcargs.fillfuncargs(item2)
|
funcargs.fillfuncargs(item2)
|
||||||
assert item2.funcargs['something'] == "test_func"
|
assert item2.funcargs['something'] == "test_func"
|
||||||
|
|
||||||
|
def test_funcarg_lookup_classlevel(self, testdir):
|
||||||
|
p = testdir.makepyfile("""
|
||||||
|
class TestClass:
|
||||||
|
def pytest_funcarg__something(self, request):
|
||||||
|
return request.instance
|
||||||
|
def test_method(self, something):
|
||||||
|
assert something is self
|
||||||
|
""")
|
||||||
|
result = testdir.runpytest(p)
|
||||||
|
assert result.stdout.fnmatch_lines([
|
||||||
|
"*1 passed*"
|
||||||
|
])
|
||||||
|
|
||||||
class TestRequest:
|
class TestRequest:
|
||||||
def test_request_attributes(self, testdir):
|
def test_request_attributes(self, testdir):
|
||||||
item = testdir.getitem("""
|
item = testdir.getitem("""
|
||||||
|
@ -90,6 +102,7 @@ class TestRequest:
|
||||||
""")
|
""")
|
||||||
req = funcargs.FuncargRequest(item, argname="something")
|
req = funcargs.FuncargRequest(item, argname="something")
|
||||||
assert req.cls.__name__ == "TestB"
|
assert req.cls.__name__ == "TestB"
|
||||||
|
assert req.instance.__class__ == req.cls
|
||||||
|
|
||||||
def test_request_contains_funcargs_provider(self, testdir):
|
def test_request_contains_funcargs_provider(self, testdir):
|
||||||
modcol = testdir.getmodulecol("""
|
modcol = testdir.getmodulecol("""
|
||||||
|
@ -284,10 +297,9 @@ class TestGenfuncFunctional:
|
||||||
|
|
||||||
def test_addcall_with_funcargs_two(self, testdir):
|
def test_addcall_with_funcargs_two(self, testdir):
|
||||||
testdir.makeconftest("""
|
testdir.makeconftest("""
|
||||||
class ConftestPlugin:
|
def pytest_generate_tests(metafunc):
|
||||||
def pytest_generate_tests(self, metafunc):
|
assert "arg1" in metafunc.funcargnames
|
||||||
assert "arg1" in metafunc.funcargnames
|
metafunc.addcall(funcargs=dict(arg1=1, arg2=2))
|
||||||
metafunc.addcall(funcargs=dict(arg1=1, arg2=2))
|
|
||||||
""")
|
""")
|
||||||
p = testdir.makepyfile("""
|
p = testdir.makepyfile("""
|
||||||
def pytest_generate_tests(metafunc):
|
def pytest_generate_tests(metafunc):
|
||||||
|
@ -328,10 +340,9 @@ class TestGenfuncFunctional:
|
||||||
|
|
||||||
def test_generate_plugin_and_module(self, testdir):
|
def test_generate_plugin_and_module(self, testdir):
|
||||||
testdir.makeconftest("""
|
testdir.makeconftest("""
|
||||||
class ConftestPlugin:
|
def pytest_generate_tests(metafunc):
|
||||||
def pytest_generate_tests(self, metafunc):
|
assert "arg1" in metafunc.funcargnames
|
||||||
assert "arg1" in metafunc.funcargnames
|
metafunc.addcall(id="world", param=(2,100))
|
||||||
metafunc.addcall(id="world", param=(2,100))
|
|
||||||
""")
|
""")
|
||||||
p = testdir.makepyfile("""
|
p = testdir.makepyfile("""
|
||||||
def pytest_generate_tests(metafunc):
|
def pytest_generate_tests(metafunc):
|
||||||
|
|
|
@ -87,11 +87,10 @@ class TestConfigPickling:
|
||||||
|
|
||||||
def test_config_pickling_customoption(self, testdir):
|
def test_config_pickling_customoption(self, testdir):
|
||||||
testdir.makeconftest("""
|
testdir.makeconftest("""
|
||||||
class ConftestPlugin:
|
def pytest_addoption(parser):
|
||||||
def pytest_addoption(self, parser):
|
group = parser.addgroup("testing group")
|
||||||
group = parser.addgroup("testing group")
|
group.addoption('-G', '--glong', action="store", default=42,
|
||||||
group.addoption('-G', '--glong', action="store", default=42,
|
type="int", dest="gdest", help="g value.")
|
||||||
type="int", dest="gdest", help="g value.")
|
|
||||||
""")
|
""")
|
||||||
config = testdir.parseconfig("-G", "11")
|
config = testdir.parseconfig("-G", "11")
|
||||||
assert config.option.gdest == 11
|
assert config.option.gdest == 11
|
||||||
|
@ -108,11 +107,10 @@ class TestConfigPickling:
|
||||||
tmp = testdir.tmpdir.ensure("w1", "w2", dir=1)
|
tmp = testdir.tmpdir.ensure("w1", "w2", dir=1)
|
||||||
tmp.ensure("__init__.py")
|
tmp.ensure("__init__.py")
|
||||||
tmp.join("conftest.py").write(py.code.Source("""
|
tmp.join("conftest.py").write(py.code.Source("""
|
||||||
class ConftestPlugin:
|
def pytest_addoption(parser):
|
||||||
def pytest_addoption(self, parser):
|
group = parser.addgroup("testing group")
|
||||||
group = parser.addgroup("testing group")
|
group.addoption('-G', '--glong', action="store", default=42,
|
||||||
group.addoption('-G', '--glong', action="store", default=42,
|
type="int", dest="gdest", help="g value.")
|
||||||
type="int", dest="gdest", help="g value.")
|
|
||||||
"""))
|
"""))
|
||||||
config = testdir.parseconfig(tmp, "-G", "11")
|
config = testdir.parseconfig(tmp, "-G", "11")
|
||||||
assert config.option.gdest == 11
|
assert config.option.gdest == 11
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import py, os
|
import py, os
|
||||||
from py.__.test.pluginmanager import PluginManager, canonical_names
|
from py.__.test.pluginmanager import PluginManager, canonical_importname
|
||||||
from py.__.test.pluginmanager import registerplugin, importplugin
|
|
||||||
|
|
||||||
class TestBootstrapping:
|
class TestBootstrapping:
|
||||||
def test_consider_env_fails_to_import(self, monkeypatch):
|
def test_consider_env_fails_to_import(self, monkeypatch):
|
||||||
|
@ -17,7 +16,7 @@ class TestBootstrapping:
|
||||||
def test_consider_env_plugin_instantiation(self, testdir, monkeypatch):
|
def test_consider_env_plugin_instantiation(self, testdir, monkeypatch):
|
||||||
pluginmanager = PluginManager()
|
pluginmanager = PluginManager()
|
||||||
testdir.syspathinsert()
|
testdir.syspathinsert()
|
||||||
testdir.makepyfile(pytest_xy123="class Xy123Plugin: pass")
|
testdir.makepyfile(pytest_xy123="#")
|
||||||
monkeypatch.setitem(os.environ, 'PYTEST_PLUGINS', 'xy123')
|
monkeypatch.setitem(os.environ, 'PYTEST_PLUGINS', 'xy123')
|
||||||
l1 = len(pluginmanager.getplugins())
|
l1 = len(pluginmanager.getplugins())
|
||||||
pluginmanager.consider_env()
|
pluginmanager.consider_env()
|
||||||
|
@ -29,7 +28,7 @@ class TestBootstrapping:
|
||||||
assert l2 == l3
|
assert l2 == l3
|
||||||
|
|
||||||
def test_pluginmanager_ENV_startup(self, testdir, monkeypatch):
|
def test_pluginmanager_ENV_startup(self, testdir, monkeypatch):
|
||||||
x500 = testdir.makepyfile(pytest_x500="class X500Plugin: pass")
|
x500 = testdir.makepyfile(pytest_x500="#")
|
||||||
p = testdir.makepyfile("""
|
p = testdir.makepyfile("""
|
||||||
import py
|
import py
|
||||||
def test_hello():
|
def test_hello():
|
||||||
|
@ -48,59 +47,49 @@ class TestBootstrapping:
|
||||||
|
|
||||||
reset = testdir.syspathinsert()
|
reset = testdir.syspathinsert()
|
||||||
pluginname = "pytest_hello"
|
pluginname = "pytest_hello"
|
||||||
testdir.makepyfile(**{pluginname: """
|
testdir.makepyfile(**{pluginname: ""})
|
||||||
class HelloPlugin:
|
|
||||||
pass
|
|
||||||
"""})
|
|
||||||
pluginmanager.import_plugin("hello")
|
pluginmanager.import_plugin("hello")
|
||||||
len1 = len(pluginmanager.getplugins())
|
len1 = len(pluginmanager.getplugins())
|
||||||
pluginmanager.import_plugin("pytest_hello")
|
pluginmanager.import_plugin("pytest_hello")
|
||||||
len2 = len(pluginmanager.getplugins())
|
len2 = len(pluginmanager.getplugins())
|
||||||
assert len1 == len2
|
assert len1 == len2
|
||||||
plugin1 = pluginmanager.getplugin("pytest_hello")
|
plugin1 = pluginmanager.getplugin("pytest_hello")
|
||||||
assert plugin1.__class__.__name__ == 'HelloPlugin'
|
assert plugin1.__name__.endswith('pytest_hello')
|
||||||
plugin2 = pluginmanager.getplugin("hello")
|
plugin2 = pluginmanager.getplugin("hello")
|
||||||
assert plugin2 is plugin1
|
assert plugin2 is plugin1
|
||||||
|
|
||||||
def test_consider_module(self, testdir):
|
def test_consider_module(self, testdir):
|
||||||
pluginmanager = PluginManager()
|
pluginmanager = PluginManager()
|
||||||
testdir.syspathinsert()
|
testdir.syspathinsert()
|
||||||
testdir.makepyfile(pytest_plug1="class Plug1Plugin: pass")
|
testdir.makepyfile(pytest_plug1="#")
|
||||||
testdir.makepyfile(pytest_plug2="class Plug2Plugin: pass")
|
testdir.makepyfile(pytest_plug2="#")
|
||||||
mod = py.std.new.module("temp")
|
mod = py.std.new.module("temp")
|
||||||
mod.pytest_plugins = ["pytest_plug1", "pytest_plug2"]
|
mod.pytest_plugins = ["pytest_plug1", "pytest_plug2"]
|
||||||
pluginmanager.consider_module(mod)
|
pluginmanager.consider_module(mod)
|
||||||
assert pluginmanager.getplugin("plug1").__class__.__name__ == "Plug1Plugin"
|
assert pluginmanager.getplugin("plug1").__name__ == "pytest_plug1"
|
||||||
assert pluginmanager.getplugin("plug2").__class__.__name__ == "Plug2Plugin"
|
assert pluginmanager.getplugin("plug2").__name__ == "pytest_plug2"
|
||||||
|
|
||||||
def test_consider_module_import_module(self, testdir):
|
def test_consider_module_import_module(self, testdir):
|
||||||
mod = py.std.new.module("x")
|
mod = py.std.new.module("x")
|
||||||
mod.pytest_plugins = "pytest_a"
|
mod.pytest_plugins = "pytest_a"
|
||||||
aplugin = testdir.makepyfile(pytest_a="""class APlugin: pass""")
|
aplugin = testdir.makepyfile(pytest_a="#")
|
||||||
pluginmanager = PluginManager()
|
pluginmanager = PluginManager()
|
||||||
sorter = testdir.geteventrecorder(pluginmanager)
|
sorter = testdir.geteventrecorder(pluginmanager)
|
||||||
#syspath.prepend(aplugin.dirpath())
|
#syspath.prepend(aplugin.dirpath())
|
||||||
py.std.sys.path.insert(0, str(aplugin.dirpath()))
|
py.std.sys.path.insert(0, str(aplugin.dirpath()))
|
||||||
pluginmanager.consider_module(mod)
|
pluginmanager.consider_module(mod)
|
||||||
call = sorter.getcall(pluginmanager.hook.pytest_plugin_registered.name)
|
call = sorter.getcall(pluginmanager.hook.pytest_plugin_registered.name)
|
||||||
assert call.plugin.__class__.__name__ == "APlugin"
|
assert call.plugin.__name__ == "pytest_a"
|
||||||
|
|
||||||
# check that it is not registered twice
|
# check that it is not registered twice
|
||||||
pluginmanager.consider_module(mod)
|
pluginmanager.consider_module(mod)
|
||||||
l = sorter.getcalls("plugin_registered")
|
l = sorter.getcalls("plugin_registered")
|
||||||
assert len(l) == 1
|
assert len(l) == 1
|
||||||
|
|
||||||
def test_consider_conftest(self, testdir):
|
def test_consider_conftest_deprecated(self, testdir):
|
||||||
pp = PluginManager()
|
pp = PluginManager()
|
||||||
mod = testdir.makepyfile("class ConftestPlugin: hello = 1").pyimport()
|
mod = testdir.makepyfile("class ConftestPlugin: pass").pyimport()
|
||||||
pp.consider_conftest(mod)
|
call = py.test.raises(ValueError, pp.consider_conftest, mod)
|
||||||
l = [x for x in pp.getplugins() if isinstance(x, mod.ConftestPlugin)]
|
|
||||||
assert len(l) == 1
|
|
||||||
assert l[0].hello == 1
|
|
||||||
|
|
||||||
pp.consider_conftest(mod)
|
|
||||||
l = [x for x in pp.getplugins() if isinstance(x, mod.ConftestPlugin)]
|
|
||||||
assert len(l) == 1
|
|
||||||
|
|
||||||
def test_config_sets_conftesthandle_onimport(self, testdir):
|
def test_config_sets_conftesthandle_onimport(self, testdir):
|
||||||
config = testdir.parseconfig([])
|
config = testdir.parseconfig([])
|
||||||
|
@ -124,33 +113,16 @@ class TestBootstrapping:
|
||||||
pp.unregister(a2)
|
pp.unregister(a2)
|
||||||
assert not pp.isregistered(a2)
|
assert not pp.isregistered(a2)
|
||||||
|
|
||||||
def test_canonical_names(self):
|
def test_canonical_importname(self):
|
||||||
for name in 'xyz', 'pytest_xyz', 'pytest_Xyz', 'Xyz':
|
for name in 'xyz', 'pytest_xyz', 'pytest_Xyz', 'Xyz':
|
||||||
impname, clsname = canonical_names(name)
|
impname = canonical_importname(name)
|
||||||
assert impname == "pytest_xyz"
|
|
||||||
assert clsname == "XyzPlugin"
|
|
||||||
|
|
||||||
def test_registerplugin(self):
|
|
||||||
l = []
|
|
||||||
registerfunc = l.append
|
|
||||||
registerplugin(registerfunc, py.io, "TerminalWriter")
|
|
||||||
assert len(l) == 1
|
|
||||||
assert isinstance(l[0], py.io.TerminalWriter)
|
|
||||||
|
|
||||||
def test_importplugin(self):
|
|
||||||
assert importplugin("py") == py
|
|
||||||
py.test.raises(ImportError, "importplugin('laksjd.qwe')")
|
|
||||||
mod = importplugin("pytest_terminal")
|
|
||||||
assert mod is py.__.test.plugin.pytest_terminal
|
|
||||||
|
|
||||||
|
|
||||||
class TestPytestPluginInteractions:
|
class TestPytestPluginInteractions:
|
||||||
def test_do_option_conftestplugin(self, testdir):
|
def test_do_option_conftestplugin(self, testdir):
|
||||||
from py.__.test.config import Config
|
from py.__.test.config import Config
|
||||||
p = testdir.makepyfile("""
|
p = testdir.makepyfile("""
|
||||||
class ConftestPlugin:
|
def pytest_addoption(parser):
|
||||||
def pytest_addoption(self, parser):
|
parser.addoption('--test123', action="store_true")
|
||||||
parser.addoption('--test123', action="store_true")
|
|
||||||
""")
|
""")
|
||||||
config = Config()
|
config = Config()
|
||||||
config._conftest.importconftest(p)
|
config._conftest.importconftest(p)
|
||||||
|
@ -165,10 +137,9 @@ class TestPytestPluginInteractions:
|
||||||
config.pluginmanager.do_configure(config=config)
|
config.pluginmanager.do_configure(config=config)
|
||||||
assert not hasattr(config.option, 'test123')
|
assert not hasattr(config.option, 'test123')
|
||||||
p = testdir.makepyfile("""
|
p = testdir.makepyfile("""
|
||||||
class ConftestPlugin:
|
def pytest_addoption(parser):
|
||||||
def pytest_addoption(self, parser):
|
parser.addoption('--test123', action="store_true",
|
||||||
parser.addoption('--test123', action="store_true",
|
default=True)
|
||||||
default=True)
|
|
||||||
""")
|
""")
|
||||||
config._conftest.importconftest(p)
|
config._conftest.importconftest(p)
|
||||||
assert config.option.test123
|
assert config.option.test123
|
||||||
|
|
|
@ -255,6 +255,19 @@ class TestFunction:
|
||||||
assert f5 != f5b
|
assert f5 != f5b
|
||||||
assert not (f5 == f5b)
|
assert not (f5 == f5b)
|
||||||
|
|
||||||
|
class callspec1:
|
||||||
|
param = 1
|
||||||
|
funcargs = {}
|
||||||
|
class callspec2:
|
||||||
|
param = 2
|
||||||
|
funcargs = {}
|
||||||
|
f5 = py.test.collect.Function(name="name", config=config,
|
||||||
|
callspec=callspec1, callobj=isinstance)
|
||||||
|
f5b = py.test.collect.Function(name="name", config=config,
|
||||||
|
callspec=callspec2, callobj=isinstance)
|
||||||
|
assert f5 != f5b
|
||||||
|
assert not (f5 == f5b)
|
||||||
|
|
||||||
class TestSorting:
|
class TestSorting:
|
||||||
def test_check_equality_and_cmp_basic(self, testdir):
|
def test_check_equality_and_cmp_basic(self, testdir):
|
||||||
modcol = testdir.getmodulecol("""
|
modcol = testdir.getmodulecol("""
|
||||||
|
|
|
@ -9,21 +9,20 @@ class TestTracebackCutting:
|
||||||
|
|
||||||
def test_traceback_argsetup(self, testdir):
|
def test_traceback_argsetup(self, testdir):
|
||||||
testdir.makeconftest("""
|
testdir.makeconftest("""
|
||||||
class ConftestPlugin:
|
def pytest_funcarg__hello(request):
|
||||||
def pytest_funcarg__hello(self, request):
|
raise ValueError("xyz")
|
||||||
raise ValueError("xyz")
|
|
||||||
""")
|
""")
|
||||||
p = testdir.makepyfile("def test(hello): pass")
|
p = testdir.makepyfile("def test(hello): pass")
|
||||||
result = testdir.runpytest(p)
|
result = testdir.runpytest(p)
|
||||||
assert result.ret != 0
|
assert result.ret != 0
|
||||||
out = result.stdout.str()
|
out = result.stdout.str()
|
||||||
assert out.find("xyz") != -1
|
assert out.find("xyz") != -1
|
||||||
assert out.find("conftest.py:3: ValueError") != -1
|
assert out.find("conftest.py:2: ValueError") != -1
|
||||||
numentries = out.count("_ _ _") # separator for traceback entries
|
numentries = out.count("_ _ _") # separator for traceback entries
|
||||||
assert numentries == 0
|
assert numentries == 0
|
||||||
|
|
||||||
result = testdir.runpytest("--fulltrace", p)
|
result = testdir.runpytest("--fulltrace", p)
|
||||||
out = result.stdout.str()
|
out = result.stdout.str()
|
||||||
assert out.find("conftest.py:3: ValueError") != -1
|
assert out.find("conftest.py:2: ValueError") != -1
|
||||||
numentries = out.count("_ _ _ _") # separator for traceback entries
|
numentries = out.count("_ _ _ _") # separator for traceback entries
|
||||||
assert numentries >3
|
assert numentries >3
|
||||||
|
|
Loading…
Reference in New Issue