plugin cleanups

* make pytest_eventlog.py work again by adding a hack to the registry, rename
* disable resultdb hook plugin, it needs merging with resultlog
* add some docstrings, streamline bits

--HG--
branch : trunk
This commit is contained in:
holger krekel 2009-05-20 23:12:37 +02:00
parent 219e627f87
commit d1f24aa251
17 changed files with 129 additions and 118 deletions

View File

@ -63,6 +63,7 @@ class Registry:
"""
Manage Plugins: Load plugins and manage calls to plugins.
"""
logfile = None
MultiCall = MultiCall
def __init__(self, plugins=None):
@ -130,6 +131,11 @@ class HookCall:
"for api call to %r" % self.name)
attr = self.registry.listattr(self.name, extra=self.extralookup)
mc = MultiCall(attr, **kwargs)
# XXX this should be doable from a hook impl:
if self.registry.logfile:
self.registry.logfile.write("%s(**%s) # firstresult=%s\n" %
(self.name, kwargs, self.firstresult))
self.registry.logfile.flush()
return mc.execute(firstresult=self.firstresult)
comregistry = Registry()

View File

@ -18,6 +18,7 @@ def pytest_funcarg__testdir(request):
basename = request.module.__name__.split(".")[-1]
if basename.startswith("pytest_"):
testdir.plugins.append(vars(request.module))
testdir.plugins.append(basename)
else:
pass # raise ValueError("need better support code")
return testdir

View File

@ -1,4 +1,9 @@
"""
automatically collect and execute doctests.
"""
import py
from py.__.code.excinfo import Repr, ReprFileLocation
def pytest_addoption(parser):
group = parser.addgroup("doctest options")
@ -13,8 +18,6 @@ def pytest_collect_file(path, parent):
if path.check(fnmatch="test_*.txt"):
return DoctestTextfile(path, parent)
from py.__.code.excinfo import Repr, ReprFileLocation
class ReprFailDoctest(Repr):
def __init__(self, reprlocation, lines):
self.reprlocation = reprlocation

View File

@ -1,45 +0,0 @@
import py
""" expected to fail.
"""
class EventlogPlugin:
""" log pytest events to a file. """
def pytest_addoption(self, parser):
parser.addoption("--eventlog", dest="eventlog",
help="write all pytest events to the given file.")
def pytest_configure(self, config):
eventlog = config.getvalue("eventlog")
if eventlog:
self.eventlogfile = open(eventlog, 'w')
def pytest_unconfigure(self, config):
if hasattr(self, 'eventlogfile'):
self.eventlogfile.close()
del self.eventlogfile
def pyevent(self, eventname, args, kwargs):
if hasattr(self, 'eventlogfile'):
f = self.eventlogfile
print >>f, eventname, args, kwargs
f.flush()
# ===============================================================================
# plugin tests
# ===============================================================================
@py.test.mark.xfail
def test_generic(plugintester):
plugintester.hookcheck()
testdir = plugintester.testdir()
testdir.makepyfile("""
def test_pass():
pass
""")
testdir.runpytest("--eventlog=event.log")
s = testdir.tmpdir.join("event.log").read()
assert s.find("testrunstart") != -1
assert s.find("ItemTestReport") != -1
assert s.find("testrunfinish") != -1

View File

@ -1,3 +1,6 @@
"""
cleanup gateways that were instantiated during a test function run.
"""
import py
def pytest_configure(config):

View File

@ -1,3 +1,6 @@
"""
write and report coverage data using the 'figleaf' module.
"""
import py
figleaf = py.test.importorskip("figleaf")

View File

@ -0,0 +1,36 @@
""" log calling of plugin hooks to a file. """
import py
def pytest_addoption(parser):
parser.addoption("--hooklog", dest="hooklog", default=None,
help="write hook calls to the given file.")
def pytest_configure(config):
hooklog = config.getvalue("hooklog")
if hooklog:
assert not config.pluginmanager.comregistry.logfile
config.pluginmanager.comregistry.logfile = open(hooklog, 'w')
def pytest_unconfigure(config):
f = config.pluginmanager.comregistry.logfile
if f:
f.close()
config.pluginmanager.comregistry.logfile = None
# ===============================================================================
# plugin tests
# ===============================================================================
def test_generic(plugintester):
plugintester.hookcheck()
def test_functional(testdir):
testdir.makepyfile("""
def test_pass():
pass
""")
testdir.runpytest("--hooklog=hook.log")
s = testdir.tmpdir.join("hook.log").read()
assert s.find("pytest_testrunstart") != -1
assert s.find("ItemTestReport") != -1
assert s.find("testrunfinish") != -1

View File

@ -1,12 +1,22 @@
"""
'capsys' and 'capfd' funcargs for capturing stdout/stderror either
by intercepting sys.stdout/stderr or File Descriptors 1/2.
Calling the reset() method of the capture funcargs gives
a out/err tuple of strings representing the captured streams.
You can call reset() multiple times each time getting
the chunk of output that was captured between the invocations.
"""
import py
def pytest_funcarg__stdcapture(request):
def pytest_funcarg__capsys(request):
""" capture writes to sys.stdout/sys.stderr. """
capture = Capture(py.io.StdCapture)
request.addfinalizer(capture.finalize)
return capture
def pytest_funcarg__stdcapturefd(request):
def pytest_funcarg__capfd(request):
""" capture writes to filedescriptors 1 and 2"""
capture = Capture(py.io.StdCaptureFD)
request.addfinalizer(capture.finalize)
@ -31,19 +41,19 @@ def test_generic(plugintester):
class TestCapture:
def test_std_functional(self, testdir):
reprec = testdir.inline_runsource("""
def test_hello(stdcapture):
def test_hello(capsys):
print 42
out, err = stdcapture.reset()
out, err = capsys.reset()
assert out.startswith("42")
""")
reprec.assertoutcome(passed=1)
def test_stdfd_functional(self, testdir):
reprec = testdir.inline_runsource("""
def test_hello(stdcapturefd):
def test_hello(capfd):
import os
os.write(1, "42")
out, err = stdcapturefd.reset()
out, err = capfd.reset()
assert out.startswith("42")
""")
reprec.assertoutcome(passed=1)

View File

@ -1,17 +1,15 @@
import os
"""
provides the "monkeypatch" funcarg for safely patching objects,
"monkeypatch" funcarg for safely patching objects,
dictionaries and environment variables during the execution of
a test. There are three helper functions:
a test. "monkeypatch" has three helper functions:
monkeypatch.setattr(obj, name, value)
monkeypatch.setitem(obj, name, value)
monkeypatch.setenv(name, value)
After the test run all such modifications will be undone,
which may even mean deleting the attribute or dictionary entry
if it didn't exist before.
After the test has run modifications will be undone.
"""
import os
def pytest_funcarg__monkeypatch(request):
monkeypatch = MonkeyPatch()

View File

@ -1,3 +1,4 @@
""" XXX should be used sometime. """
from py.__.test.custompdb import post_mortem
def pytest_item_runtest_finished(item, excinfo, outerr):

View File

@ -1,6 +1,5 @@
"""pylint plugin
XXX: Currently in progress, NOT IN WORKING STATE.
"""
import py

View File

@ -1,5 +1,5 @@
"""
pytes plugin for easing testing of pytest runs themselves.
funcargs and support code for testing py.test functionality.
"""
import py

View File

@ -1,8 +1,5 @@
"""
provides "recwarn" funcarg for asserting warnings to be shown
to a user. See the test at the bottom for an example.
"recwarn" funcarg for asserting that warnings are shown to a user.
"""
import py
import os

View File

@ -1,3 +1,7 @@
"""
perform ReST specific tests on .txt files, including
linkchecks and remote URL checks.
"""
import py
def pytest_addoption(parser):

View File

