casa  $Rev:20696$
 All Classes Namespaces Files Functions Variables
runUnitTest.py
Go to the documentation of this file.
00001 
00002 """ Script to run unit tests from the command line as: 
00003     casapy [casa-options] -c runUnitTest.py testname1 testname2 ...
00004     casapy [casa-options] -c runUnitTest.py testname1[test_r,test23] testname2...
00005     casapy [casa-options] -c runUnitTest.py --Help
00006     casapy [casa-options] -c runUnitTest.py --list
00007     casapy [casa-options] -c runUnitTest.py --list
00008     casapy [casa-options] -c runUnitTest.py --file Tests.txt
00009     
00010     or from inside casapy:
00011     runUnitTest.main(['testname']) 
00012     runUnitTest.main()
00013     
00014     NOTE: It will search for scripts in the casapy installation directory, which usually is in:
00015            <casa_install_dir>/python/2.6/tests"""
00016 
00017 # The main class in testwrapper.py is:
00018 # class UnitTest, methods: getUnitTest(), getFuncTest()
00019 #
00020 # UnitTest.getUnitTest() --> for new scripts as described in ....doc....
00021 # UnitTest.getFuncTest() --> for old tests, which contain functions data() and run()
00022 
00023 
00024 import os
00025 import sys
00026 import getopt
00027 import traceback
00028 import unittest
00029 import string
00030 import re
00031 import shutil
00032 import nose
00033 from taskinit import casalog
00034 
00035 PYVER = str(sys.version_info[0]) + "." + str(sys.version_info[1])
00036 
00037 CASA_DIR = os.environ["CASAPATH"].split()[0]
00038 TESTS_DIR = CASA_DIR + "/" + os.environ["CASAPATH"].split()[1] + '/python/' + PYVER + '/tests/'
00039 #DATA_DIR = CASA_DIR+'/data/'
00040 #print 'HELLOR DATA_DIR'
00041 #print DATA_DIR
00042 if not os.access(TESTS_DIR, os.F_OK):
00043     if os.access(CASA_DIR+'/lib64', os.F_OK):
00044         TESTS_DIR = CASA_DIR+'/lib64/python' + PYVER + '/tests/'
00045     elif os.access(CASA_DIR+'/lib', os.F_OK):
00046         TESTS_DIR = CASA_DIR+'/lib/python/tests/'
00047     else:            #Mac release
00048         TESTS_DIR = CASA_DIR+'/Resources/python/tests/'
00049 
00050 HAVE_MEMTEST=True
00051 try:
00052     import memTest
00053 except:
00054     HAVE_MEMTEST = False
00055 
00056 import testwrapper
00057 from testwrapper import *
00058 
00059 
00060 # Tests included in the following file are run automatically by
00061 # Hudson. This is also the list of tests run when no options are given
00062 # to this program
00063 LISTofTESTS = TESTS_DIR+'unittests_list.txt'
00064 
00065 
00066 # memory mode variable
00067 MEM = 0
00068 
00069 def usage():
00070     print '========================================================================='
00071     print '\nRunUnitTest will execute Python unit test(s) of CASA tasks.'
00072     print 'Usage:\n'
00073     print 'casapy [casapy-options] -c runUnitTest.py [options] test_name\n'
00074     print 'Options:'
00075     print '  no option              run all tests defined in '
00076     print '                         active/gcwrap/python/scripts/tests/unittests_list.txt.'
00077     print '  <test_name>            run only <test_name> (more tests are separated by spaces).'
00078     print '  -f or --file <list>    run the tests defined in an ASCII file <list>; one test per line.'
00079     print '  -d or --datadir <dir>  set an env. variable to a directory, TEST_DATADIR=<dir> '
00080     print '                         that can be used inside the tests.'
00081     print '  -m or --mem            show the memory used by the tests and the number of files left open.'
00082     print '  -g or --debug          set casalog.filter to DEBUG.'
00083     print '  -l or --list           print the list of tests from '
00084     print '                         active/gcwrap/python/scripts/tests/unittests_list.txt.'
00085     print '  -H or --Help           print this message and exit.\n'
00086     print 'NOTE: it will look for tests in the install directory, which usually is \r'
00087     print '      <casa_install_dir>/python/2.6/tests'
00088     print 'See documentation in: http://www.eso.org/~scastro/ALMA/CASAUnitTests.htm\n'
00089     print '=========================================================================='
00090 
00091 def list_tests():
00092     print 'Full list of unit tests'
00093     print '-----------------------'
00094     for t in readfile(LISTofTESTS):
00095         print t
00096     
00097 
00098 def haslist(name):
00099     '''Check if specific list of tests have been requested'''
00100     n0 = name.rfind('[')
00101     n1 = name.rfind(']')
00102     if n0 == -1:
00103         return False
00104     return True
00105 
00106 def getname(testfile):
00107     '''Get the test name from the command-line
00108        Ex: from test_clean[test1], returns test_clean'''
00109     n0 = testfile.rfind('[')
00110     n1 = testfile.rfind(']')
00111     if n0 != -1:
00112         return testfile[:n0]
00113 
00114 def gettests(testfile):
00115     '''Get the list of specific tests from the command-line
00116        Ex: from test_clean[test1,test3] returns [test1,test3]'''
00117     n0 = testfile.rfind('[')
00118     n1 = testfile.rfind(']')
00119     if n0 != -1:
00120         temp = testfile[n0+1:n1]
00121         tests = temp.split(',')
00122         return tests
00123 
00124 def readfile(FILE):
00125     # It will skip lines that contain '#' and
00126     # it will only read words starting with test
00127     if(not os.path.exists(FILE)):
00128         print 'ERROR: List of tests does not exist'
00129         return []
00130     
00131     List = []
00132     infile = open(FILE, "r")
00133     for newline in infile:
00134         if newline.__contains__('#'):
00135             continue
00136         
00137         if newline.startswith('test'):
00138             words = newline.split()
00139             List.append(words[0])
00140     
00141     infile.close()
00142     return List
00143 
00144 def settestdir(datadir):
00145     '''Set an environmental variable for the data directory'''
00146     absdatadir = os.path.abspath(datadir)
00147     os.environ.__setitem__('TEST_DATADIR',absdatadir)
00148     return
00149 
00150 
00151 # Define which tests to run    
00152 whichtests = 0
00153             
00154 
00155 def main(testnames=[]):
00156 
00157     # Global variable used by regression framework to determine pass/failure status
00158     global regstate  
00159     regstate = False
00160         
00161     listtests = testnames
00162     if listtests == '--Help':
00163         usage()
00164         sys.exit()
00165     if listtests == '--list':
00166         list_tests()
00167         sys.exit()
00168         
00169     if listtests == []:
00170         whichtests = 0
00171         # Get the full list of tests from file
00172         listtests = readfile(LISTofTESTS)
00173         if listtests == []:
00174             raise Exception, 'List of tests \"%s\" is empty or does not exist'%LISTofTESTS
00175 
00176     elif (type(testnames) != type([])):
00177         if (os.path.isfile(testnames)):
00178             # How to prevent it from opening a real test???
00179             whichtests = 1
00180             listtests = readfile(testnames)
00181             if listtests == []:
00182                 raise Exception, 'List of tests is empty'
00183         else:
00184             raise Exception, 'List of tests does not exist'
00185             
00186     else:
00187         # run specific tests
00188         whichtests = 1
00189            
00190 
00191     # Directories
00192     PWD = os.getcwd()
00193     WDIR = PWD+'/nosedir/'
00194     
00195     # Create a working directory
00196     workdir = WDIR
00197     print 'Creating work directory '+ workdir
00198     if os.access(workdir, os.F_OK) is False:
00199         os.makedirs(workdir)
00200     else:
00201         shutil.rmtree(workdir)
00202         os.makedirs(workdir)
00203     
00204     # Move to working dir
00205     os.chdir(workdir)
00206     
00207     # Create a directory for nose's xml files
00208     xmldir = WDIR+'xml/'
00209     if os.access(xmldir, os.F_OK) is False:
00210         os.makedirs(xmldir)
00211     else:
00212         shutil.rmtree(xmldir)
00213         os.makedirs(xmldir)
00214     
00215     print "Starting unit tests for %s: " %(listtests)
00216     
00217     # ASSEMBLE and RUN the TESTS
00218     if not whichtests:
00219         '''Run all tests'''
00220         list = []
00221         
00222         for f in listtests:
00223             try:
00224                 tests = UnitTest(f).getUnitTest()
00225                 list = list+tests
00226             except:
00227                 traceback.print_exc()
00228                     
00229     elif (whichtests == 1):
00230         '''Run specific tests'''
00231         list = []
00232         for f in listtests:
00233             if not haslist(f):
00234                 testcases = UnitTest(f).getUnitTest()
00235                 list = list+testcases
00236             else:
00237                 ff = getname(f)
00238                 tests = gettests(f)
00239                 testcases = UnitTest(ff).getUnitTest(tests)
00240                 list = list+testcases                
00241                 
00242         if (len(list) == 0):
00243             os.chdir(PWD)
00244             raise Exception, 'ERROR: There are no valid tests to run'
00245                                                                      
00246                 
00247     # Run all tests and create a XML report
00248     xmlfile = xmldir+'nose.xml'
00249     try:
00250         if (HAVE_MEMTEST and MEM):
00251             regstate = nose.run(argv=[sys.argv[0],"-d","-s","--with-memtest","--verbosity=2",
00252                             "--memtest-file="+xmlfile], suite=list, addplugins=[memTest.MemTest()])
00253         else:
00254             regstate = nose.run(argv=[sys.argv[0],"-d","-s","--with-xunit","--verbosity=2",
00255                             "--xunit-file="+xmlfile], suite=list)
00256 
00257         os.chdir(PWD)
00258     except:
00259         print "Failed to run one or more tests"
00260         traceback.print_exc()
00261     else:
00262         os.chdir(PWD)
00263 
00264 
00265 # ------------------ NOTE ---------------------------------------------
00266 # Once CASA moves to Python 2.7, the getpopt module should be replaced
00267 # by argparse. The next section will need to be updated accordingly
00268 # ---------------------------------------------------------------------
00269 if __name__ == "__main__":
00270     # Get command line arguments
00271     
00272     if "-c" in sys.argv:
00273         # If called with ... -c runUnitTest.py from the command line,
00274         # then parse the command line parameters
00275         i = sys.argv.index("-c")
00276         if len(sys.argv) >= i + 2 and \
00277                re.compile("runUnitTest\.py$").search(sys.argv[i + 1]):
00278             
00279         
00280             try:
00281                 # Get only this script options
00282                 opts,args=getopt.getopt(sys.argv[i+2:], "Hlmgf:d:", ["Help","list","mem",
00283                                                                      "debug","file=","datadir="])
00284                 
00285             except getopt.GetoptError, err:
00286                 # Print help information and exit:
00287                 print str(err) # will print something like "option -a not recognized"
00288                 usage()
00289                 os._exit(2)
00290                 
00291             # List of tests to run
00292             testnames = []
00293             
00294             # Boolean for file with tests.
00295             # One could allow the use of --file with specific tests given in
00296             # the command line by removing this option and appending to the
00297             # testnames list in the args handling
00298             hasfile = False
00299             
00300             # If no option is given to this script, run all tests that are defined in
00301             # ../gcwrap/python/scripts/tests/unittests_list.txt
00302             if opts == [] and args == []:
00303                 whichtests = 0
00304                 testnames = []
00305             # run all tests in memory mode
00306             elif (args == [] and opts.__len__() == 1 and opts[0][0] == "--mem"):
00307                 MEM = 1
00308                 whichtests = 0
00309                 testnames = []     
00310             # All other options       
00311             else:
00312                 for o, a in opts:
00313                     if o in ("-H", "--Help"):
00314                         usage()
00315                         os._exit(0) 
00316                     if o in ("-l", "--list"):
00317                         list_tests()
00318                         os._exit(0)
00319                     if o in ("-m", "--mem"):
00320                         # run specific tests in mem mode            
00321                         MEM = 1
00322                     elif o in ("-g", "--debug"):
00323                         #Set the casalog to DEBUG
00324                         casalog.filter('DEBUG')
00325                     elif o in ("-f", "--file"):
00326                         hasfile = True
00327                         testnames = a
00328                     elif o in ("-d", "--datadir"):
00329                         # This will create an environmental variable called
00330                         # TEST_DATADIR that can be read by the tests to use
00331                         # an alternative location for the data. This is used 
00332                         # to test tasks with MMS data
00333                         # directory with test data
00334                         datadir = a
00335                         if not os.path.isdir(datadir):                            
00336                             raise Exception, 'Value of --datadir is not a directory -> '+datadir  
00337                         
00338                         # Set an environmental variable for the data directory
00339                         settestdir(datadir)
00340                         if not os.environ.has_key('TEST_DATADIR'):    
00341                             raise Exception, 'Could not create environmental variable TEST_DATADIR'
00342                         
00343                         
00344                     else:
00345                         assert False, "unhandled option"
00346                 
00347                 # Deal with other arguments
00348                 if args != [] and not hasfile:
00349                     testnames = args
00350                     
00351         else:
00352             testnames = []
00353         
00354     else:
00355         # Not called with -c (but possibly execfile() from iPython)
00356         testnames = []
00357 
00358                     
00359     try:
00360         main(testnames)
00361     except:
00362         traceback.print_exc()
00363         
00364