PDOS

[uia] / trunk / uia / lib / basic_test.py  

View of /trunk/uia/lib/basic_test.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2519 - (download) (as text) (annotate)
Wed May 30 21:56:24 2007 UTC (2 years, 5 months ago) by ctl
File size: 5263 byte(s)
move basic_test into top lib directory.

#! /usr/bin/python
'''
basic_test.py

A small, self-contained module which can be a primitive test harness for
modules whose test suites are designed for the more sophisticated `py.test`
module.

Usage:

  In a Python module, add the following lines to the end::

    if __name__ == '__main__':
      import basic_test
      basic_test.main()

  Or, basic_test can be used as a standalone program:

    python basic_test.py some_module.py
'''

__all__ = [ 'main' ]

import sys
import os
import types

try:
  from cStringIO import StringIO
except ImportError:
  from StringIO import StringIO


status = sys.stdout


# Compatibility layer: implement minimal py.test functionality.
class py:
  _name = 'py'
  class test:
    _name = 'py.test'

    @staticmethod
    def raises( expected_exception, function, *args ):
      try:
        function( *args )
      except expected_exception:
        return
      raise AssertionError( 'expected %s to raise %s exception' % ( function, expected_exception ) )

    class collect:
      _name = 'py.test.collect'
      class Directory:
        'Placeholder stub, has no functionality.'

for m in py, py.test, py.test.collect:
  sys.modules[ m._name ] = m



def main():
  '''Runs any test suites found in the main module.  Usage::
  
    if __name__ == '__main__':
      import basic_test
      basic_test.main()
  '''
  run_module_tests( sys.modules[ '__main__' ] )



def run_module_tests( module ):
  '''Runs any test suites found in the given module.  In particular, searches
  for classes with names beginning with ``Test`` and functions with names
  beginning with ``test``.  See `py.test` for more information on the test case
  interface.'''

  function_types = ( types.FunctionType, types.MethodType )
  class_types = ( types.ClassType, types.TypeType )
  
  # Collect test cases.
  cases = []
  for name, value in module.__dict__.items():
    if name[0:4] == 'test' and isinstance( value, function_types ):
      cases.append( value )
    elif name[0:4] == 'Test' and isinstance( value, class_types ):
      obj = value() # create new class instance
      for subname, subvalue in value.__dict__.items():
        if subname[0:4] == 'test' and isinstance( subvalue, function_types ):
          cases.append( getattr( obj, subname ) )

  # Run test cases.
  name = module.__name__
  if name == '__main__': name = module.__file__
  status.write( '%s [%i] ' % ( name, len( cases ) ) )
  status.flush()
  for case in cases:
    run_test_case( case )
    status.write( '.' )
    status.flush()
  status.write( '\n' )
  status.flush()

    

def run_test_case( case ):
  '''Runs a single test case.'''
  # Capture stdout.
  stdout = sys.stdout
  sys.stdout = StringIO()

  # Try the test case.
  try:
    result = case()
    # Handle test-case generators.
    if isinstance( result, types.GeneratorType ):
      for subcase in result:
        if hasattr( subcase, '__iter__' ):
          subcase = list( subcase )
          subcase[0]( *subcase[1:] )
        else:
          subcase()

  except Exception, x:
    stdout.write( '\nTest failed: %s\n' % case.__name__ )
    output = sys.stdout.getvalue()
    if len( output ) > 0:
      stdout.write( 'Saved output:\n' )
      stdout.write( output )
      stdout.write( '\n' )
    sys.stdout = stdout
    raise

  # Restore stdout.
  sys.stdout = stdout



def standalone( name ):
  '''Runs any test suite found in `name`, which may be a Python module
  name, filename, or a directory.'''
  if os.path.isdir( name ):
    def fail( error ): raise error
    for dir, subdirs, files in os.walk( name, topdown = True, onerror = fail ):
      for file in files:
        filename = os.path.join( dir, file )
        if is_python_file( filename ):
          run_file_tests( filename )
  elif os.path.exists( name ):
    run_file_tests( name )
  else:
    # No such file: assume that name is a module name.
    sys.path.insert( 0, os.curdir )
    module = __import__( name, globals(), locals(), ['__doc__'] )
    run_module_tests( module )

def is_python_file( filename ):
  '''Guess whether the file is a Python module.  Current implementation just
  checks whether the filename extension is '.py'.'''
  root, ext = os.path.splitext( filename )
  return ext.lower() == '.py'

def run_file_tests( filename ):
  '''Run tests found in the given file.'''
  head, extension = os.path.splitext( os.path.abspath( filename ) )
  assert extension == '.py' or extension == ''

  package_root = None
  path = []
  while head != '' and head != '/':
    head, tail = os.path.split( head )
    path.append( tail )
    if os.path.exists( os.path.join( head, 'conftest.py' ) ):
      execfile( os.path.join( head, 'conftest.py' ) )
    if not os.path.exists( os.path.join( head, '__init__.py' ) ):
      package_root = head
      break
  path.reverse()
  name = '.'.join( path )

  if package_root is not None and package_root not in sys.path:
    sys.path.insert( 0, package_root )

  module = __import__( name, globals(), locals(), ['__doc__'] )
  run_module_tests( module )



if __name__ == '__main__':
  if len( sys.argv ) > 2:
    print 'Usage: %s [some_module.py]' % sys.argv[0]
    sys.exit( 1 )

  if len( sys.argv ) > 1:
    standalone( sys.argv[1] )
  else:
    standalone( os.curdir )

Maintained by PDOS
ViewVC Help
Powered by ViewVC 1.0.3