[svn r63932] * Fixed broken setup_method()-mechanism.

* Added --twisted-logging option.
* Added example test-script to the plugin-test.

--HG--
branch : trunk
This commit is contained in:
mzeidler 2009-04-10 13:12:04 +02:00
parent 0b554bf925
commit 59bd09ce9a
1 changed files with 131 additions and 40 deletions

View File

@ -1,15 +1,16 @@
""" """
Notes: twisted's asynchrone behavior may have influence on the order of test-functions
TODO: TODO:
+ switching on this plugin breaks 'setup_method' mechanism which then is not previously called before the test function.
+ credits to Ralf Schmitt See: http://twistedmatrix.com/pipermail/twisted-python/2007-February/014872.html + credits to Ralf Schmitt See: http://twistedmatrix.com/pipermail/twisted-python/2007-February/014872.html
+ add option for twisted logging + get test to work
+ write tests
""" """
import os import os
import sys import sys
import py import py
try: try:
from twisted.internet.defer import Deferred from twisted.internet.defer import Deferred
except ImportError: except ImportError:
@ -22,10 +23,10 @@ except ImportError:
"http://pypi.python.org/pypi/greenlet" "http://pypi.python.org/pypi/greenlet"
sys.exit(0) sys.exit(0)
DIR_CUR = str(py.path.local())
def _start_twisted_logging(): def _start_twisted_logging():
"""Enables twisted internal logging"""
class Logger(object): class Logger(object):
"""late-bound sys.stdout""" """late-bound sys.stdout"""
def write(self, msg): def write(self, msg):
@ -34,31 +35,38 @@ def _start_twisted_logging():
def flush(self): def flush(self):
sys.stdout.flush() sys.stdout.flush()
# sys.stdout will be changed by py.test later. # sys.stdout will be changed by py.test later.
import twisted.python.log import twisted.python.log
twisted.python.log.startLogging(Logger(), setStdout=0) twisted.python.log.startLogging(Logger(), setStdout=0)
def _run_twisted(): def _run_twisted(logging=False):
"""greenlet: run twisted mainloop""" """Start twisted mainloop and initialize recursive calling of doit()."""
from twisted.internet import reactor, defer from twisted.internet import reactor, defer
from twisted.python import log, failure from twisted.python import log, failure
failure.Failure.cleanFailure = lambda *args: None # make twisted copy traceback... # make twisted copy traceback...
_start_twisted_logging() # XXX: add py.test option failure.Failure.cleanFailure = lambda *args: None
if logging:
def doit(val): _start_twisted_logging()
# recursively called for each test-function/method due done()
def doit(val): # val always None
# switch context to wait that wrapper() passes back to test-method
res = gr_tests.switch(val) res = gr_tests.switch(val)
if res is None: if res is None:
reactor.stop() reactor.stop()
return return
def done(res): def done(res):
reactor.callLater(0.0, doit, None) reactor.callLater(0.0, doit, None) # recursive call of doit()
def err(res): def err(res):
reactor.callLater(0.0, doit, res) reactor.callLater(0.0, doit, res)
# the test-function *may* return a deferred
# here the test-function will actually been called
# done() is finalizing a test-process by assureing recursive envoking
# of doit()
defer.maybeDeferred(res).addCallback(done).addErrback(err) defer.maybeDeferred(res).addCallback(done).addErrback(err)
# initialy preparing the calling of doit() and starting the reactor
reactor.callLater(0.0, doit, None) reactor.callLater(0.0, doit, None)
reactor.run() reactor.run()
@ -67,26 +75,41 @@ class TwistedPlugin:
"""Allows to test twisted applications with pytest.""" """Allows to test twisted applications with pytest."""
def pytest_addoption(self, parser): def pytest_addoption(self, parser):
parser.addoption("--twisted", dest="twisted", #parser.addoption("--twisted", dest="twisted",
help="Allows to test twisted applications with pytest.") # help="Allows to test twisted applications with pytest.")
group = parser.addgroup('twisted options')
group.addoption('-T', action='store_true', default=False,
dest = 'twisted',
help="Allows to test twisted applications.")
group.addoption('--twisted-logging', action='store', default=False,
dest='twisted_logging',
help="switch on twisted internal logging")
self.twisted = False
def pytest_configure(self, config): def pytest_configure(self, config):
twisted = config.getvalue("twisted") twisted = config.getvalue("twisted")
twisted_logging = config.getvalue("twisted_logging")
if twisted: if twisted:
print "Twisted plugin switched on" self.twisted = True
gr_twisted.switch() gr_twisted.switch(twisted_logging)
def pytest_unconfigure(self, config): def pytest_unconfigure(self, config):
if self.twisted:
gr_twisted.switch(None) gr_twisted.switch(None)
def pytest_pyfunc_call(self, pyfuncitem, *args, **kwargs): def pytest_pyfunc_call(self, pyfuncitem, *args, **kwargs):
if self.twisted:
def wrapper(func): def wrapper(func):
res = func.obj() """
if isinstance(res, Deferred): wrapper just to pass back (injecting) the test-function into
res = gr_twisted.switch(func.obj) doit() by using a greenlet switch.
"""
if hasattr(func, 'obj'):
# XXX: what about **kwargs?
res = gr_twisted.switch(lambda: func.obj(*args))
if res: if res:
res.raiseException() res.raiseException()
return res
pyfuncitem = wrapper(pyfuncitem) pyfuncitem = wrapper(pyfuncitem)
@ -97,19 +120,87 @@ gr_tests = greenlet.getcurrent()
# plugin tests # plugin tests
# =============================================================================== # ===============================================================================
# XXX: write test
'''
def test_generic(plugintester): def test_generic(plugintester):
plugintester.apicheck(EventlogPlugin) plugintester.apicheck(TwistedPlugin)
testdir = plugintester.testdir() testdir = plugintester.testdir()
testdir.makepyfile(""" testdir.makepyfile('''
def test_pass(): def test_pass():
pass pass
""") from twisted.internet import defer, reactor
testdir.runpytest("--twisted") from twisted.python import failure
s = testdir.tmpdir.join("event.log").read() from twisted.python import log
assert s.find("TestrunStart") != -1
assert s.find("ItemTestReport") != -1
assert s.find("TestrunFinish") != -1 def test_no_deferred():
''' assert True is True
def test_deferred():
log.msg("test_deferred() called")
d = defer.Deferred()
def done():
log.msg("test_deferred.done() CALLBACK DONE")
d.callback(None)
reactor.callLater(2.5, done)
log.msg("test_deferred() returning deferred: %r" % (d,))
return d
def test_deferred2():
log.msg("test_deferred2() called")
d = defer.Deferred()
def done():
log.msg("test_deferred2.done() CALLBACK DONE")
d.callback(None)
reactor.callLater(2.5, done)
log.msg("test_deferred2() returning deferred: %r" % (d,))
return d
def test_deferred4():
log.msg("test_deferred4() called")
from twisted.web.client import getPage
def printContents(contents):
assert contents == ""
deferred = getPage('http://twistedmatrix.com/')
deferred.addCallback(printContents)
return deferred
def test_deferred3():
log.msg("test_deferred3() called")
d = defer.Deferred()
def done():
log.msg("test_deferred3.done() CALLBACK DONE")
d.callback(None)
reactor.callLater(2.5, done)
log.msg("test_deferred3() returning deferred: %r" % (d,))
return d
class TestTwistedSetupMethod:
def setup_method(self, method):
log.msg("TestTwistedSetupMethod.setup_method() called")
def test_deferred(self):
log.msg("TestTwistedSetupMethod.test_deferred() called")
d = defer.Deferred()
def done():
log.msg("TestTwistedSetupMethod.test_deferred() CALLBACK DONE")
d.callback(None)
reactor.callLater(2.5, done)
log.msg("TestTwistedSetupMethod.test_deferred() returning deferred: %r" % (d,))
return d
def test_defer_fail():
def fun():
log.msg("provoking NameError")
rsdfg
return defer.maybeDeferred(fun)
''')
testdir.runpytest("-T")
# XXX: what to do?
# s = testdir.tmpdir.join("event.log").read()
# assert s.find("TestrunFinish") != -1