IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 29227


Ignore:
Timestamp:
Sep 23, 2010, 3:38:03 PM (16 years ago)
Author:
Serge CHASTEL
Message:

Test report / product

Location:
branches/sc_branches/psps_testing
Files:
2 added
10 edited

Legend:

Unmodified
Added
Removed
  • branches/sc_branches/psps_testing/build.py

    r29111 r29227  
    11#!/usr/bin/python
    22
     3from utilities.psps_logger import PsPsLogger
     4import logging
     5
    36# Setup logging
    4 import logging
    5 datefmt = '%H:%M:%S'
    6 fmt = '[%(asctime)8s/@%(filename)s/%(funcName)s()/%(lineno)03d %(levelname)5s] %(message)s'
    7 logging.basicConfig(level=logging.INFO, format=fmt)
    8 logger = logging.Logger("main")
    9 handler = logging.StreamHandler()
    10 handler.setFormatter(logging.Formatter(fmt, datefmt))
    11 logger.addHandler(handler)
    12 logger.setLevel(logging.INFO)
     7# datefmt = '%H:%M:%S'
     8# fmt = '[%(asctime)8s/@%(filename)s/%(funcName)s()/%(lineno)03d %(levelname)5s] %(message)s'
     9# logging.basicConfig(level=logging.INFO, format=fmt)
     10# logger = logging.Logger("main")
     11# handler = logging.StreamHandler()
     12# handler.setFormatter(logging.Formatter(fmt, datefmt))
     13# logger.addHandler(handler)
     14# logger.setLevel(logging.INFO)
    1315
    1416#
     
    1618
    1719FILES_TO_CHECK = [ 'data/samples/B00029152.tar.gz',
    18                    'data/samples/B00030978.tar.gz',
    19                    'data/samples/B00031481.tar.gz',
    20                    'data/samples/B00032090.tar.gz',
    21                    'data/samples/B00032701.tar.gz',
    22                    'data/samples/B00033107.tar.gz',
    23                    'data/samples/B00033820.tar.gz',
    24                    'data/samples/B00034120.tar.gz',
    25                    'data/samples/B00034574.tar.gz',
    26                    'data/samples/B00035357.tar.gz',
     20                   # 'data/samples/B00030978.tar.gz',
     21                   # 'data/samples/B00031481.tar.gz',
     22                   # 'data/samples/B00032090.tar.gz',
     23                   # 'data/samples/B00032701.tar.gz',
     24                   # 'data/samples/B00033107.tar.gz',
     25                   # 'data/samples/B00033820.tar.gz',
     26                   # 'data/samples/B00034120.tar.gz',
     27                   # 'data/samples/B00034574.tar.gz',
     28                   # 'data/samples/B00035357.tar.gz',
    2729                   ]
    2830
    2931if __name__ == '__main__':
    30     for file_to_check in FILES_TO_CHECK:
    31         logger.info('Testing for entry %s' % (file_to_check))
    32         print BatchFileTester(file_to_check).test()
     32    import sys
     33    current_argument_position = 1
     34    testMode = False
     35    PsPsLogger.setLevel(logging.INFO)
     36    PsPsLogger.set_stdout()
     37    while current_argument_position < len(sys.argv):
     38        if sys.argv[current_argument_position] == '-v':
     39            PsPsLogger.setLevel(logging.DEBUG)
     40            current_argument_position += 1
     41        elif sys.argv[current_argument_position] == '-o':
     42            PsPsLogger.set_fileout(sys.argv[current_argument_position+1])
     43            current_argument_position += 2
     44        elif sys.argv[current_argument_position] == 'test':
     45            testMode = True
     46            current_argument_position += 1
     47        else:
     48            filename = sys.argv[current_argument_position]
     49            current_argument_position += 1
     50    PsPsLogger.info('Command line was: [%s]' % ' '.join(sys.argv))
     51
     52    if testMode:
     53        for file_to_check in FILES_TO_CHECK:
     54            PsPsLogger.info('Testing for entry %s' % (file_to_check))
     55            print BatchFileTester(file_to_check).test().success
     56    else:
     57            PsPsLogger.info('Testing for file: [%s]' % (filename))
     58            print BatchFileTester(filename).test().success
     59       
  • branches/sc_branches/psps_testing/psi/psi_inquisitor.py

    r29140 r29227  
    22from suds.xsd.doctor import Import, ImportDoctor
    33from suds import sudsobject
    4 from utilities.util import convert
     4from utilities.util import psi_convert
    55import unicodedata
     6from utilities.psps_logger import PsPsLogger
     7from utilities.test_report import TestReport
    68
    79class PsiInquisitor:
     
    2426        # exec 'from %s import Configuration' % configuration_file
    2527        # self.configuration = Configuration
     28        PsPsLogger.debug('Creating PsiInquisitor from %s file' % configuration_file)
    2629        self.configuration = __import__(configuration_file, globals(), locals(),
    27                                         ['Configuration'], -1).Configuration
     30                                        ['Configuration'], -1).PsiConfiguration
     31        TestReport.info('PsiInquisitor created from %s' % configuration_file)
     32        TestReport.info(self.configuration.str())
    2833        self.authClient = Client(self.configuration.authUrl)
    2934        self.sessionID = self.authClient.service.login(self.configuration.userID,
     
    3944        Make a query in the fast queue.
    4045       
     46        >>> psiInquisitor = PsiInquisitor('psi.web01_configuration')
    4147        >>> query = 'select frameID from FrameMeta where frameID=105439;'
    42         >>> psiInquisitor = PsiInquisitor('psi.web01_configuration')
    4348        >>> result = psiInquisitor.query(query)
    4449        >>> # we cannot guarantee the order in result
     
    4954        >>> print result['types']
    5055        {'[frameID]': 'Integer'}
     56
     57        >>> query = 'select surveyID from FrameMeta where frameID=105439;'
     58        >>> result = psiInquisitor.query(query)
     59        >>> # we cannot guarantee the order in result
     60        >>> print result['items']
     61        [{'surveyID': 0}]
     62        >>> print result['fields']
     63        ['[surveyID]']
     64        >>> print result['types']
     65        {'[surveyID]': 'Byte'}
     66
     67        >>> query = 'select cameraID from FrameMeta where frameID=105439;'
     68        >>> result = psiInquisitor.query(query)
     69        >>> # we cannot guarantee the order in result
     70        >>> print result['items']
     71        [{'cameraID': 1}]
     72        >>> print result['fields']
     73        ['[cameraID]']
     74        >>> print result['types']
     75        {'[cameraID]': 'Integer'}
     76        >>> # It should be something expressing that it is a 16-bits integer
     77
     78        >>> # REAL 4 bytes
     79        >>> query = 'select photoScat from FrameMeta where frameID=105439;'
     80        >>> result = psiInquisitor.query(query)
     81        >>> # we cannot guarantee the order in result
     82        >>> print result['items']
     83        [{'photoScat': 0.051822260000000002}]
     84        >>> print result['fields']
     85        ['[photoScat]']
     86        >>> print result['types']
     87        {'[photoScat]': 'Float'}
     88        >>> # There should be sthg to make the difference between f32 and f64
     89
     90        >>> # FLOAT 8 bytes
     91        >>> query = 'select expStart from FrameMeta where frameID=105439;'
     92        >>> result = psiInquisitor.query(query)
     93        >>> # we cannot guarantee the order in result
     94        >>> print result['items']
     95        [{'expStart': 55163.4545890027}]
     96        >>> print result['fields']
     97        ['[expStart]']
     98        >>> print result['types']
     99        {'[expStart]': 'Float'}
     100        >>> # There should be sthg to make the difference between f32 and f64
     101
    51102        >>> # This test has to be completed with exhaustive ones...
    52103        >>> # e.g. unit tests against the csr data base.
    53104        """
     105        PsPsLogger.debug('Querying PSI: [%s]' % sql_query)
    54106        results = self.jobsClient.service.executeQuickJob(self.sessionID,
    55107                                                          self.configuration.schemaGroup,
     
    94146                                                               '').replace(']',
    95147                                                                           '')
    96                     element[field_name] = convert(types_dictionary[contents['fields'][i]],
     148                    element[field_name] = psi_convert(types_dictionary[contents['fields'][i]],
    97149                                                  values[i])
    98150                contents['items'].append(element)
     151        PsPsLogger.debug('Number of answers: %d' % len(contents['items']))
    99152        return contents
    100153
    101154if __name__ == '__main__':
     155    import logging
     156    PsPsLogger.set_stderr()
     157    PsPsLogger.setLevel(logging.DEBUG)
    102158    import doctest
    103159    doctest.testmod()
  • branches/sc_branches/psps_testing/psi/web01_configuration.py

    r29115 r29227  
    1 class Configuration:
     1from utilities.psps_logger import PsPsLogger
     2
     3class PsiConfiguration:
    24    """
    35    The configuration described as a class...
    46    """
    57    server = 'http://web01.psps.ifa.hawaii.edu/'
    6     authUrl = server + 'DFetch/WSDL/AuthService.php.wsdl'
    78    userID = 'schastel'
    89    password = 'd1str1ct13'
    910    schemaGroup = 'PS1_SCHEMA';
    1011    context     = 'PS1 3PI';
     12    authUrl = server + 'DFetch/WSDL/AuthService.php.wsdl'
    1113    jobsUrl = server + 'DFetch/WSDL/JobsService.php.wsdl'
     14
     15    @staticmethod
     16    def str():
     17        """
     18        >>> print PsiConfiguration.str()
     19        PsiConfiguration
     20          Server: http://web01.psps.ifa.hawaii.edu/
     21          User: schastel
     22          Password: d1str1ct13
     23          SchemaGroup: PS1_SCHEMA
     24          Context: PS1 3PI
     25          AuthUrl: http://web01.psps.ifa.hawaii.edu/DFetch/WSDL/AuthService.php.wsdl
     26          JobsUrl: http://web01.psps.ifa.hawaii.edu/DFetch/WSDL/JobsService.php.wsdl
     27        """
     28        return """Configuration
     29  Server: %s
     30  User: %s
     31  Password: %s
     32  SchemaGroup: %s
     33  Context: %s
     34  AuthUrl: %s
     35  JobsUrl: %s""" % (PsiConfiguration.server,
     36                    PsiConfiguration.userID,
     37                    PsiConfiguration.password,
     38                    PsiConfiguration.schemaGroup,
     39                    PsiConfiguration.context,
     40                    PsiConfiguration.authUrl,
     41                    PsiConfiguration.jobsUrl)
  • branches/sc_branches/psps_testing/testers/batch_file.py

    r29116 r29227  
    1 # Strings managed as files
    2 from StringIO import StringIO
    31# Regular expressions
    42import re
     
    75import os
    86from utilities.file_manipulation import FileManipulation
     7from utilities.test_report import TestReport
     8from utilities.test_product import TestProduct
     9# Sub-tests
    910from testers.batch_manifest_file import BatchManifestFileTester
    1011from testers.fits_file import FitsFileTester
     
    1314# Global definitions
    1415from utilities.configuration import Configuration
     16# Logging
     17from utilities.psps_logger import PsPsLogger
    1518
    1619class BatchFileTester:
     
    2225      of the files contained in the archive
    2326
    24     >>> print BatchFileTester("data/psut/ok/B00029152.tar.gz").test()
     27    >>> print BatchFileTester("data/psut/ok/B00000010.tar.gz").test()
    2528    PSDC-940-006-01, 3.4.1: OK
    2629    PSDC-940-006-01, 3.4: OK
     
    4245        dummy/
    4346        """
     47        PsPsLogger.debug('Creating BatchFileTester object with filename = [%s]' % filename)
     48        TestReport.info('Tests performed on file [%s]' % filename)
    4449        self._filename = filename
    4550        self.expected_basename = os.path.basename(self._filename
    4651                                                  ).replace(Configuration.EXTENSION,
    4752                                                            '') + '/'
     53        PsPsLogger.debug(' BatchFileTester object expected basename = [%s]'
     54                           % self.expected_basename)
    4855
    4956    def test(self, start_dependant_tests = True):
     
    5259        tests are succesful.
    5360        """
    54         report = StringIO()
    55         testsOk = True
    56         (message, status) = self._test_file_name("PSDC-940-006-01, 3.4.1")
    57         report.write(message)
    58         testsOk = testsOk and status
    59         (message, status) = self._test_file_format("PSDC-940-006-01, 3.4")
    60         report.write('\n' + message)
    61         testsOk = testsOk and status
    62         # Now runs the dependant tests
    63         if testsOk and start_dependant_tests:
    64             # Uncompress the archive (since it's valid) to some temp dir
     61        PsPsLogger.debug('Starting BatchFileTester object test')
     62        TestReport.title('Batch file tests')
     63        # Set up global test product
     64        product = TestProduct()
     65        product.success = True
     66        # Subtest
     67        subproduct = self._test_file_name("PSDC-940-006-01, 3.4.1")
     68        product.success =  product.success and subproduct.success
     69        # Subtest
     70        subproduct = self._test_file_format("PSDC-940-006-01, 3.4")
     71        product.success =  product.success and subproduct.success
     72        # Now runs the dependent tests
     73        if product.success and start_dependant_tests:
     74            # Uncompress the archive (since it is valid) to some temp dir
    6575            tempDir = tempfile.mkdtemp()
    6676            command = '/bin/tar xvfz %s -C %s' % (self._filename, tempDir)
     77            PsPsLogger.debug('Unpacking data (%s)' % command)
    6778            (status,
    6879             child_stdout,
     
    7182            batchManifestFileTester = BatchManifestFileTester(self.expected_basename,
    7283                                                              tempDir)
    73             (_report, fits_info) = batchManifestFileTester.test()
    74             report.write('\n' + _report)
    75             # Run the tests on the fits file
    76             fitsFileTester = FitsFileTester(fits_info['filename'],
    77                                             self.expected_basename, tempDir,
    78                                             fits_info['filetype'])
    79             (_report, info) = fitsFileTester.test()
    80             report.write('\n' + _report)
     84            subproduct = batchManifestFileTester.test()
     85            product.success =  product.success and subproduct.success
     86            if not product.success:
     87                FileManipulation.delete_directory(tempDir)
     88                return product
     89            # Run the tests on the fits file (subproduct.filename and
     90            # subproduct.filetype are supposed to convey such
     91            # information)
     92            fitsFileTester = FitsFileTester(subproduct.filename,
     93                                            self.expected_basename,
     94                                            tempDir,
     95                                            subproduct.filetype)
     96            subproduct = fitsFileTester.test()
     97            product.success =  product.success and subproduct.success
    8198            # End of test... Delete the temporary directory
    8299            FileManipulation.delete_directory(tempDir)
    83         return report.getvalue()
     100        else:
     101            PsPsLogger.debug('Dependant tests not run (condition on upstream tests is %s and start_dependant_tests variable is %s)' % (str(testsOk), str(start_dependant_tests)))
     102        return product
    84103
    85104    def _test_file_name(self, requirement):
     
    94113
    95114        >>> batchFileTester = BatchFileTester('B12345678.tar.gz')
    96         >>> print batchFileTester._test_file_name("REQ_ID")
    97         ('REQ_ID: OK', True)
     115        >>> print batchFileTester._test_file_name("(UNIT_TEST_SAMPLE_REQ)").success
     116        True
    98117
    99118        >>> batchFileTester = BatchFileTester('B1234567.tar.gz')
    100         >>> print batchFileTester._test_file_name("REQ_ID")
    101         ("REQ_ID: KO (invalid archive file basename 'B1234567.tar.gz')", False)
     119        >>> print batchFileTester._test_file_name("(UNIT_TEST_SAMPLE_REQ)").success
     120        False
    102121
    103122        >>> batchFileTester = BatchFileTester('B123456789.tar.gz')
    104         >>> print batchFileTester._test_file_name("REQ_ID")
    105         ("REQ_ID: KO (invalid archive file basename 'B123456789.tar.gz')", False)
     123        >>> print batchFileTester._test_file_name("(UNIT_TEST_SAMPLE_REQ)").success
     124        False
    106125
    107126        >>> batchFileTester = BatchFileTester('B123a5678.tar.gz')
    108         >>> print batchFileTester._test_file_name("REQ_ID")
    109         ("REQ_ID: KO (invalid archive file basename 'B123a5678.tar.gz')", False)
     127        >>> print batchFileTester._test_file_name("(UNIT_TEST_SAMPLE_REQ)").success
     128        False
    110129
    111130        >>> batchFileTester = BatchFileTester('b12345678.tar.gz')
    112         >>> print batchFileTester._test_file_name("REQ_ID")
    113         ("REQ_ID: KO (invalid archive file basename 'b12345678.tar.gz')", False)
     131        >>> print batchFileTester._test_file_name("(UNIT_TEST_SAMPLE_REQ)").success
     132        False
    114133
    115134        >>> batchFileTester = BatchFileTester('B12345678.tgz')
    116         >>> print batchFileTester._test_file_name("REQ_ID")
    117         ("REQ_ID: KO (invalid archive file basename 'B12345678.tgz')", False)
     135        >>> print batchFileTester._test_file_name("(UNIT_TEST_SAMPLE_REQ)").success
     136        False
    118137       
    119138        >>> batchFileTester = BatchFileTester('B12345678.TAR.GZ')
    120         >>> print batchFileTester._test_file_name("REQ_ID")
    121         ("REQ_ID: KO (invalid archive file basename 'B12345678.TAR.GZ')", False)
    122         """
    123         report = StringIO()
     139        >>> print batchFileTester._test_file_name("(UNIT_TEST_SAMPLE_REQ)").success
     140        False
     141        """
     142        PsPsLogger.debug('Running tests on file format')
    124143        basename = os.path.basename(self._filename)
     144        product = TestProduct()
    125145        if re.match('B\d{8}\.tar.gz', basename) == None:
    126             return ('%s: KO (invalid archive file basename \'%s\')' % (requirement, basename), False)
     146            TestReport.ko(requirement,
     147                          'invalid archive file basename \'%s\'' % basename )
    127148        else:
    128             report.write('%s: OK' % requirement)
    129         return (report.getvalue(), True)
     149            TestReport.ok(requirement)
     150            product.success = True
     151        return product
    130152
    131153    def _test_file_format(self, requirement):
     
    152174              (named BatchManifest.xml) and exactly one FITS file.
    153175
    154         >>> batchFileTester = BatchFileTester('data/psut/ok/B00029152.tar.gz')
    155         >>> print batchFileTester._test_file_format("REQ_ID")
    156         ('REQ_ID: OK', True)
     176        >>> batchFileTester = BatchFileTester('data/psut/ok/B00000010.tar.gz')
     177        >>> print batchFileTester._test_file_format("(UNIT_TEST_SAMPLE_REQ)").success
     178        True
    157179
    158180        >>> batchFileTester = BatchFileTester('This_file_does_not_exist.tar.gz')
    159         >>> print batchFileTester._test_file_format("REQ_ID")
    160         ("REQ_ID: KO (invalid tar gzipped archive file 'This_file_does_not_exist.tar.gz')", False)
     181        >>> print batchFileTester._test_file_format("(UNIT_TEST_SAMPLE_REQ)").success
     182        False
    161183
    162184        >>> batchFileTester = BatchFileTester('data/psut/ko/B00000001.tar.gz')
    163         >>> print batchFileTester._test_file_format("REQ_ID")
    164         ("REQ_ID: KO (invalid directory name in archive 'data/psut/ko/B00000001.tar.gz': Got tmp/ instead of B00000001/)", False)
     185        >>> print batchFileTester._test_file_format("(UNIT_TEST_SAMPLE_REQ)").success
     186        False
    165187
    166188        >>> batchFileTester = BatchFileTester('data/psut/ko/B00000002.tar.gz')
    167         >>> print batchFileTester._test_file_format("REQ_ID")
    168         ("REQ_ID: KO (missing XML Manifest file in archive 'data/psut/ko/B00000002.tar.gz')", False)
     189        >>> print batchFileTester._test_file_format("(UNIT_TEST_SAMPLE_REQ)").success
     190        False
    169191
    170192        >>> batchFileTester = BatchFileTester('data/psut/ko/B00000003.tar.gz')
    171         >>> print batchFileTester._test_file_format("REQ_ID")
    172         ("REQ_ID: KO (missing FITS file in archive 'data/psut/ko/B00000003.tar.gz')", False)
     193        >>> print batchFileTester._test_file_format("(UNIT_TEST_SAMPLE_REQ)").success
     194        False
    173195
    174196        >>> batchFileTester = BatchFileTester('data/psut/ko/B00000004.tar.gz')
    175         >>> print batchFileTester._test_file_format("REQ_ID")
    176         ("REQ_ID: KO (unexpected file 'B00000004/extra' in archive 'data/psut/ko/B00000004.tar.gz')", False)
    177         """
     197        >>> print batchFileTester._test_file_format("(UNIT_TEST_SAMPLE_REQ)").success
     198        False
     199        """
     200        PsPsLogger.debug('Running tests on file format')
    178201        (status,
    179202         child_stdout,
    180203         child_stderr) = FileManipulation.system('/bin/tar tfz ' + self._filename)
     204        product = TestProduct()
    181205        # Test 1: if the archive is not valid
    182206        if status != 0:
    183             return (requirement + ': KO (invalid tar gzipped archive file \'%s\')' % self._filename, False)
     207            TestReport.ko(requirement,
     208                          'invalid tar gzipped archive file \'%s\'' % self._filename)
     209            return product
    184210        # Now check the results of the standard output which must be:
    185211        #   <basename>/
     
    199225            if status == 0:
    200226                if line != self.expected_basename:
    201                     return (requirement + ': KO (invalid directory name in archive \'%s\': Got %s instead of %s)' % (self._filename, line, self.expected_basename), False)
     227                    TestReport.ko(requirement,
     228                                  'invalid directory name in archive \'%s\': Got %s instead of %s'
     229                                  % (self._filename, line, self.expected_basename))
     230                    return product
    202231                status = 1
    203232            elif status == 1:
     
    207236                    xml_file_in_archive = True
    208237                else:
    209                     return (requirement + ': KO (unexpected file \'%s\' in archive \'%s\')' % (line, self._filename), False)
     238                    TestReport.ko(requirement,
     239                                  'unexpected file \'%s\' in archive \'%s\'' % (line, self._filename))
     240                    return product
    210241        if not xml_file_in_archive:
    211             return (requirement + ': KO (missing XML Manifest file in archive \'%s\')' % (self._filename), False)
     242            TestReport.ko(requirement,
     243                          'missing XML Manifest file in archive \'%s\'' % (self._filename))
     244            return product
    212245        if not fits_file_in_archive:
    213             return (requirement + ': KO (missing FITS file in archive \'%s\')' % (self._filename), False)
    214         return (requirement + ': OK', True)
    215 
     246            TestReport.ko(requirement,
     247                          'missing FITS file in archive \'%s\'' % (self._filename))
     248            return product
     249        product.success = True
     250        return product
     251
     252################################################################
     253#
     254# __main__
     255#
     256################################################################
    216257if __name__ == '__main__':
    217     import doctest
    218     doctest.testmod()
     258    import logging
     259    import sys
     260    PsPsLogger.setLevel(logging.DEBUG)
     261    current_argument_position = 1
     262    while current_argument_position < len(sys.argv):
     263        if sys.argv[current_argument_position] == '-v':
     264            PsPsLogger.set_stderr()
     265            current_argument_position += 1
     266        elif sys.argv[current_argument_position] == 'test':
     267            print 'Running unittest for BatchFileTester class'
     268            import doctest
     269            doctest.testmod()
     270            sys.exit(0)
  • branches/sc_branches/psps_testing/testers/batch_manifest_file.py

    r29111 r29227  
    1 # Strings managed as files
    2 from StringIO import StringIO
    31# System call and so on
    42from utilities.file_manipulation import FileManipulation
     
    97# Load some utilities to compute md5 checksum
    108import hashlib
     9# Logging
     10from utilities.psps_logger import PsPsLogger
     11from utilities.test_report import TestReport
     12from utilities.test_product import TestProduct
    1113
    1214class BatchManifestFileTester:
     
    3638        Creates an instance of a BatchManifestFileTester
    3739
    38         >>> basename = 'B00029152'
     40        >>> basename = 'B00000010'
    3941        >>> tgz_filename = 'data/psut/ok/' + basename + '.tar.gz'
    4042        >>> # Create the temporary directory for tests
     
    4345        >>> bmft = BatchManifestFileTester(basename, '.tmp')
    4446        >>> print bmft.manifest
    45         .tmp/B00029152/BatchManifest.xml
     47        .tmp/B00000010/BatchManifest.xml
    4648        >>> # Delete temporary directory
    4749        >>> BatchManifestFileTester._remove_test_environment()
     
    5759
    5860        >>> # Unit test: valid file
    59         >>> basename = 'B00029152'
     61        >>> basename = 'B00000010'
    6062        >>> tgz_filename = 'data/psut/ok/' + basename + '.tar.gz'
    6163        >>> # Create the temporary directory for tests
    6264        >>> BatchManifestFileTester._setup_test_environment(basename, tgz_filename)
    6365        >>> bmft = BatchManifestFileTester(basename, '.tmp')
    64         >>> (report, fits_info) = bmft.test()
    65         >>> print report
    66         PSDC-940-006-01, 3.5.1.2: OK
    67         PSDC-940-006-01, 3.5.1.1: OK
    68         PSDC-940-006-01, 3.5.1 (file attributes/name): OK
    69         PSDC-940-006-01, 3.5.1 (file attributes/size): OK
    70         PSDC-940-006-01, 3.5.1 (file attributes/MD5 checksum of file): OK
    71         >>> print fits_info
    72         {'filetype': u'P2', 'filename': u'00105439.FITS'}
    73         >>> BatchManifestFileTester._remove_test_environment()
     66        >>> product = bmft.test()
     67        >>> print product.success
     68        True
     69        >>> print product.filetype
     70        P2
     71        >>> print product.filename
     72        00000010.FITS
     73
     74        # >>> print fits_info
     75        # {'filetype': u'P2', 'filename': u'00000010.FITS'}
     76        # >>> BatchManifestFileTester._remove_test_environment()
    7477
    7578        >>> # Unit test: invalid manifest file name in archive
     
    7982        >>> BatchManifestFileTester._setup_test_environment(basename, tgz_filename)
    8083        >>> bmft = BatchManifestFileTester(basename, '.tmp')
    81         >>> (report, fits_info) = bmft.test()
    82         >>> print report
    83         PSDC-940-006-01, 3.5.1.2: KO (No .tmp/B00000005/BatchManifest.xml file)
    84         >>> print fits_info
    85         None
     84        >>> product = bmft.test()
     85        >>> print product.success
     86        False
    8687        >>> BatchManifestFileTester._remove_test_environment()
    8788
     
    9293        >>> BatchManifestFileTester._setup_test_environment(basename, tgz_filename)
    9394        >>> bmft = BatchManifestFileTester(basename, '.tmp')
    94         >>> (report, fits_info) = bmft.test()
    95         >>> print report
    96         PSDC-940-006-01, 3.5.1.2: OK
    97         PSDC-940-006-01, 3.5.1.1: KO (XML validation through XSD failed: command was [/usr/bin/xmllint --schema data/xsd/BatchManifest.xsd --noout .tmp/B00000006/BatchManifest.xml])
    98         >>> print fits_info
    99         None
     95        >>> product = bmft.test()
     96        >>> print product.success
     97        False
    10098        >>> BatchManifestFileTester._remove_test_environment()
    10199
     
    106104        >>> BatchManifestFileTester._setup_test_environment(basename, tgz_filename)
    107105        >>> bmft = BatchManifestFileTester(basename, '.tmp')
    108         >>> (report, fits_filename) = bmft.test()
    109         >>> print report
    110         PSDC-940-006-01, 3.5.1.2: OK
    111         PSDC-940-006-01, 3.5.1.1: OK
    112         PSDC-940-006-01, 3.5.1 (file attributes/name): KO (no FITS file is named '.tmp/B00000007/00105439.FITS')
    113         >>> print fits_info
    114         None
     106        >>> print product.success
     107        False
    115108        >>> BatchManifestFileTester._remove_test_environment()
    116109
     
    121114        >>> BatchManifestFileTester._setup_test_environment(basename, tgz_filename)
    122115        >>> bmft = BatchManifestFileTester(basename, '.tmp')
    123         >>> (report, fits_info) = bmft.test()
    124         >>> print report
    125         PSDC-940-006-01, 3.5.1.2: OK
    126         PSDC-940-006-01, 3.5.1.1: OK
    127         PSDC-940-006-01, 3.5.1 (file attributes/name): OK
    128         PSDC-940-006-01, 3.5.1 (file attributes/size): KO (actual size of FITS file is '0' instead of '10336320')
    129         >>> print fits_info
    130         None
     116        >>> product = bmft.test()
     117        >>> print product.success
     118        False
    131119        >>> BatchManifestFileTester._remove_test_environment()
    132120
     
    137125        >>> BatchManifestFileTester._setup_test_environment(basename, tgz_filename)
    138126        >>> bmft = BatchManifestFileTester(basename, '.tmp')
    139         >>> (report, fits_info) = bmft.test()
    140         >>> print report
    141         PSDC-940-006-01, 3.5.1.2: OK
    142         PSDC-940-006-01, 3.5.1.1: OK
    143         PSDC-940-006-01, 3.5.1 (file attributes/name): OK
    144         PSDC-940-006-01, 3.5.1 (file attributes/size): OK
    145         PSDC-940-006-01, 3.5.1 (file attributes/MD5 checksum of file): KO (actual md5sum of FITS file is 'd41d8cd98f00b204e9800998ecf8427e' instead of '852461f5e14ff6ce5f0b0edd7166b515')
    146         >>> print fits_info
    147         None
    148         >>> BatchManifestFileTester._remove_test_environment()
    149         """
    150 
    151         report = StringIO()
     127        >>> product = bmft.test()
     128        >>> print product.success
     129        False
     130        >>> BatchManifestFileTester._remove_test_environment()
     131        """
     132        TestReport.title('Batch manifest file tests')
    152133        # Check file existence and proper naming in archive
    153         requirement = 'PSDC-940-006-01, 3.5.1.2: '
     134        requirement = 'PSDC-940-006-01, 3.5.1.2'
     135        product = TestProduct()
    154136        if not FileManipulation.exists(self.manifest):
    155             report.write(requirement + 'KO (No %s file)' % (self.manifest))
    156             return (report.getvalue(), None)
     137            TestReport.ko(requirement,
     138                          'No %s file' % (self.manifest))
     139            return product
    157140        else:
    158             report.write(requirement + 'OK')
     141            TestReport.ok(requirement)
    159142        # Check validation of XML by XSD through xmllint
    160         requirement = 'PSDC-940-006-01, 3.5.1.1: '
    161         command = '/usr/bin/xmllint --schema %s --noout %s'
     143        requirement = 'PSDC-940-006-01, 3.5.1.1'
     144        command = '%s --schema %s --noout %s'  % (Configuration.XMLLINT,
     145                                                  Configuration.XSD_FILE,
     146                                                  self.manifest)
    162147        (status,
    163148         stdout,
    164          stderr) = FileManipulation.system(command % (Configuration.XSD_FILE,
    165                                                       self.manifest) )
     149         stderr) = FileManipulation.system(command)
    166150        if status != 0:
    167             report.write('\n' + requirement + 'KO (XML validation through XSD failed: command was [%s])' % (command % (Configuration.XSD_FILE, self.manifest) ))
    168             return (report.getvalue(), None)
    169         else:
    170             report.write('\n' + requirement + 'OK')
     151            TestReport.ko(requirement,
     152                          'XML validation through XSD failed: command was [%s]' % (command))
     153            return product
     154        TestReport.ok(requirement)
    171155        # Get XML information concerning FITS file
    172156        # Note: We are only interested in the first <file> element
     
    174158        fileList = xmldoc.getElementsByTagName('file')
    175159        # File existence
    176         requirement = 'PSDC-940-006-01, 3.5.1 (file attributes/name): '
     160        requirement = 'PSDC-940-006-01, 3.5.1 (file attributes/name)'
    177161        fitsFilename = fileList[0].attributes['name'].value
    178162        fileToLookFor = self._manifest_relative_directory + '/' + fitsFilename
    179163        if not FileManipulation.exists(fileToLookFor):
    180             report.write('\n' + requirement + 'KO (no FITS file is named \'%s\')' % (fileToLookFor))
    181             return (report.getvalue(), None)
    182         report.write('\n' + requirement + 'OK')
     164            TestReport.ko(requirement,
     165                          'no FITS file is named \'%s\'' % (fileToLookFor))
     166            return product
     167        TestReport.ok(requirement)
    183168        # File size match
    184         requirement = 'PSDC-940-006-01, 3.5.1 (file attributes/size): '
     169        requirement = 'PSDC-940-006-01, 3.5.1 (file attributes/size)'
    185170        expected_size = fileList[0].attributes['bytes'].value
    186171        actual_size = str(FileManipulation.size(fileToLookFor))
    187172        if actual_size != expected_size:
    188             report.write('\n' + requirement + 'KO (actual size of FITS file is \'%s\' instead of \'%s\')' % (actual_size, expected_size))
    189             return (report.getvalue(), None)
    190         report.write('\n' + requirement + 'OK')
     173            TestReport.ko(requirement,
     174                          'actual size of FITS file is \'%s\' instead of \'%s\''
     175                          % (actual_size, expected_size))
     176            return product
     177        TestReport.ok(requirement)
    191178        # File md5sum
    192         requirement = 'PSDC-940-006-01, 3.5.1 (file attributes/MD5 checksum of file): '
     179        requirement = 'PSDC-940-006-01, 3.5.1 (file attributes/MD5 checksum of file)'
    193180        expected_md5sum = fileList[0].attributes['md5'].value
    194181        actual_md5sum = FileManipulation.md5(fileToLookFor)
    195182        if actual_md5sum != expected_md5sum:
    196             report.write('\n' + requirement + 'KO (actual md5sum of FITS file is \'%s\' instead of \'%s\')' % (actual_md5sum, expected_md5sum))
    197             return (report.getvalue(), None)
    198         report.write('\n' + requirement + 'OK')
     183            TestReport.ko(requirement,
     184                          'actual md5sum of FITS file is \'%s\' instead of \'%s\''
     185                          % (actual_md5sum, expected_md5sum))
     186            return product
     187        TestReport.ok(requirement)
    199188        # TODO: Perform some validation of the XML content that XSD can't do
    200189        # e.g.: minObjId < maxObjId.
    201190        # Note: if other objects need to be provided in the output, just add them to the dictionary...
    202191        # e.g.: return (..., {'filename': fitsFilename, 'fitsFilesize': fitsFilesize})
    203         return (report.getvalue(),
    204                 { 'filename': fitsFilename,
    205                   'filetype': xmldoc.getElementsByTagName('manifest')[0].attributes['type'].value})
     192        # Extend test product with values useful in next tests
     193        product.success = True
     194        product.filename = fitsFilename
     195        product.filetype = xmldoc.getElementsByTagName('manifest')[0].attributes['type'].value
     196        return product
    206197
    207198if __name__ == '__main__':
    208     import doctest
    209     doctest.testmod()
     199    import logging
     200    import sys
     201    PsPsLogger.setLevel(logging.DEBUG)
     202    current_argument_position = 1
     203    while current_argument_position < len(sys.argv):
     204        if sys.argv[current_argument_position] == '-v':
     205            PsPsLogger.set_stderr()
     206            current_argument_position += 1
     207        elif sys.argv[current_argument_position] == 'test':
     208            print 'Running unittest for BatchManifestFileTester class'
     209            import doctest
     210            doctest.testmod()
     211            sys.exit(0)
  • branches/sc_branches/psps_testing/testers/fits/p2.py

    r29140 r29227  
    11from psi.psi_inquisitor import PsiInquisitor
    22import pyfits
    3 from StringIO import StringIO
    43from utilities.util import match
     4# Logging
     5from utilities.psps_logger import PsPsLogger
     6from utilities.configuration import Configuration
     7from utilities.test_report import TestReport
     8from utilities.test_product import TestProduct
    59
    610class P2FitsTester:
     
    1418
    1519    Note that the purpose of this class is NOT to test the FITS
    16     validity (which can be checked using some pyfits options).
     20    validity (which can be checked using pyfits options).
    1721    """
    1822    def __init__(self, fits_file, psi_configuration):
     
    2529        >>> p2ft = P2FitsTester(fits_file, psi_configuration)
    2630        """
     31        PsPsLogger.debug('Creating P2FitsTester object')
    2732        self.fits = fits_file
    2833        self.psi_inquisitor = PsiInquisitor(psi_configuration)
    2934
    30     def test(self):
     35    def test(self, be_tolerant_for_types = False):
    3136        """
    3237        Tests a FITS file supposed to contain a P2 frame data set.
     
    3641        >>> psi_configuration = 'psi.web01_configuration'
    3742        >>> p2ft = P2FitsTester(fits_file, psi_configuration)
    38         >>> (message, values) = p2ft.test()
    39         >>> print message # doctest:+ELLIPSIS
    40         PSDC-940-006-01, 3.6.3, 1): OK
    41         PSDC-940-006-01, 3.6.6.8: OK
    42         PSDC-940-006-01, TBD_test_detections_frames: OK (frame 00 - SELECT * FROM ImageMeta WHERE imageID = 10543901)
    43         PSDC-940-006-01, TBD_test_detections_frames: OK (frame 01 - SELECT * FROM ImageMeta WHERE imageID = 10543902)
    44         ...
    45         PSDC-940-006-01, TBD_test_detections_frames: OK (frame 57 - SELECT * FROM ImageMeta WHERE imageID = 10543976)
    46         >>> print values
    47         None
    48         """
    49         report = StringIO()
     43        >>> product = p2ft.test(False)
     44        >>> print product.success
     45        False
     46
     47        >>> product = p2ft.test(True)
     48        >>> print product.success
     49        True
     50        """
     51        PsPsLogger.info('Testing P2FitsTester object')
    5052        # 1. There is no image for the PrimaryHDU (at 0)
    51         (messages, other) = self.test_primary()
    52         report.write(messages)
     53        PsPsLogger.debug('  Testing P2FitsTester object: primary')
     54        product = self.test_primary()
     55        if not product.success:
     56            return product
    5357        # 2. Look at the FrameMeta information
    54         (messages, values) = self.test_frame_meta()
    55         report.write('\n' + messages)
    56         if values is None:
    57             return (report.getvalue(), None)
    58         # 3. There should be values['ota'] sequences of [ImageMeta,
     58        PsPsLogger.debug('  Testing P2FitsTester object: frameMeta')
     59        product = self.test_frame_meta(be_tolerant_for_types)
     60        # Fail if there is any failure and we are type-strict
     61        if not product.success and not be_tolerant_for_types:
     62            return product
     63        # 3. There should be 'product.nOTA' sequences of [ImageMeta,
    5964        # Detection, SkinnyObject, ObjectCalColor] frames
    60         frameID = values['frameID']
    61         nOTA = values['nOTA']
     65        frameID = product.frameID
     66        nOTA = product.nOTA
    6267        if len(self.fits) != 4*nOTA + 2:
    6368            report.write('\nInvalid number of OTA: from FITS file: %d / from FrameMeta %d'
     
    6570            return (report.getvalue(), None)
    6671        for ota_index in range(nOTA):
    67             (messages, values) = self.test_detections_frames(frameID, ota_index)
     72            PsPsLogger.debug('  Testing P2FitsTester object: OTA (%d/%d)'
     73                               % ((ota_index+1), nOTA))
     74            (messages, values) = self.test_detections_frames(frameID, ota_index,
     75                                                             be_tolerant_for_types)
     76            PsPsLogger.debug(messages)
    6877            report.write('\n' + messages)
    6978        return (report.getvalue(), None)
    7079
    71     def test_detections_frames(self, frameID, ota_index):
     80    #####################################################
     81    def test_detections_frames(self, frameID, ota_index, be_tolerant_for_types):
    7282        """
    7383        Tests the contents of the 4-frame sequence [ImageMeta,
    7484        Detection, SkinnyObject, ObjectCalColor].
    7585        Those contents can be queried by: TODO
    76        
    77         """
    78         report = StringIO()
    79         # Check that the 4 sequence is correct
     86        """
     87        # Check that the 4-frame sequence is correct
    8088        requirement = 'PSDC-940-006-01, TBD_test_detections_frames: '
    8189        fits_index = 4*ota_index+2
     90        product = TestProduct()
     91        TestReport.title('Data frames tests')
    8292        if self.fits[fits_index].name != 'IMAGEMETA':
    83             return (requirement + 'KO (Not an ImageMeta frame)', None)
     93            TestReport.ko(requirement,
     94                          'Not an ImageMeta frame at index %d' % fits_index)
     95            return product
    8496        if self.fits[fits_index+1].name != 'DETECTION':
    85             return (requirement + 'KO (Not a Detection frame)', None)
     97            TestReport.ko(requirement,
     98                          'Not a Detection frame at index %d' % fits_index)
     99            return product
    86100        if self.fits[fits_index+2].name != 'SKINNYOBJECT':
    87             return (requirement + 'KO (Not a SkinnyObject frame)', None)
     101            TestReport.ko(requirement,
     102                          'Not a SkinnyObject frame at index %d' % fits_index)
     103            return product
    88104        if self.fits[fits_index+3].name != 'OBJECTCALCOLOR':
    89             return (requirement + 'KO (Not a ObjectCalColor frame)', None)
     105            TestReport.ko(requirement,
     106                          'Not an ObjectCalColor frame at index %d' % fits_index)
     107            return product
     108        TestReport.ok(requirement)
    90109        # Check ImageMeta values (!We get imageID from the FITS file
    91110        # since they are not sorted)
     111        PsPsLogger.debug('  Checking ImageMeta values')
    92112        imageID = self.fits[fits_index].data.field('imageID')[0]
    93113        query = 'SELECT * FROM ImageMeta WHERE imageID = %s' % str(imageID)
    94114        answer = self.psi_inquisitor.query(query)
    95         (message, status) = match(self.fits[fits_index].data, answer, requirement)
    96         if status != 0:
    97             return (message + ' (frame %02d - %s)' % (ota_index, query), None)
    98         report.write(message)
     115        TestReport.title('ImageMeta values tests (frame %d - %s)'
     116                         % (ota_index, query))
     117        subproduct = match(self.fits[fits_index].data, answer, requirement,
     118                           tolerance = Configuration.TOLERANCE,
     119                           max_failures = Configuration.LIMIT)
     120        if not subproduct.success and not be_tolerant_for_types:
     121            return product
    99122        # Extract the number of detections
    100123        nDetect = int(self.fits[fits_index].data.field('nDetect')[0])
     
    103126        howMany = self.psi_inquisitor.query(query)['items'][0]['HowMany']
    104127        if nDetect != howMany:
    105             report.write('\nGot %d Detection items from PSI instead of %d for image %s'
    106                          % (howMany, nDetect, str(imageID)) )
     128            TestReport.ko(requirement,
     129                          'Got %d Detection items from PSI instead of %d for image %s'
     130                          % (howMany, nDetect, str(imageID)) )
     131            return product
    107132        # Get the nDetect detections (they are assumed to be sorted in the FITS file)
     133        PsPsLogger.debug('  Checking Detection values')
    108134        query = 'SELECT * FROM Detection WHERE imageID = %s ORDER BY detectID' % str(imageID)
    109135        answer = self.psi_inquisitor.query(query)
     136        count = 0
    110137        for detection_index in range(nDetect):
    111             (message, status) = match(self.fits[fits_index+1].data, answer,
    112                                       requirement, detection_index)
    113             report.write('\n' + message)
    114         return (report.getvalue() + ' (frame %02d - %s)' % (ota_index, query), None)
    115 
    116     def test_frame_meta(self):
     138            PsPsLogger.debug('  Detection index: %d out of %d'
     139                               % (detection_index+1, nDetect))
     140            subproduct = match(self.fits[fits_index+1].data,
     141                               answer,
     142                               requirement,
     143                               tolerance = Configuration.TOLERANCE,
     144                               fits_index = detection_index,
     145                               max_failures = Configuration.LIMIT)
     146            if not subproduct.success:
     147                TestReport.ko(requirement,
     148                              'Comparison Matching failed')
     149                if not be_tolerant_for_types:
     150                    return product
     151        product.success = True
     152        return product
     153
     154    #################################################
     155    def test_frame_meta(self, be_tolerant_for_types):
    117156        """
    118157        Tests the contents of the FrameMeta table.
     
    124163        """
    125164        requirement = 'PSDC-940-006-01, 3.6.6.8: '
     165        product = TestProduct()
     166        TestReport.title('MetaFrame tests')
    126167        if self.fits[1].header['NAXIS'] != 2:
    127             return (requirement + 'KO (NAXIS != 2)', None)
     168            TestReport.ko(requirement, 'NAXIS != 2')
     169            return product
    128170        if self.fits[1].header['NAXIS2'] != 1:
    129             return (requirement + 'KO (NAXIS2 != 1)', None)
     171            TestReport.ko(requirement, 'NAXIS2 != 1')
     172            return product
    130173        if self.fits[1].header['TFIELDS'] != 48:
    131             return (requirement + 'KO (TFIELDS != 48)', None)
     174            TestReport.ko(requirement, 'TFIELDS != 48')
     175            return product
    132176        frameID = self.fits[1].data.field('frameID')[0]
    133177        query = "SELECT * FROM FrameMeta WHERE frameID = %d" % frameID
    134178        answer = self.psi_inquisitor.query(query)
    135         (message, status) = match(self.fits[1].data, answer, requirement)
    136         if status != 0:
    137             return (message, None)
    138         else:
    139             return (message,
    140                     {'frameID': int(self.fits[1].data.field('frameID')[0]),
    141                      'nOTA': int(self.fits[1].data.field('nOTA')[0]) })
     179        product = match(self.fits[1].data,
     180                        answer,
     181                        requirement,
     182                        max_failures = Configuration.LIMIT,
     183                        tolerance = Configuration.TOLERANCE)
     184        if not product.success and not be_tolerant_for_types:
     185            return product
     186        # Extend the product with some useful values
     187        product.frameID = int(self.fits[1].data.field('frameID')[0])
     188        product.nOTA = int(self.fits[1].data.field('nOTA')[0])
     189        return product
    142190   
     191    #######################
    143192    def test_primary(self):
    144193        """
    145194        Check that the primary header i.e. fits[0] has no dimension.
    146195        """
    147         requirement = 'PSDC-940-006-01, 3.6.3, 1): '
     196        TestReport.title('Primary frame tests')
     197        requirement = 'PSDC-940-006-01, 3.6.3, 1'
     198        product = TestProduct()
    148199        if self.fits[0].header['NAXIS'] != 0:
    149             return (requirement + 'KO', None)
     200            TestReport.ko(requirement, 'Dimension should be 0')
     201            return product
    150202        # Add more tests?
    151         return (requirement + 'OK', None)
     203        product.success = True
     204        TestReport.ok(requirement)
     205        return product
    152206
    153207if __name__ == '__main__':
    154     import doctest
    155     doctest.testmod()
     208    import logging
     209    import sys
     210    PsPsLogger.setLevel(logging.DEBUG)
     211    current_argument_position = 1
     212    while current_argument_position < len(sys.argv):
     213        if sys.argv[current_argument_position] == '-v':
     214            PsPsLogger.set_stderr()
     215            PsPsLogger.set_fileout('dummy.log')
     216            current_argument_position += 1
     217        elif sys.argv[current_argument_position] == 'test':
     218            print 'Running unittest for P2FitsTester functions'
     219            import doctest
     220            doctest.testmod()
     221            sys.exit(0)
  • branches/sc_branches/psps_testing/testers/fits_file.py

    r29140 r29227  
    22import pyfits
    33from testers.fits.p2 import P2FitsTester
     4# Logging
     5from utilities.psps_logger import PsPsLogger
     6from utilities.configuration import Configuration
     7from utilities.test_report import TestReport
    48
    59"""
     
    812"""
    913class FitsFileTester:
    10     class Type:
    11         """
    12         Definition taken from 5.2
    13         """
    14         UNKNOWN = {'id': 00, 'code': ''}
    15         INITIALIZATION = 10
    16         DETECTION = 20
    17         STACK = 30
    18         DIFFERENCE = 40
    19         OBJECTS = 50
    20 
    2114    _TMPDIR = '.tmp'
    2215    @staticmethod
     
    6053        self.fitsFile = pyfits.open(self.filename)
    6154        self.psi_configuration = psi_configuration
     55        TestReport.info(str(self.psi_configuration))
    6256
    6357    def __del__(self):
    6458        """
    65         Closes the FITS file
     59        Explicitly closes the FITS file
    6660        """
    6761        self.fitsFile.close()
     
    7165        Tests the contents of the FITS file
    7266
    73         >>> fitsname = '00105439.FITS'
    74         >>> basename = 'B00029152'
     67        >>> fitsname = '00000010.FITS'
     68        >>> basename = 'B00000010'
    7569        >>> tgz_filename = 'data/psut/ok/' + basename + '.tar.gz'
    7670
     
    7872        >>> FitsFileTester._setup_test_environment(basename, tgz_filename)
    7973        >>> fft = FitsFileTester(fitsname, basename, '.tmp', 'P2')
    80         >>> print fft.test()
    81         ('BARF', None)
     74        >>> product = fft.test()
     75        >>> print product.success
     76        False
    8277        >>> # Delete temporary directory
    8378        >>> FitsFileTester._remove_test_environment()
     
    9287        """
    9388        if self.fitsType == "P2":
    94             return P2FitsTester(self.fitsFile, self.psi_configuration).test()
     89            return P2FitsTester(self.fitsFile,
     90                                self.psi_configuration).test(Configuration.BE_TYPE_TOLERANT)
    9591        else:
    9692            raise Exception("Unsupported FITS type [%s]" % self.fitsType)
    9793
    9894if __name__ == '__main__':
    99     import doctest
    100     doctest.testmod()
     95    import logging
     96    import sys
     97    PsPsLogger.setLevel(logging.DEBUG)
     98    current_argument_position = 1
     99    while current_argument_position < len(sys.argv):
     100        if sys.argv[current_argument_position] == '-v':
     101            PsPsLogger.set_stderr()
     102            current_argument_position += 1
     103        elif sys.argv[current_argument_position] == 'test':
     104            print 'Running unittest for FitsFileTester class'
     105            import doctest
     106            doctest.testmod()
     107            sys.exit(0)
  • branches/sc_branches/psps_testing/utilities/configuration.py

    r29111 r29227  
    88    # The location of the validating XSD file
    99    XSD_FILE = 'data/xsd/BatchManifest.xsd'
     10    # xmllint path
     11    XMLLINT = '/usr/bin/xmllint'
     12    # Limit to numeric tests failures in match function
     13    LIMIT = 15 # Can be None, 100, -1
     14    # Tolerance value for floating-point numbers
     15    TOLERANCE = 1.0e-5
     16    # Be type tolerant (at least until all those promotions concerns
     17    # are not fixed). The value is used in FitsFileTester.test()
     18    BE_TYPE_TOLERANT = True
     19
     20    def __repr__(self):
     21        from StringIO import StringIO
     22        representation = StringIO()
     23        representation.write('Tests Configuration Values:\n')
     24        representation.write('  File extension: [%s]\n'
     25                             % Configuration.EXTENSION)
     26        representation.write('  Batch manifest name: [%s]\n'
     27                             % Configuration.BATCH_MANIFEST)
     28        representation.write('  XSD file: [%s]\n'
     29                             % Configuration.XSD_FILE)
     30        representation.write('  XML validation tool: [%s]\n'
     31                             % Configuration.XMLLINT)
     32        representation.write('  Limit for test failure in a single test item: [%d]\n'
     33                             % Configuration.LIMIT)
     34        representation.write('  Tolerance for floating-point comparison: [%s]\n'
     35                             % Configuration.TOLERANCE)
     36        if Configuration.BE_TYPE_TOLERANT:
     37            tolerant = 'never'
     38        else:
     39            tolerant = 'always'
     40        representation.write('  Different types comparison [%s] fails'
     41                             % tolerant)
     42        return representation.getvalue()
  • branches/sc_branches/psps_testing/utilities/psps_logger.py

    r29140 r29227  
    22import sys
    33
    4 class PsPsLogger:
     4class PsPsLoggerClass:
    55    """
    66    Logging facility for PSPS Testing framework.
     
    88    http://code.activestate.com/recipes/52558-the-singleton-pattern-implemented-with-python/
    99
    10     Check PsPsLogger.__init__() to see how it is used.
     10    Check PsPsLoggerClass.__init__() to see how it is used.
    1111    """
    1212    datefmt = '%H:%M:%S'
     
    1818            """Sets logging up"""
    1919            logging.Logger.__init__(self, __name__)
    20             logging.basicConfig(level=logging.INFO, format=PsPsLogger.fmt)
     20            logging.basicConfig(level=logging.INFO, format=PsPsLoggerClass.fmt)
    2121            try:
    2222                handler = logging.NullHandler()
    2323            except AttributeError: # logging.NullHandler only python >= 2.7
    2424                handler = logging.StreamHandler(open('/dev/null', 'w'))
    25             handler.setFormatter(logging.Formatter(PsPsLogger.fmt,
    26                                                    PsPsLogger.datefmt))
     25            handler.setFormatter(logging.Formatter(PsPsLoggerClass.fmt,
     26                                                   PsPsLoggerClass.datefmt))
    2727            self.addHandler(handler)
    2828        def id(self):
     
    3737        Creates singleton instance.
    3838
    39         >>> logger1 = PsPsLogger()
     39        >>> logger1 = PsPsLoggerClass()
    4040        >>> logger1.debug('This message is not displayed')
    41         >>> logger2 = PsPsLogger()
     41        >>> logger2 = PsPsLoggerClass()
    4242        >>> logger1.id() == logger2.id()
    4343        True
     
    4545        >>> logger1.warning('This message is not displayed')
    4646        >>> logger1.setLevel(logging.INFO)
    47         >>> PsPsLogger().debug('This message is not displayed')
     47        >>> PsPsLoggerClass().debug('This message is not displayed')
    4848        >>> logger1.setLevel(logging.DEBUG)
    49         >>> PsPsLogger().debug('This message is not displayed')
     49        >>> PsPsLoggerClass().debug('This message is not displayed')
    5050        """
    5151        # Check whether we already have an instance
    52         if PsPsLogger.__instance is None:
     52        if PsPsLoggerClass.__instance is None:
    5353            # Create and remember instance
    54             PsPsLogger.__instance = PsPsLogger.__impl()
     54            PsPsLoggerClass.__instance = PsPsLoggerClass.__impl()
    5555        # Store instance reference as the only member in the handle
    56         self.__dict__['_PsPsLogger__instance'] = PsPsLogger.__instance
     56        self.__dict__['_PsPsLoggerClass__instance'] = PsPsLoggerClass.__instance
    5757
    5858    def __getattr__(self, attr):
     
    6767        """
    6868        Set up the logging to sys.stdout
    69         >>> logger = PsPsLogger()
     69        >>> logger = PsPsLoggerClass()
    7070        >>> logger.set_stdout()
    7171        >>> logger.setLevel(logging.DEBUG)
     
    8585        """
    8686        Set up the logging to sys.stderr
    87         >>> logger = PsPsLogger()
     87        >>> logger = PsPsLoggerClass()
    8888        >>> logger.set_stderr()
    8989        >>> logger.setLevel(logging.DEBUG)
     
    103103        """ Set up the logging to some file """
    104104        if fmt == None:
    105             fmt = PsPsLogger.fmt
     105            fmt = PsPsLoggerClass.fmt
    106106        if datefmt == None:
    107             datefmt = PsPsLogger.datefmt
     107            datefmt = PsPsLoggerClass.datefmt
    108108        handler = logging.StreamHandler(open(filename, 'w'))
    109109        handler.setFormatter(logging.Formatter(fmt, datefmt))
     
    117117        self.critical('The last is critical')
    118118
     119PsPsLogger = PsPsLoggerClass()
     120
    119121if __name__ == '__main__':
    120122    if len(sys.argv)<2:
     
    124126    # if sys.argv[1] == 'testfile':
    125127    #     print 'Testing for %s' % sys.argv[2]
    126     #     PsPsLogger().set_fileout(sys.argv[2],
     128    #     PsPsLoggerClass().set_fileout(sys.argv[2],
    127129    #                              '[%(asctime)8s %(levelname)5s] %(message)s', '%H:%M:%S')
    128     #     PsPsLogger().setLevel(logging.INFO)
    129     #     logger = PsPsLogger()
     130    #     PsPsLoggerClass().setLevel(logging.INFO)
     131    #     logger = PsPsLoggerClass()
    130132    #     logger.setLevel(logging.DEBUG)
    131133    #     print '5 messages'
  • branches/sc_branches/psps_testing/utilities/util.py

    r29140 r29227  
    1 from StringIO import StringIO
    21import numpy
    3 
    4 def equal(a, b, tolerance = 1.e-5):
     2from utilities.psps_logger import PsPsLogger
     3from utilities.test_report import TestReport
     4from utilities.test_product import TestProduct
     5
     6def equal(a, b, tolerance = 1.e-15):
    57    """
    68    Compares two floating-point numbers and consider them equal if
     
    2224    """
    2325    try:
    24         if a.__class__ != b.__class__:
    25             # print 'Warning! Comparing different types: %s and %s' % (a.__class__.__name__, b.__class__.__name__)
    26             b = a.__class__(b)
    2726        return abs(a-b)<tolerance
    2827    except TypeError:
    2928        return a == b
    3029
    31 def match(fits_data, psi_answer, requirement, tolerance = 1e-5, fits_index=0):
     30def match(fits_data,
     31          psi_answer,
     32          requirement,
     33          tolerance = 1e-15,
     34          fits_index=0,
     35          max_failures = None):
    3236    """
    3337    Compares the values of data contained in a FITS file and those
     
    4448    >>> answer['items'] = [{}]
    4549    >>> answer['items'][0]['key'] = 'value'
    46     >>> (message, status) = match(fits, answer, 'Req: ')
    47     >>> print message
    48     Req: OK
    49     >>> print status
    50     0
     50    >>> product = match(fits, answer, 'Req: ')
     51    >>> print product.success
     52    True
    5153
    5254    >>> answer['items'][0]['key'] = 'VALUE'
    53     >>> (message, status) = match(fits, answer, 'Req: ')
    54     >>> print message
    55     Req: KO Different values for element key (from psi = "VALUE", from FITS = "value")
    56     >>> print status
    57     1
     55    >>> product = match(fits, answer, 'Req: ')
     56    >>> print product.success
     57    False
    5858
    5959    >>> fits2 = DummyFits()
     
    6262    >>> answer2['items'] = [{}]
    6363    >>> answer2['items'][0]['sky'] = 745.895
    64     >>> (message, status) = match(fits2, answer2, 'Req: ')
    65     >>> print message
    66     Req: OK
    67     >>> print status
    68     0
     64    >>> product = match(fits2, answer2, 'Req: ')
     65    >>> print product.success
     66    True
    6967
    7068    >>> fits2 = DummyFits()
     
    7371    >>> answer2['items'] = [{}]
    7472    >>> answer2['items'][0]['sky'] = 745.896
    75     >>> (message, status) = match(fits2, answer2, 'Req: ')
    76     >>> print message
    77     Req: KO Different values for element sky (from psi = "745.896", from FITS = "745.895")
    78     >>> print status
    79     1
     73    >>> product = match(fits2, answer2, 'Req: ')
     74    >>> print product.success
     75    False
    8076
    8177    >>> fits2._fields['sky2'] = [745.895]
    8278    >>> answer2['items'][0]['sky2'] = 745.896
    83     >>> (message, status) = match(fits2, answer2, 'Req: ')
    84     >>> print message
    85     Req: KO Different values for element sky2 (from psi = "745.896", from FITS = "745.895")
    86     Req: KO Different values for element sky (from psi = "745.896", from FITS = "745.895")
    87     >>> print status
    88     1
    89     """
    90     status = 0
    91     report = StringIO()
     79    >>> product = match(fits2, answer2, 'Req: ')
     80    >>> print product.success
     81    False
     82
     83    >>> fits2._fields['sky2'] = [1792.05]
     84    >>> answer2['items'][0]['sky2'] = 1792.054
     85    >>> product = match(fits2, answer2, 'Req: ')
     86    >>> print product.success
     87    False
     88
     89    """
     90    product = TestProduct()
     91    first_time = True
     92    complain = True
     93    PsPsLogger.debug('match(): %d rows to compare' % len(psi_answer['items']))
     94    items_count = 1
     95    tenPercent = len(psi_answer['items'])/10
     96    nextTenthPercents = int(tenPercent)
    9297    for items in psi_answer['items']:
     98        if first_time:
     99            PsPsLogger.debug('match(): %d items in columns'
     100                             % (len(items.items())))
     101            first_time = False
     102        if items_count == nextTenthPercents:
     103            PsPsLogger.debug('match(): %d out of %d'
     104                             % (items_count,
     105                                len(psi_answer['items'])))
     106            nextTenthPercents += tenPercent
     107        items_count += 1
     108        failures_count = 0
    93109        for (key, value) in items.items():
    94             same = (fits_data.field(str(key))[fits_index] == value)
    95             if not same and not isinstance(value, str):
    96                 same = equal(fits_data.field(str(key))[0], value)
     110            fits_value = fits_data.field(str(key))[fits_index]
     111            if fits_value.__class__.__name__ != value.__class__.__name__:
     112                if complain:
     113                    TestReport.ko(requirement,
     114                                  'Classes of FITS value (%s/%s) and PSI value (%s/%s) are different for key \'%s\''
     115                                  % (fits_value.__class__.__name__,
     116                                     fits_value,
     117                                     value.__class__.__name__,
     118                                     value,
     119                                     str(key)))
     120                failures_count += 1
     121                complain = complain and __still_complain(max_failures, failures_count)
     122            psi_value = fits_value.__class__(value)
     123            same = (fits_data.field(str(key))[fits_index] == psi_value)
     124            if not same and not isinstance(psi_value, str):
     125                same = equal(fits_data.field(str(key))[0],
     126                             psi_value,
     127                             tolerance)
    97128            if not same:
    98                 if status == 1:
    99                     report.write('\n')
    100                 report.write('%sKO Different values for element %s (from psi = "%s", from FITS = "%s")' % (requirement, key, str(value), str(fits_data.field(key)[fits_index])))
    101                 status = 1
    102     if status == 0:
    103         report.write(requirement + 'OK')
    104     return (report.getvalue(), status)
    105 
    106 def convert(type, value):
    107     """
    108     >>> a = convert('Float', '55163.4545890027')
    109     >>> b = 55163.454589
     129                if complain:
     130                    TestReport.ko(requirement,
     131                                  'Different values for key %s: PSI = [%s] (%s) / FITS = [%s] (%s) / FITS index = %d' %
     132                                  (key,
     133                                   psi_value,
     134                                   psi_value.__class__.__name__,
     135                                   fits_data.field(key)[fits_index],
     136                                   fits_data.field(key)[fits_index].__class__.__name__,
     137                                   fits_index))
     138                failures_count += 1
     139                complain = complain and __still_complain(max_failures, failures_count)
     140    if failures_count == 0:
     141        product.success = True
     142        TestReport.ok(requirement)
     143    else:
     144        if not complain:
     145            # Write the summary of all errors
     146            TestReport.ko(requirement,
     147                          'Total of %d comparison errors for match (comparison over %d rows of %d columns)'
     148                          % (failures_count,
     149                             len(psi_answer['items']),
     150                             len(items.items())))
     151    return product
     152
     153def __still_complain(max_failures, failures_count):
     154    if max_failures is not None and failures_count >= max_failures:
     155        TestReport.ko('INFO', 'Limit of failures reached: %d (total number of errors should follow' % failures_count)
     156        return False
     157    return True
     158
     159def psi_convert(type, value):
     160    """
     161    >>> a = psi_convert('Float', '55163.4545890027')
     162    >>> b = 55163.4545890027
     163    >>> print (a, b)
     164    (55163.4545890027, 55163.4545890027)
    110165    >>> equal(a,b)
    111166    True
    112     >>> a = convert('Real', '55163.4545890027')
    113     >>> b = 55163.454589
     167    >>> a = psi_convert('Real', '55163.4545890027')
     168    >>> b = 55163.4545890027
     169    >>> print (a, b)
     170    (55163.453, 55163.4545890027)
    114171    >>> equal(a,b)
    115172    False
    116     >>> equal(convert('String', 'Dummy'), 'Dummy')
    117     True
    118     >>> equal(convert('String', 'Dummy'), 'Dumy')
    119     False
    120     >>> convert('UnsupportedType', '45')
     173    >>> equal(psi_convert('String', 'Dummy'), 'Dummy')
     174    True
     175    >>> equal(psi_convert('String', 'Dummy'), 'Dumy')
     176    False
     177    >>> psi_convert('UnsupportedType', '45')
    121178    Traceback (most recent call last):
    122179    ...
    123180    Exception: Type 'UnsupportedType' is not supported
    124181    """
     182    # PsPsLogger.debug('Value class: %s (%s/%s)'
     183    #                    % (value.__class__.__name__,
     184    #                       str(value), type))
    125185    if type == 'String':
    126186        return str(value).replace('"', '')
     
    137197    raise Exception('Type \'%s\' is not supported' % type)
    138198
     199# def weak_convert(a, b):
     200#     """
     201#     If 'a' has a weaker type than 'b', returns the tuple
     202#     (a, a.__class__(b)), otherwise returns  the tuple
     203#     (b.__class__(a), b)
     204
     205#     Types must be comparable:
     206#     - numpy.float32 < numpy.float64
     207#     - numpy.int8 < numpy.int16 < numpy.int32 < numpy.int64
     208#     """
     209#     if
     210
    139211if __name__ == '__main__':
    140     import doctest
    141     doctest.testmod()
     212    import logging
     213    import sys
     214    PsPsLogger.setLevel(logging.DEBUG)
     215    current_argument_position = 1
     216    while current_argument_position < len(sys.argv):
     217        if sys.argv[current_argument_position] == '-v':
     218            PsPsLogger.set_stderr()
     219            current_argument_position += 1
     220        elif sys.argv[current_argument_position] == 'test':
     221            print 'Running unittest for util functions'
     222            import doctest
     223            doctest.testmod()
     224            sys.exit(0)
Note: See TracChangeset for help on using the changeset viewer.