[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:
parent
0b554bf925
commit
59bd09ce9a
|
@ -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,27 +75,42 @@ 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):
|
||||||
gr_twisted.switch(None)
|
if self.twisted:
|
||||||
|
gr_twisted.switch(None)
|
||||||
|
|
||||||
def pytest_pyfunc_call(self, pyfuncitem, *args, **kwargs):
|
def pytest_pyfunc_call(self, pyfuncitem, *args, **kwargs):
|
||||||
def wrapper(func):
|
if self.twisted:
|
||||||
res = func.obj()
|
def wrapper(func):
|
||||||
if isinstance(res, Deferred):
|
"""
|
||||||
res = gr_twisted.switch(func.obj)
|
wrapper just to pass back (injecting) the test-function into
|
||||||
if res:
|
doit() by using a greenlet switch.
|
||||||
res.raiseException()
|
"""
|
||||||
return res
|
if hasattr(func, 'obj'):
|
||||||
pyfuncitem = wrapper(pyfuncitem)
|
# XXX: what about **kwargs?
|
||||||
|
res = gr_twisted.switch(lambda: func.obj(*args))
|
||||||
|
if res:
|
||||||
|
res.raiseException()
|
||||||
|
pyfuncitem = wrapper(pyfuncitem)
|
||||||
|
|
||||||
|
|
||||||
gr_twisted = greenlet(_run_twisted)
|
gr_twisted = greenlet(_run_twisted)
|
||||||
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue