[py-svn] r63628 - in py/trunk/py/test: . plugin testing
hpk at codespeak.net
hpk at codespeak.net
Sat Apr 4 21:06:23 CEST 2009
Author: hpk
Date: Sat Apr 4 21:06:20 2009
New Revision: 63628
Added:
py/trunk/py/test/testing/test_fixture_and_setup.py
- copied, changed from r63589, py/trunk/py/test/testing/test_setup_nested.py
Removed:
py/trunk/py/test/testing/test_setup_nested.py
Modified:
py/trunk/py/test/config.py
py/trunk/py/test/plugin/api.py
py/trunk/py/test/plugin/pytest_pytester.py
py/trunk/py/test/runner.py
Log:
* shuffle SetupState and fixture handling into runner.py
* introduce a itemsetupreport and new setupitem/teardownitem methods.
* more tests
Modified: py/trunk/py/test/config.py
==============================================================================
--- py/trunk/py/test/config.py (original)
+++ py/trunk/py/test/config.py Sat Apr 4 21:06:20 2009
@@ -3,6 +3,7 @@
from py.__.test import parseopt
from py.__.misc.warn import APIWARN
+from py.__.test.runner import SetupState
def ensuretemp(string, dir=1):
""" return temporary directory path with
@@ -312,34 +313,6 @@
else:
return pkgdir.dirpath()
-class SetupState(object):
- """ shared state for setting up/tearing down test items or collectors. """
- def __init__(self):
- self.stack = []
-
- def teardown_all(self):
- while self.stack:
- col = self.stack.pop()
- col.teardown()
-
- def teardown_exact(self, item):
- if self.stack and self.stack[-1] == item:
- col = self.stack.pop()
- col.teardown()
-
- def prepare(self, colitem):
- """ setup objects along the collector chain to the test-method
- Teardown any unneccessary previously setup objects."""
-
- needed_collectors = colitem.listchain()
- while self.stack:
- if self.stack == needed_collectors[:len(self.stack)]:
- break
- col = self.stack.pop()
- col.teardown()
- for col in needed_collectors[len(self.stack):]:
- col.setup()
- self.stack.append(col)
# this is the one per-process instance of py.test configuration
config_per_process = Config(
Modified: py/trunk/py/test/plugin/api.py
==============================================================================
--- py/trunk/py/test/plugin/api.py (original)
+++ py/trunk/py/test/plugin/api.py Sat Apr 4 21:06:20 2009
@@ -85,6 +85,9 @@
def pyevent__itemtestreport(self, event):
""" test has been run. """
+ def pyevent__itemsetupreport(self, rep):
+ """ test has been run. """
+
def pyevent__deselected(self, items):
""" collected items that were deselected (by keyword). """
Modified: py/trunk/py/test/plugin/pytest_pytester.py
==============================================================================
--- py/trunk/py/test/plugin/pytest_pytester.py (original)
+++ py/trunk/py/test/plugin/pytest_pytester.py Sat Apr 4 21:06:20 2009
@@ -74,6 +74,11 @@
if hasattr(self, '_olddir'):
self._olddir.chdir()
+ def geteventrecorder(self, config):
+ evrec = EventRecorder(config.bus)
+ self.pyfuncitem.addfinalizer(lambda: config.bus.unregister(evrec))
+ return evrec
+
def chdir(self):
old = self.tmpdir.chdir()
if not hasattr(self, '_olddir'):
@@ -174,9 +179,12 @@
def getitem(self, source, funcname="test_func"):
modcol = self.getmodulecol(source)
- item = modcol.join(funcname)
- assert item is not None, "%r item not found in module:\n%s" %(funcname, source)
- return item
+ moditems = modcol.collect()
+ for item in modcol.collect():
+ if item.name == funcname:
+ return item
+ else:
+ assert 0, "%r item not found in module:\n%s" %(funcname, source)
def getitems(self, source):
modcol = self.getmodulecol(source)
@@ -284,12 +292,13 @@
for i, event in py.builtin.enumerate(self.events):
if event.name == name:
del self.events[i]
- return event
+ eventparser = self.geteventparser(name)
+ return eventparser(*event.args, **event.kwargs)
raise KeyError("popevent: %r not found in %r" %(name, self.events))
def getevents(self, eventname):
""" return list of ParsedEvent instances matching the given eventname. """
- method = self.geteventmethod(eventname)
+ method = self.geteventparser(eventname)
l = []
for event in self.events:
if event.name == eventname:
@@ -297,23 +306,18 @@
l.append(pevent)
return l
- def geteventmethod(self, eventname):
+ def geteventparser(self, eventname):
mname = "pyevent__" + eventname
method = getattr(api.Events, mname)
args, varargs, varkw, default = inspect.getargspec(method)
assert args[0] == "self"
args = args[1:]
fspec = inspect.formatargspec(args, varargs, varkw, default)
- source = """def %(mname)s%(fspec)s:
- return ParsedEvent(locals())""" % locals()
- print source
- exec source
+ code = py.code.compile("""def %(mname)s%(fspec)s:
+ return ParsedEvent(locals())""" % locals())
+ exec code
return locals()[mname]
-
- def firstparsedevent(self, eventname):
- return self.parsedevents(eventname)[0]
-
def get(self, cls):
l = []
for event in self.events:
Modified: py/trunk/py/test/runner.py
==============================================================================
--- py/trunk/py/test/runner.py (original)
+++ py/trunk/py/test/runner.py Sat Apr 4 21:06:20 2009
@@ -6,7 +6,7 @@
* and generating report events about it
"""
-import py, os, sys
+import py
from py.__.test.outcome import Exit, Skipped
@@ -55,7 +55,6 @@
return CollectionReport(collector, res, excinfo, outerr)
from cPickle import Pickler, Unpickler
-from cStringIO import StringIO
def forked_run_report(item, pdb=None):
EXITSTATUS_TESTEXIT = 4
@@ -66,7 +65,7 @@
try:
testrep = basic_run_report(item)
except (KeyboardInterrupt, Exit):
- os._exit(EXITSTATUS_TESTEXIT)
+ py.std.os._exit(EXITSTATUS_TESTEXIT)
return ipickle.dumps(testrep)
ff = py.process.ForkedFunc(runforked)
@@ -164,3 +163,70 @@
else:
out.line(str(longrepr))
+class ItemSetupReport(BaseReport):
+ """ Test Execution Report. """
+ failed = passed = skipped = False
+
+ def __init__(self, item, excinfo=None, outerr=None):
+ self.item = item
+ self.outerr = outerr
+ if not excinfo:
+ self.passed = True
+ else:
+ if excinfo.errisinstance(Skipped):
+ self.skipped = True
+ else:
+ self.failed = True
+ self.excrepr = item._repr_failure_py(excinfo, outerr)
+
+class SetupState(object):
+ """ shared state for setting up/tearing down test items or collectors. """
+ def __init__(self):
+ self.stack = []
+
+ def teardown_all(self):
+ while self.stack:
+ col = self.stack.pop()
+ col.teardown()
+
+ def teardown_exact(self, item):
+ if self.stack and self.stack[-1] == item:
+ col = self.stack.pop()
+ col.teardown()
+
+ def prepare(self, colitem):
+ """ setup objects along the collector chain to the test-method
+ Teardown any unneccessary previously setup objects."""
+ needed_collectors = colitem.listchain()
+ while self.stack:
+ if self.stack == needed_collectors[:len(self.stack)]:
+ break
+ col = self.stack.pop()
+ col.teardown()
+ for col in needed_collectors[len(self.stack):]:
+ col.setup()
+ self.stack.append(col)
+
+ def fixturecall(self, callable, item):
+ excinfo = None
+ capture = item.config._getcapture()
+ try:
+ try:
+ callable(item)
+ except (KeyboardInterrupt, SystemExit):
+ raise
+ except:
+ excinfo = py.code.ExceptionInfo()
+ finally:
+ outerr = capture.reset()
+ if not excinfo:
+ return True
+ else:
+ rep = ItemSetupReport(item, excinfo, outerr)
+ item.config.pytestplugins.notify("itemsetupreport", rep)
+
+ def setupitem(self, item):
+ return self.fixturecall(self.prepare, item)
+
+ def teardownitem(self, item):
+ self.fixturecall(self.teardown_exact, item)
Copied: py/trunk/py/test/testing/test_fixture_and_setup.py (from r63589, py/trunk/py/test/testing/test_setup_nested.py)
==============================================================================
--- py/trunk/py/test/testing/test_setup_nested.py (original)
+++ py/trunk/py/test/testing/test_fixture_and_setup.py Sat Apr 4 21:06:20 2009
@@ -138,3 +138,74 @@
assert not hasattr(self, 'world')
""")
sorter.assertoutcome(passed=4, failed=0)
+
+from py.__.test.config import SetupState
+
+class TestSetupState:
+ def test_setupitem_works(self, testdir):
+ item = testdir.getitem("""
+ def setup_module(mod):
+ pass
+ def test_func():
+ pass
+ """)
+ evrec = testdir.geteventrecorder(item.config)
+ setup = SetupState()
+ res = setup.setupitem(item)
+ assert res
+
+ def test_setupitem_fails(self, testdir):
+ item = testdir.getitem("""
+ def setup_module(mod):
+ print "world"
+ raise ValueError(42)
+ def test_func():
+ pass
+ """)
+ evrec = testdir.geteventrecorder(item.config)
+ setup = SetupState()
+ res = setup.setupitem(item)
+ assert not res
+ rep = evrec.popevent("itemsetupreport").rep
+ assert rep.failed
+ assert not rep.skipped
+ assert rep.excrepr
+ assert "42" in str(rep.excrepr)
+ assert rep.outerr[0].find("world") != -1
+
+ def test_teardownitem_fails(self, testdir):
+ item = testdir.getitem("""
+ def test_func():
+ pass
+ def teardown_function(func):
+ print "13"
+ raise ValueError(25)
+ """)
+ evrec = testdir.geteventrecorder(item.config)
+ setup = SetupState()
+ res = setup.setupitem(item)
+ assert res
+ setup.teardownitem(item)
+ rep = evrec.popevent("itemsetupreport").rep
+ assert rep.item == item
+ assert rep.failed
+ assert not rep.passed
+ assert "13" in rep.outerr[0]
+ assert "25" in str(rep.excrepr)
+
+ def test_setupitem_skips(self, testdir):
+ item = testdir.getitem("""
+ import py
+ def setup_module(mod):
+ py.test.skip("17")
+ def test_func():
+ pass
+ """)
+ evrec = testdir.geteventrecorder(item.config)
+ setup = SetupState()
+ setup.setupitem(item)
+ rep = evrec.popevent("itemsetupreport").rep
+ assert not rep.failed
+ assert rep.skipped
+ assert rep.excrepr
+ assert "17" in str(rep.excrepr)
Deleted: /py/trunk/py/test/testing/test_setup_nested.py
==============================================================================
--- /py/trunk/py/test/testing/test_setup_nested.py Sat Apr 4 21:06:20 2009
+++ (empty file)
@@ -1,140 +0,0 @@
-#
-# test correct setup/teardowns at
-# module, class, and instance level
-
-def test_module_and_function_setup(testdir):
- sorter = testdir.inline_runsource("""
- modlevel = []
- def setup_module(module):
- assert not modlevel
- module.modlevel.append(42)
-
- def teardown_module(module):
- modlevel.pop()
-
- def setup_function(function):
- function.answer = 17
-
- def teardown_function(function):
- del function.answer
-
- def test_modlevel():
- assert modlevel[0] == 42
- assert test_modlevel.answer == 17
-
- class TestFromClass:
- def test_module(self):
- assert modlevel[0] == 42
- assert not hasattr(test_modlevel, 'answer')
- """)
- rep = sorter.getreport("test_modlevel")
- assert rep.passed
- rep = sorter.getreport("test_module")
- assert rep.passed
-
-def test_class_setup(testdir):
- sorter = testdir.inline_runsource("""
- class TestSimpleClassSetup:
- clslevel = []
- def setup_class(cls):
- cls.clslevel.append(23)
-
- def teardown_class(cls):
- cls.clslevel.pop()
-
- def test_classlevel(self):
- assert self.clslevel[0] == 23
-
- class TestInheritedClassSetupStillWorks(TestSimpleClassSetup):
- def test_classlevel_anothertime(self):
- assert self.clslevel == [23]
-
- def test_cleanup():
- assert not TestSimpleClassSetup.clslevel
- assert not TestInheritedClassSetupStillWorks.clslevel
- """)
- sorter.assertoutcome(passed=1+2+1)
-
-def test_method_setup(testdir):
- sorter = testdir.inline_runsource("""
- class TestSetupMethod:
- def setup_method(self, meth):
- self.methsetup = meth
- def teardown_method(self, meth):
- del self.methsetup
-
- def test_some(self):
- assert self.methsetup == self.test_some
-
- def test_other(self):
- assert self.methsetup == self.test_other
- """)
- sorter.assertoutcome(passed=2)
-
-def test_method_generator_setup(testdir):
- sorter = testdir.inline_runsource("""
- class TestSetupTeardownOnInstance:
- def setup_class(cls):
- cls.classsetup = True
-
- def setup_method(self, method):
- self.methsetup = method
-
- def test_generate(self):
- assert self.classsetup
- assert self.methsetup == self.test_generate
- yield self.generated, 5
- yield self.generated, 2
-
- def generated(self, value):
- assert self.classsetup
- assert self.methsetup == self.test_generate
- assert value == 5
- """)
- sorter.assertoutcome(passed=1, failed=1)
-
-def test_func_generator_setup(testdir):
- sorter = testdir.inline_runsource("""
- import sys
-
- def setup_module(mod):
- print "setup_module"
- mod.x = []
-
- def setup_function(fun):
- print "setup_function"
- x.append(1)
-
- def teardown_function(fun):
- print "teardown_function"
- x.pop()
-
- def test_one():
- assert x == [1]
- def check():
- print "check"
- print >>sys.stderr, "e"
- assert x == [1]
- yield check
- assert x == [1]
- """)
- rep = sorter.getreport("test_one")
- assert rep.passed
-
-def test_method_setup_uses_fresh_instances(testdir):
- sorter = testdir.inline_runsource("""
- class TestSelfState1:
- def __init__(self):
- self.hello = 42
- def test_hello(self):
- self.world = 23
- def test_afterhello(self):
- assert not hasattr(self, 'world')
- assert self.hello == 42
- class TestSelfState2:
- def test_hello(self):
- self.world = 10
- def test_world(self):
- assert not hasattr(self, 'world')
- """)
- sorter.assertoutcome(passed=4, failed=0)
More information about the pytest-commit
mailing list