@ -1,54 +1,51 @@
"""XXX in progress: resultdb plugin for database logging of test results.
Saves test results to a datastore.
XXX this needs to be merged with resultlog plugin
Also mixes in some early ideas about an archive abstraction for test
results.
"""
import py
py.test.skip("XXX needs to be merged with resultlog")
from pytest_resultlog import ResultLog
class ResultdbPlugin:
"""XXX in progress: resultdb plugin for database logging of test results.
def pytest_addoption(parser):
group = parser.addgroup("resultdb", "resultdb plugin options")
group.addoption('--resultdb', action="store", dest="resultdb",
metavar="path",
help="path to the file to store test results.")
group.addoption('--resultdb_format', action="store",
dest="resultdbformat", default='json',
help="data format (json, sqlite)")
Saves test results to a datastore.
XXX this needs to be merged with resultlog plugin
Also mixes in some early ideas about an archive abstraction for test
results.
"""
def pytest_addoption(self, parser):
group = parser.addgroup("resultdb", "resultdb plugin options")
group.addoption('--resultdb', action="store", dest="resultdb",
metavar="path",
help="path to the file to store test results.")
group.addoption('--resultdb_format', action="store",
dest="resultdbformat", default='json',
help="data format (json, sqlite)")
def pytest_configure(self, config):
if config.getvalue('resultdb'):
if config.option.resultdb:
# local import so missing module won't crash py.test
try:
import sqlite3
except ImportError:
raise config.Error('Could not import sqlite3 module')
try:
import simplejson
except ImportError:
raise config.Error('Could not import simplejson module')
if config.option.resultdbformat.lower() == 'json':
self.resultdb = ResultDB(JSONResultArchive,
config.option.resultdb)
elif config.option.resultdbformat.lower() == 'sqlite':
self.resultdb = ResultDB(SQLiteResultArchive,
config.option.resultdb)
else:
raise config.Error('Unknown --resultdb_format: %s' %
config.option.resultdbformat)
config.pluginmanager.register(self.resultdb)
def pytest_unconfigure(self, config):
if hasattr(self, 'resultdb'):
del self.resultdb
#config.pluginmanager.unregister(self.resultdb)
def pytest_configure(config):
# XXX using config.XYZ is not good
if config.getvalue('resultdb'):
if config.option.resultdb:
# local import so missing module won't crash py.test
try:
import sqlite3
except ImportError:
raise config.Error('Could not import sqlite3 module')
try:
import simplejson
except ImportError:
raise config.Error('Could not import simplejson module')
if config.option.resultdbformat.lower() == 'json':
resultdb = ResultDB(JSONResultArchive,
config.option.resultdb)
elif config.option.resultdbformat.lower() == 'sqlite':
resultdb = ResultDB(SQLiteResultArchive,
config.option.resultdb)
else:
raise config.Error('Unknown --resultdb_format: %s' %
config.option.resultdbformat)
config.pluginmanager.register(resultdb)
class JSONResultArchive(object):
def __init__(self, archive_path):
@ -328,8 +325,7 @@ class TestWithFunctionIntegration:
assert x.startswith(" ")
assert "XXX" in "".join(lines[1:])
def test_log_test_outcomes(self, plugintester):
testdir = plugintester.testdir()
def test_log_test_outcomes(self, testdir):
mod = testdir.makepyfile(test_mod="""
import py
def test_pass(): pass

View File

@ -10,8 +10,6 @@ this code is somewhat derived from Guido Wesdorps
http://johnnydebris.net/svn/projects/py_unittest
$HeadURL: https://codespeak.net/svn/py/branch/pytestplugin/contrib/py_unittest/conftest.py $
$Id: conftest.py 60979 2009-01-14 22:29:32Z hpk $
"""
import py

View File

@ -1,7 +1,8 @@
"""
mark and report specially about "expected to fail" tests.
mark tests as expected-to-fail and report them separately.
example:
for marking and reporting "expected to fail" tests.
@py.test.mark.xfail("needs refactoring")
def test_hello():
...
@ -29,7 +30,7 @@ def pytest_report_teststatus(rep):
elif rep.failed:
return "xpassed", "P", "xpass"
# a hook implemented called by the terminalreporter instance/plugin
# called by the terminalreporter instance/plugin
def pytest_terminal_summary(terminalreporter):
tr = terminalreporter
xfailed = tr.stats.get("xfailed")