casa
$Rev:20696$
|
00001 """ Class to wrap a test to use with unittest framework.""" 00002 00003 import os 00004 import commands 00005 import sys 00006 import shutil 00007 import inspect 00008 import re 00009 import string 00010 import traceback 00011 import casac 00012 import unittest 00013 00014 PYVER = str(sys.version_info[0]) + "." + str(sys.version_info[1]) 00015 00016 AIPS_DIR = os.environ["CASAPATH"].split()[0] 00017 DATA_DIR = AIPS_DIR+'/data' 00018 00019 SCRIPT_REPOS=AIPS_DIR + "/" + os.environ["CASAPATH"].split()[1] + '/python/' + PYVER + '/tests/' 00020 00021 if not os.access(SCRIPT_REPOS, os.F_OK): 00022 if os.access(AIPS_DIR+'/lib64', os.F_OK): 00023 SCRIPT_REPOS = AIPS_DIR+'/lib64/python' + PYVER + '/tests/' 00024 elif os.access(AIPS_DIR+'/lib', os.F_OK): 00025 SCRIPT_REPOS = AIPS_DIR+'/lib/python' + PYVER + '/tests/' 00026 else: #Mac release 00027 SCRIPT_REPOS = AIPS_DIR+'/Resources/python/tests/' 00028 00029 class Helper(): 00030 # This class is called when a test is not found. It will 00031 # raise an exception and make nose fail. This way, the not 00032 # found test will be counted as an error and won't be ignored. 00033 def __init__(self, name): 00034 self.tname = name 00035 00036 def test_dummy(self): 00037 '''Helper function''' 00038 raise Exception, "Cannot find test %s"%self.tname 00039 00040 class UnitTest: 00041 def __init__(self,testname=''): 00042 """Take the name of a test file (without .py), wrap it and run""" 00043 self.testname = testname 00044 self.workdir = testname+'_work' 00045 self.scriptdir = SCRIPT_REPOS 00046 self.datadir = [DATA_DIR] 00047 self.dataFiles = [] 00048 00049 def funcdesc(self): 00050 '''Name of test for FunctionTestCase''' 00051 return 'Test '+self.testname 00052 00053 def funcSetup(self): 00054 """Copy data files to local working directory""" 00055 00056 dataFiles = self.dataFiles 00057 print 'Searching for input data in %s'%(self.datadir) 00058 for datafile in dataFiles: 00059 file = self.locatedata(datafile, self.datadir) 00060 #if data already exist, remove them 00061 if(file != ''): 00062 os.system('rm -rf '+ self.workdir+'/'+datafile) 00063 if(os.path.isdir(file)): 00064 shutil.copytree(file, self.workdir+'/'+datafile) 00065 if(os.path.isfile(file)): 00066 shutil.copy(file, self.workdir+'/'+datafile) 00067 00068 def funcTeardown(self): 00069 """Remove data files from working directory""" 00070 00071 dataFiles = self.dataFiles 00072 for datafile in dataFiles: 00073 file = self.workdir+'/'+datafile 00074 os.system('rm -rf ' + file) 00075 00076 self.dataFiles = [] 00077 00078 def getFuncTest(self): 00079 print '-------------- Unit Test for %s ---------------'%self.testname 00080 """Wrap a script using unittest""" 00081 testscript = self.searchscript(self.testname, self.scriptdir) 00082 00083 # avoid creating a _work directory 00084 if (testscript == ""): 00085 return 00086 00087 # copy test to local directory 00088 self.workdir = os.getcwd() 00089 self.getTest(testscript, self.testname,self.scriptdir, self.workdir) 00090 00091 # import the test 00092 mytest = __import__(self.testname) 00093 reload(mytest) 00094 00095 #get the data 00096 try: 00097 self.dataFiles = mytest.data() 00098 except: 00099 print 'No data needed or found' 00100 00101 # Wrap the test, funcSetup and funcTeardown in a FunctionTestCase and return it 00102 testcase = (unittest.FunctionTestCase(mytest.run,setUp=self.funcSetup, 00103 tearDown=self.funcTeardown, 00104 description=self.funcdesc())) 00105 00106 return testcase 00107 00108 00109 def getUnitTest(self,list=[]): 00110 """Set up a unit test script to run wit nose""" 00111 print '-------------- Unit Test for %s ---------------'%self.testname 00112 if list: 00113 print 'List of specific tests %s'%(list) 00114 00115 # search for script in repository 00116 testscript = self.searchscript(self.testname, self.scriptdir) 00117 00118 if (testscript == ""): 00119 testlist = [] 00120 # Create a dummy list and return it so that nose 00121 # includes this test in the list of erroneous tests 00122 # instead of ignoring it. 00123 t = unittest.FunctionTestCase(Helper(self.testname).test_dummy) 00124 return [t] 00125 00126 # copy test to local directory 00127 self.workdir = os.getcwd() 00128 self.getTest(testscript, self.testname,self.scriptdir, self.workdir) 00129 00130 # import the test 00131 mytest = __import__(self.testname) 00132 reload(mytest) 00133 00134 # get the classes 00135 classes = mytest.suite() 00136 testlist = [] 00137 00138 # Check if specific tests/classes were requested 00139 if not list: 00140 # print "no list" 00141 for c in classes: 00142 for attr, value in c.__dict__.iteritems(): 00143 # print attr, " = ", value 00144 if len(attr) >= len("test") and \ 00145 attr[:len("test")] == "test" : \ 00146 testlist.append(c(attr)) 00147 00148 else: 00149 # verify if list contains classes and/or methods 00150 for input in list: 00151 for c in classes: 00152 # print c 00153 if self.isaclass(c,input): 00154 # print "it is a class" 00155 # It is a class. Get all its methods 00156 for attr, value in c.__dict__.iteritems(): 00157 if len(attr) >= len("test") and \ 00158 attr[:len("test")] == "test" : \ 00159 # append each test method to the list 00160 testlist.append(c(attr)) 00161 else: 00162 # maybe it is a method. Get only this one 00163 # print "maybe it is a method" 00164 for attr, value in c.__dict__.iteritems(): 00165 if input == attr: 00166 testlist.append(c(attr)) 00167 00168 # for attr, value in c.__dict__.iteritems(): 00169 # print attr, value 00170 # if list: 00171 # print 'There is a list' 00172 # for test in list: 00173 # print test 00174 # if test == attr: 00175 # testlist.append(c(attr)) 00176 # else: 00177 # print attr, " = ", value 00178 # if len(attr) >= len("test") and \ 00179 # attr[:len("test")] == "test" : \ 00180 ## attr.rfind('test') != -1 : 00181 # testlist.append(c(attr)) 00182 # print testlist 00183 return testlist 00184 00185 00186 def cleanup(self,workdir): 00187 # for safety, avoid removing the local directory 00188 if (workdir == '.'): 00189 workdir = '/tmp/utests' 00190 00191 if os.path.isdir(workdir): 00192 print 'Cleaning up '+ workdir 00193 shutil.rmtree(workdir) 00194 00195 00196 def createDir(self, workdir): 00197 """Create a working directory""" 00198 if os.access(workdir, os.F_OK) is False: 00199 print workdir+' does not exist, creating it' 00200 os.makedirs(workdir) 00201 00202 00203 def locatedata(self, datafile, datadir): 00204 00205 for repository in datadir : 00206 00207 #Skip hidden directories 00208 filter_hidden = ' | grep -vE "^\\." | grep -vE "/\\."' 00209 00210 #See if find understands -L or -follow (depends on find version) 00211 (err, a) = commands.getstatusoutput('find -L ' + repository+'/ 1>/dev/null 2>&1') 00212 if not err: 00213 findstr='find -L '+repository+'/ -name '+datafile+' -print 2>/dev/null' + filter_hidden 00214 else: 00215 findstr='find '+repository+'/ -follow -name '+datafile+' -print 2>/dev/null' + filter_hidden 00216 # A '/' is appended to the directory name; otherwise sometimes find doesn't find. 00217 #Also, ignore error messages such as missing directory permissions 00218 00219 (find_errorcode, a)=commands.getstatusoutput(findstr) # stdout and stderr 00220 #if find_errorcode != 0: 00221 # print >> sys.stderr, "%s failed: %s" % (findstr, a) 00222 retval='' 00223 b=[''] 00224 if(a!=''): 00225 b=string.split(a, '\n') 00226 retval=b[len(b)-1] 00227 if(len(b) > 1): 00228 print 'More than 1 file found with name '+datafile 00229 print 'Will use', retval 00230 return retval 00231 raise Exception, 'Could not find datafile %s in the repository directories %s' \ 00232 % (datafile, datadir) 00233 00234 00235 def searchscript(self, testname, scriptdir): 00236 """Search for the script""" 00237 print "Searching for script %s in %s" %(testname,scriptdir) 00238 # TestName=string.lower(testname) 00239 TestName = testname 00240 00241 theScript='' 00242 numOfScript=0 00243 00244 # search for DIR/<name>.py 00245 if os.path.isdir(scriptdir): 00246 allScripts=os.listdir(scriptdir) 00247 else: 00248 allScripts=[] 00249 # print "allScripts = ", allScripts 00250 for scr in allScripts: 00251 # print scriptdir, scr, testname 00252 if (scr == TestName + '.py'): 00253 theScript = scr 00254 numOfScript += 1 00255 00256 if numOfScript == 0: 00257 # raise Exception, 'Could not find test %s' %TestName 00258 print 'ERROR: Could not find test %s' %TestName 00259 return "" 00260 00261 if( numOfScript > 1) : 00262 print 'More than 1 scripts found for name '+TestName 00263 print 'Using the following one '+ theScript 00264 00265 print "Found", theScript 00266 return theScript 00267 00268 def getTest(self, testnamek, testName, scriptdir, workdir): 00269 print 'Copy the script to the working dir' 00270 if testnamek[0:6] == 'tests/': 00271 shutil.copy(scriptdir+'/'+testnamek, 00272 workdir+'/'+testName+'.py') 00273 else: 00274 shutil.copy(scriptdir+'/'+testnamek, \ 00275 workdir+'/') 00276 00277 def isaclass(self,myclass,input): 00278 '''Check if input equals the class name''' 00279 # print "input=%s myclass=%s"%(input,myclass.__name__) 00280 if input == myclass.__name__: 00281 return True 00282 00283 return False 00284 00285 00286 class ExecTest(unittest.TestCase,UnitTest): 00287 """Wraps scripts to run with execfile""" 00288 00289 def setup(self): 00290 self.workdir = self.testname+'_work' 00291 self.scriptdir = SCRIPT_REPOS 00292 00293 self.testscript = self.searchscript(self.testname,self.scriptdir) 00294 # avoid creating a _work directory 00295 if (self.testscript == ""): 00296 return 00297 00298 # create a working directory 00299 self.cleanup(self.workdir) 00300 self.createDir(self.workdir) 00301 00302 # copy test to workdir 00303 self.getTest(self.testscript, self.testname, self.scriptdir, self.workdir) 00304 thisDir = os.getcwd() 00305 os.chdir(self.workdir) 00306 00307 def testrun(self): 00308 #self.testname is defined in the calling function 00309 # run self.setup before calling this function 00310 """Run test with execfile""" 00311 00312 # run the test 00313 a=inspect.stack() 00314 stacklevel=0 00315 for k in range(len(a)): 00316 if (string.find(a[k][1], 'ipython console') > 0): 00317 stacklevel=k 00318 break 00319 gl=sys._getframe(stacklevel).f_globals 00320 00321 execfile(self.testscript, gl) 00322 00323