########################################################################
# $Header: /var/local/cvsroot/4Suite/Ft/Lib/TestSuite/TestModule.py,v 1.9 2006/08/11 15:50:12 jkloth Exp $
"""
Provides the TestModule class for wrapping modules/packages.
Copyright 2006 Fourthought, Inc. (USA).
Detailed license and copyright information: http://4suite.org/COPYRIGHT
Project home, documentation, distributions: http://4suite.org/
"""
import os
from Ft.Lib import ImportUtil
import TestLoader, TestFunction, TestMode, TestCoverage
class TestModule(TestLoader.TestLoader):
"""Test object for a module or package."""
def __init__(self, name, module, addModes, skipModes, allModes):
TestLoader.TestLoader.__init__(self, name, module.__name__, addModes,
skipModes, allModes)
self.module = module
self.modes = self.getModes(addModes, skipModes, allModes)
loader = ImportUtil.FindLoader(self.path)
self.isPackage = loader.is_package(self.path)
return
def getModes(self, addModes, skipModes, allModes):
# Create the list of modes we will run
modes = getattr(self.module, 'MODES', [TestMode.DefaultMode()])
run_modes = []
if allModes:
# Use whatever modes are not skipped
for mode in modes:
if mode.name not in skipModes:
run_modes.append(mode)
else:
# Use the specified modes that are not also skipped
for mode in modes:
if mode.name in addModes and mode.name not in skipModes:
run_modes.append(mode)
# If no specified modes found, use the default
if not run_modes:
for mode in modes:
if mode.default and mode.name not in skipModes:
run_modes.append(mode)
return run_modes
def getTests(self):
"""
Get the test objects contained within this module.
"""
# If there are no cached results, gather the sub-tests based on
# the type of module.
if not self.tests:
# Get the test function(s) defined in this module
for name in dir(self.module):
if name == 'Test': #name.startswith('Test'):
obj = getattr(self.module, name)
if callable(obj):
self.tests.append(TestFunction.TestFunction(obj))
# If this is a package, get the available modules
if self.isPackage:
files = []
dirs = []
path = ImportUtil.GetSearchPath(self.path)
for importer, name, ispkg in ImportUtil.IterModules(path):
if ispkg:
dirs.append(name)
else:
files.append(name)
# Default running order is alphabetical
dirs.sort()
files.sort()
# Let the module manipulate the test lists
if hasattr(self.module, 'PreprocessFiles'):
(dirs, files) = self.module.PreprocessFiles(dirs, files)
# Add the test lists to our available tests
for name in dirs + files:
self.addTest(name)
# If this modules defines a CoverageModule, add the coverage
# start and end functions.
if hasattr(self.module, 'CoverageModule'):
ignored = None
if hasattr(self.module,'CoverageIgnored'):
ignored = self.module.CoverageIgnored
ct = TestCoverage.TestCoverage(self.module.CoverageModule,ignored)
self.tests.insert(0, TestFunction.TestFunction(ct._start))
self.tests.append(TestFunction.TestFunction(ct._end))
return self.tests
def showTests(self, indent):
if self.isPackage:
# A package
print '%s%s%s' % (indent, self.name, os.sep)
new_indent = indent + ' '*2
for test in self.getTests():
test.showTests(new_indent)
else:
# A simple module
print '%s%s' % (indent, self.name)
return
def run(self, tester):
# Determine the modes
tester.startGroup(self.name)
modes = []
for mode in self.modes:
if mode.initialize(tester):
modes.append(mode)
if not modes:
tester.warning("All modes have been skipped")
for mode in modes:
mode.start(tester)
try:
have_run = 0
for test in self.getTests():
self.runTest(tester, test)
have_run = 1
if not have_run:
tester.warning('Module does define any tests')
finally:
mode.finish(tester)
tester.groupDone()
return
def runTest(self, tester, testObject):
# Saved to check for misbehaving tests
depth = len(tester.groups)
# Run the test
try:
testObject.run(tester)
except (KeyboardInterrupt, SystemExit):
raise
except:
tester.exception('Unhandled exception in test')
# Clean up for the interrupted test
if tester.test:
tester.testDone()
while len(tester.groups) > depth:
tester.groupDone()
return
if tester.test:
tester.warning('Failed to finish test (fixed)')
tester.testDone()
# Verify proper group count
count = len(tester.groups) - depth
if count < 0:
tester.error('Closed too many groups')
elif count > 0:
tester.warning('Failed to close %d groups (fixed)' % count)
while count:
count -= 1
tester.message('Closing group %s' % tester.groups[-1])
tester.groupDone()
return
|