]> SALOME platform Git repositories - tools/sat.git/commitdiff
Salome HOME
'sat test': add the script and the script traces in the log
authorSerge Rehbinder <serge.rehbinder@cea.fr>
Wed, 20 Jul 2016 12:52:45 +0000 (14:52 +0200)
committerSerge Rehbinder <serge.rehbinder@cea.fr>
Wed, 20 Jul 2016 12:52:45 +0000 (14:52 +0200)
commands/test.py
data/site.pyconf
src/__init__.py
src/test_module.py
src/xmlManager.py
src/xsl/test.xsl

index d16e9df60f9723b3f95003c161f949dd61d331e6..571f67ca78d57198c8d71957ae1419b9c5ea35c2 100644 (file)
@@ -37,8 +37,8 @@ parser = src.options.Options()
 parser.add_option('a', 'appli', 'string', 'appli',
     _('Use this option to specify the path to an installed application.'))
 parser.add_option('g', 'grid', 'string', 'grid',
-    _("""Indicate the name of the grid to test.
-\tThis name has to be registered in sat. If your test base is not known by sat, use the option --dir."""))
+    _("Indicate the name of the grid to test.\n\tThis name has to be registered"
+      " in sat. If your test base is not known by sat, use the option --dir."))
 parser.add_option('m', 'module', 'list', 'modules',
     _('Indicate which module(s) to test (subdirectory of the grid).'))
 parser.add_option('t', 'type', 'list', 'types',
@@ -46,12 +46,11 @@ parser.add_option('t', 'type', 'list', 'types',
 parser.add_option('d', 'dir', 'string', 'dir',
     _('Indicate the directory containing the test base.'), "")
 parser.add_option('', 'mode', 'string', 'mode',
-    _("Indicate which kind of test to run. If MODE is 'batch' only python and NO_GUI tests are run."), "normal")
+    _("Indicate which kind of test to run. If MODE is 'batch' only python and"
+      " NO_GUI tests are run."), "normal")
 parser.add_option('', 'display', 'string', 'display',
-    _("""Set the display where to launch SALOME.
-\tIf value is NO then option --show-desktop=0 will be used to launch SALOME."""))
-parser.add_option('n', 'name', 'string', 'session',
-    _('Give a name to the test session (REQUIRED if no product).'))
+    _("Set the display where to launch SALOME."
+"\tIf value is NO then option --show-desktop=0 will be used to launch SALOME."))
 parser.add_option('', 'light', 'boolean', 'light',
     _('Only run minimal tests declared in TestsLight.txt.'), False)
 
@@ -64,6 +63,13 @@ def description():
     return _("The test command runs a test base on a SALOME installation.")     
 
 def parse_option(args, config):
+    """ Parse the options and do some verifications about it
+    
+    :param args List: The list of arguments of the command
+    :param config Config: The global configuration
+    :return: the options of the current command launch and the full arguments
+    :rtype: Tuple (options, args)
+    """
     (options, args) = parser.parse_args(args)
 
     if not options.appli:
@@ -81,6 +87,8 @@ def parse_option(args, config):
     return (options, args)
 
 def ask_a_path():
+    """ 
+    """
     path = raw_input("enter a path where to save the result: ")
     if path == "":
         result = raw_input("the result will be not save. Are you sure to "
@@ -218,27 +226,6 @@ def check_remote_machine(machine_name, logger):
     else:
         logger.write(src.printcolors.printcSuccess(src.OK_STATUS) + "\n\n", 4)
 
-##
-# Transform YYYYMMDD_hhmmss into YYYY-MM-DD hh:mm:ss.
-def parse_date(date):
-    if len(date) != 15:
-        return date
-    res = "%s-%s-%s %s:%s:%s" % (date[0:4], date[4:6], date[6:8], date[9:11], date[11:13], date[13:])
-    return res
-
-##
-# Writes a report file from a XML tree.
-def write_report(filename, xmlroot, stylesheet):
-    if not os.path.exists(os.path.dirname(filename)):
-        os.makedirs(os.path.dirname(filename))
-
-    f = open(filename, "w")
-    f.write("<?xml version='1.0' encoding='utf-8'?>\n")
-    if len(stylesheet) > 0:
-        f.write("<?xml-stylesheet type='text/xsl' href='%s'?>\n" % stylesheet)
-    f.write(etree.tostring(xmlroot, encoding='utf-8'))
-    f.close()
-
 ##
 # Creates the XML report for a product.
 def create_test_report(config, dest_path, stylesheet, xmlname=""):
@@ -251,18 +238,24 @@ def create_test_report(config, dest_path, stylesheet, xmlname=""):
 
     if withappli:
 
-        add_simple_node(prod_node, "version_to_download", config.APPLICATION.name)
+        add_simple_node(prod_node, "version_to_download",
+                        config.APPLICATION.name)
         
         add_simple_node(prod_node, "out_dir", config.APPLICATION.workdir)
 
     # add environment
     exec_node = add_simple_node(prod_node, "exec")
     exec_node.append(etree.Element("env", name="Host", value=config.VARS.node))
-    exec_node.append(etree.Element("env", name="Architecture", value=config.VARS.dist))
-    exec_node.append(etree.Element("env", name="Number of processors", value=str(config.VARS.nb_proc)))    
-    exec_node.append(etree.Element("env", name="Begin date", value=parse_date(config.VARS.datehour)))
-    exec_node.append(etree.Element("env", name="Command", value=config.VARS.command))
-    exec_node.append(etree.Element("env", name="sat version", value=config.INTERNAL.sat_version))
+    exec_node.append(etree.Element("env", name="Architecture",
+                                   value=config.VARS.dist))
+    exec_node.append(etree.Element("env", name="Number of processors",
+                                   value=str(config.VARS.nb_proc)))    
+    exec_node.append(etree.Element("env", name="Begin date",
+                                   value=src.parse_date(config.VARS.datehour)))
+    exec_node.append(etree.Element("env", name="Command",
+                                   value=config.VARS.command))
+    exec_node.append(etree.Element("env", name="sat version",
+                                   value=config.INTERNAL.sat_version))
 
     if 'TESTS' in config:
         tests = add_simple_node(prod_node, "tests")
@@ -295,9 +288,8 @@ def create_test_report(config, dest_path, stylesheet, xmlname=""):
                     types["%s/%s" % (test.module, test.type)] = tyn
 
                 for script in test.script:
-                    tn = add_simple_node(types["%s/%s" % (test.module, test.type)], "test")
-                    #tn.attrib['grid'] = test.grid
-                    #tn.attrib['module'] = test.module
+                    tn = add_simple_node(types[
+                                    "%s/%s" % (test.module, test.type)], "test")
                     tn.attrib['type'] = test.type
                     tn.attrib['script'] = script.name
                     if 'callback' in script:
@@ -305,14 +297,27 @@ def create_test_report(config, dest_path, stylesheet, xmlname=""):
                             cnode = add_simple_node(tn, "callback")
                             if src.architecture.is_windows():
                                 import string
-                                cnode.text = filter(lambda x: x in string.printable,
-                                                    script.callback)
+                                cnode.text = filter(
+                                                lambda x: x in string.printable,
+                                                script.callback)
                             else:
-                                cnode.text = script.callback.decode('string_escape')
+                                cnode.text = script.callback.decode(
+                                                                'string_escape')
                         except UnicodeDecodeError as exc:
-                            zz = script.callback[:exc.start] + '?' + script.callback[exc.end-2:]
+                            zz = (script.callback[:exc.start] +
+                                  '?' +
+                                  script.callback[exc.end-2:])
                             cnode = add_simple_node(tn, "callback")
                             cnode.text = zz.decode("UTF-8")
+                    
+                    # Add the script content
+                    cnode = add_simple_node(tn, "content")
+                    cnode.text = script.content
+                    
+                    # Add the script execution log
+                    cnode = add_simple_node(tn, "out")
+                    cnode.text = script.out
+                    
                     if 'amend' in script:
                         cnode = add_simple_node(tn, "amend")
                         cnode.text = script.amend.decode("UTF-8")
@@ -325,8 +330,11 @@ def create_test_report(config, dest_path, stylesheet, xmlname=""):
 
                     if "amend" in script:
                         amend_test = add_simple_node(amend, "atest")
-                        amend_test.attrib['name'] = os.path.join(test.module, test.type, script.name)
-                        amend_test.attrib['reason'] = script.amend.decode("UTF-8")
+                        amend_test.attrib['name'] = os.path.join(test.module,
+                                                                 test.type,
+                                                                 script.name)
+                        amend_test.attrib['reason'] = script.amend.decode(
+                                                                        "UTF-8")
 
                     # calculate status
                     nb += 1
@@ -337,21 +345,29 @@ def create_test_report(config, dest_path, stylesheet, xmlname=""):
 
                     if "known_error" in script:
                         kf_script = add_simple_node(known_errors, "error")
-                        kf_script.attrib['name'] = os.path.join(test.module, test.type, script.name)
+                        kf_script.attrib['name'] = os.path.join(test.module,
+                                                                test.type,
+                                                                script.name)
                         kf_script.attrib['date'] = script.known_error.date
-                        kf_script.attrib['expected'] = script.known_error.expected
-                        kf_script.attrib['comment'] = script.known_error.comment.decode("UTF-8")
-                        kf_script.attrib['fixed'] = str(script.known_error.fixed)
-                        overdue = datetime.datetime.today().strftime("%Y-%m-%d") > script.known_error.expected
+                        kf_script.attrib[
+                                    'expected'] = script.known_error.expected
+                        kf_script.attrib[
+                         'comment'] = script.known_error.comment.decode("UTF-8")
+                        kf_script.attrib['fixed'] = str(
+                                                       script.known_error.fixed)
+                        overdue = datetime.datetime.today().strftime("%Y-%m-"
+                                            "%d") > script.known_error.expected
                         if overdue:
                             kf_script.attrib['overdue'] = str(overdue)
                         
                     elif script.res == src.KO_STATUS:
                         new_err = add_simple_node(new_errors, "new_error")
-                        script_path = os.path.join(test.module, test.type, script.name)
+                        script_path = os.path.join(test.module,
+                                                   test.type, script.name)
                         new_err.attrib['name'] = script_path
-                        new_err.attrib['cmd'] = "sat testerror %s -s %s -c 'my comment' -p %s" % \
-                            (application_name, script_path, config.VARS.dist)
+                        new_err.attrib['cmd'] = ("sat testerror %s -s %s -c 'my"
+                                                 " comment' -p %s" % \
+                            (application_name, script_path, config.VARS.dist))
 
 
             gn.attrib['total'] = str(nb)
@@ -365,7 +381,9 @@ def create_test_report(config, dest_path, stylesheet, xmlname=""):
     if not xmlname.endswith(".xml"):
         xmlname += ".xml"
 
-    write_report(os.path.join(dest_path, xmlname), root, stylesheet)
+    src.xmlManager.write_report(os.path.join(dest_path, xmlname),
+                                root,
+                                stylesheet)
     return src.OK_STATUS
 
 def run(args, runner, logger):
@@ -377,19 +395,19 @@ def run(args, runner, logger):
         raise src.SatException(_("The options --grid and --dir are not "
                                  "compatible!"))
 
-    with_product = False
+    with_application = False
     if runner.cfg.VARS.application != 'None':
         logger.write(_('Running tests on application %s\n') % 
                             src.printcolors.printcLabel(
                                                 runner.cfg.VARS.application), 1)
-        with_product = True
+        with_application = True
     elif options.dir:
         logger.write(_('Running tests from directory %s\n') % 
                             src.printcolors.printcLabel(options.dir), 1)
     elif not options.grid:
         raise src.SatException(_('a grid or a directory is required'))
 
-    if with_product:
+    if with_application:
         # check if environment is loaded
         if 'KERNEL_ROOT_DIR' in os.environ:
             logger.write(src.printcolors.printcWarning(_("WARNING: "
@@ -403,11 +421,6 @@ def run(args, runner, logger):
         logger.write(src.printcolors.printcWarning(_("WARNING running "
                                             "without a product.")) + "\n\n", 1)
 
-        # name for session is required
-        if not options.session:
-            raise src.SatException(_("--name argument is required when no "
-                                        "product is specified."))
-
         # check if environment is loaded
         if not 'KERNEL_ROOT_DIR' in os.environ:
             raise src.SatException(_("SALOME environment not found") + "\n")
@@ -422,7 +435,8 @@ def run(args, runner, logger):
         os.environ['DISPLAY'] = options.display
     elif 'DISPLAY' not in os.environ:
         # if no display set
-        if 'display' in runner.cfg.SITE.test and len(runner.cfg.SITE.test.display) > 0:
+        if ('display' in runner.cfg.SITE.test and 
+                                        len(runner.cfg.SITE.test.display) > 0):
             # use default value for test tool
             os.environ['DISPLAY'] = runner.cfg.SITE.test.display
         else:
@@ -430,8 +444,8 @@ def run(args, runner, logger):
 
     # initialization
     #################
-    if with_product:
-        tmp_dir = runner.cfg.SITE.test.tmp_dir_with_product
+    if with_application:
+        tmp_dir = runner.cfg.SITE.test.tmp_dir_with_application
     else:
         tmp_dir = runner.cfg.SITE.test.tmp_dir
 
@@ -461,7 +475,7 @@ def run(args, runner, logger):
     content = "\n".join(lines)
 
     # create hash from session information
-    dirname = sha1(content).hexdigest()
+    dirname = sha1(content.encode()).hexdigest()
     session_dir = os.path.join(tmp_dir, dirname)
     os.makedirs(session_dir)
     os.environ['TT_TMP_RESULT'] = session_dir
@@ -489,7 +503,8 @@ def run(args, runner, logger):
     grid = ""
     if options.grid:
         grid = options.grid
-    elif not options.dir and with_product and "test_base" in runner.cfg.APPLICATION:
+    elif (not options.dir and with_application and 
+                                        "test_base" in runner.cfg.APPLICATION):
         grid = runner.cfg.APPLICATION.test_base.name
 
     src.printcolors.print_value(logger, _('Display'), os.environ['DISPLAY'], 2)
@@ -516,7 +531,7 @@ def run(args, runner, logger):
     
     # run the test
     logger.allowPrintLevel = False
-    retcode = test_runner.run_all_tests(options.session)
+    retcode = test_runner.run_all_tests()
     logger.allowPrintLevel = True
 
     logger.write(_("Tests finished"), 1)
@@ -526,7 +541,10 @@ def run(args, runner, logger):
     out_dir = os.path.join(runner.cfg.SITE.log.log_dir, "TEST")
     src.ensure_path_exists(out_dir)
     name_xml_board = logger.logFileName.split(".")[0] + "board" + ".xml"
-    create_test_report(runner.cfg, out_dir, "test.xsl", xmlname = name_xml_board)
+    create_test_report(runner.cfg,
+                       out_dir,
+                       "test.xsl",
+                       xmlname = name_xml_board)
     xml_board_path = os.path.join(out_dir, name_xml_board)
     logger.l_logFiles.append(xml_board_path)
     logger.add_link(os.path.join("TEST", name_xml_board),
index 60ff90ddaa247dd06804ae1788bb9787cf40cd32..6652e7df57e009317d4a0ddeb22add3a0a593953 100644 (file)
@@ -9,7 +9,7 @@ SITE :
     }
     #base : $USER.workdir + $VARS.sep + "BASE-FROM-SITE"
     test :{
-           tmp_dir_with_product : '/tmp' + $VARS.sep + $VARS.user + $VARS.sep + $APPLICATION.name + $VARS.sep + 'test'
+           tmp_dir_with_application : '/tmp' + $VARS.sep + $VARS.user + $VARS.sep + $APPLICATION.name + $VARS.sep + 'test'
            tmp_dir : '/tmp' + $VARS.sep + $VARS.user + $VARS.sep + 'test'
            timeout : 150
            }
index fdc236bbc4a1cfc049e54228fbd5f6602080557a..f4c065d6aa6316a22fa5520d4854cbd839367b9d 100644 (file)
@@ -312,4 +312,21 @@ def deepcopy_list(input_list):
     res = []
     for elem in input_list:
         res.append(elem)
-    return res
\ No newline at end of file
+    return res
+
+def parse_date(date):
+    """Transform YYYYMMDD_hhmmss into YYYY-MM-DD hh:mm:ss.
+    
+    :param date str: The date to transform
+    :return: The date in the new format
+    :rtype: str
+    """
+    if len(date) != 15:
+        return date
+    res = "%s-%s-%s %s:%s:%s" % (date[0:4],
+                                 date[4:6],
+                                 date[6:8],
+                                 date[9:11],
+                                 date[11:13],
+                                 date[13:])
+    return res
index db4cb851e869c577f87a076121ad41483256aa86..e8dfb86670670cfe7128c21ffaf491172c0a413e 100644 (file)
 #  License along with this library; if not, write to the Free Software
 #  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 
+# Python 2/3 compatibility for execfile function
+try:
+    execfile
+except:
+    def execfile(somefile, global_vars, local_vars):
+        with open(somefile) as f:
+            code = compile(f.read(), somefile, 'exec')
+            exec(code, global_vars, local_vars)
+
+
 import os, sys, datetime, shutil, string
 import subprocess
-import fork
+from . import fork
 import src
 
 # directories not considered as test modules
 C_IGNORE_MODULES = ['.git', '.svn', 'RESSOURCES']
 
-C_TESTS_SOURCE_DIR = "Tests"
 C_TESTS_LIGHT_FILE = "TestsLight.txt"
 
 # Get directory to be used for the temporary files.
@@ -90,12 +99,15 @@ class Test:
                             symlinks=True)
 
     def prepare_grid_from_dir(self, grid_name, grid_dir):
-        self.logger.write(_("get grid from dir: %s\n") % src.printcolors.printcLabel(grid_dir), 3)
+        self.logger.write(_("get grid from dir: %s\n") % \
+                          src.printcolors.printcLabel(grid_dir), 3)
         if not os.access(grid_dir, os.X_OK):
-            raise src.SatException(_("testbase %(name)s (%(dir)s) does not exist ...\n") % \
-                { 'name': grid_name, 'dir': grid_dir })
+            raise src.SatException(_("testbase %(name)s (%(dir)s) does not "
+                                     "exist ...\n") % { 'name': grid_name,
+                                                       'dir': grid_dir })
 
-        self._copy_dir(grid_dir, os.path.join(self.sessionDir, 'BASES', grid_name))
+        self._copy_dir(grid_dir,
+                       os.path.join(self.sessionDir, 'BASES', grid_name))
 
     def prepare_grid_from_git(self, grid_name, grid_base, grid_tag):
         self.logger.write(
@@ -116,7 +128,9 @@ class Test:
             else:
                 cmd += " && git fetch origin %(branch)s:%(branch)s"
             cmd += " && git checkout %(branch)s"
-            cmd = cmd % { 'branch': grid_tag, 'base': grid_base, 'dir': grid_name }
+            cmd = cmd % { 'branch': grid_tag,
+                         'base': grid_base,
+                         'dir': grid_name }
 
             self.logger.write("> %s\n" % cmd, 5)
             if src.architecture.is_windows():
@@ -134,15 +148,17 @@ class Test:
                                 stdout=self.logger.logTxtFile,
                                 stderr=subprocess.PIPE)
             if res != 0:
-                raise src.SatException(_("Error: unable to get test base '%(name)s' from git '%(repo)s'.") % \
-                    { 'name': grid_name, 'repo': grid_base })
+                raise src.SatException(_("Error: unable to get test base "
+                                         "'%(name)s' from git '%(repo)s'.") % \
+                                       { 'name': grid_name, 'repo': grid_base })
 
         except OSError:
             self.logger.error(_("git is not installed. exiting...\n"))
             sys.exit(0)
 
     def prepare_grid_from_svn(self, user, grid_name, grid_base):
-        self.logger.write(_("get grid '%s' from svn\n") % src.printcolors.printcLabel(grid_name), 3)
+        self.logger.write(_("get grid '%s' from svn\n") % \
+                          src.printcolors.printcLabel(grid_name), 3)
         try:
             def set_signal(): # pragma: no cover
                 """see http://bugs.python.org/issue1652"""
@@ -306,6 +322,30 @@ class Test:
                         pass
 
                 results[test] = [status, exec_time, callback, expected]
+            
+            # check if <test>.py file exists
+            testfile = os.path.join(self.currentDir,
+                                   self.currentModule,
+                                   self.currentType,
+                                   test)
+            
+            if not os.path.exists(testfile):
+                results[test].append('')
+            else:
+                text = open(testfile, "r").read()
+                results[test].append(text)
+
+            # check if <test>.out.py file exists
+            outfile = os.path.join(self.currentDir,
+                                   self.currentModule,
+                                   self.currentType,
+                                   test[:-3] + ".out.py")
+            
+            if not os.path.exists(outfile):
+                results[test].append('')
+            else:
+                text = open(outfile, "r").read()
+                results[test].append(text)
 
         return results
 
@@ -401,8 +441,8 @@ class Test:
 
 
     def get_test_timeout(self, test_name, default_value):
-        if (self.settings.has_key("timeout") and 
-                self.settings["timeout"].has_key(test_name)):
+        if ("timeout" in self.settings and 
+                test_name in self.settings["timeout"]):
             return self.settings["timeout"][test_name]
 
         return default_value
@@ -443,7 +483,7 @@ class Test:
             else:
                 # New application
                 binSalome = self.appli
-                binPython = self.appli + ' shell'
+                binPython = self.appli + ' context'
                 killSalome = self.appli + ' killall'
                 return binSalome, binPython, killSalome
 
@@ -480,7 +520,7 @@ class Test:
             if src.architecture.is_windows():
                 binSalome += '.bat'
 
-            binPython = binSalome + ' shell'
+            binPython = binSalome + ' context'
             killSalome = binSalome + ' killall'
             return binSalome, binPython, killSalome
                 
@@ -585,7 +625,10 @@ class Test:
                 script_info.known_error.expected = kfres[1]
                 script_info.known_error.comment = kfres[2]
                 script_info.known_error.fixed = kfres[3]
-
+            
+            script_info.content = script_results[sr][4]
+            script_info.out = script_results[sr][5]
+            
             # add it to the list of results
             test_info.script.append(script_info, '')
 
@@ -784,7 +827,7 @@ class Test:
                 self.logger.write(src.printcolors.printcHeader("----------- end"
                                                 " %s" % script_name) + "\n", 2)
 
-    def run_all_tests(self, session_name=""):
+    def run_all_tests(self):
         initTime = datetime.datetime.now()
 
         self.run_script('test_setup')
@@ -839,9 +882,6 @@ class Test:
             status = src.KNOWNFAILURE_STATUS
         
         self.logger.write(_("Status: %s\n" % status), 3)
-        
-        if session_name is not None and len(session_name) > 0:
-            self.config.RESULTS.test["session"] = session_name
 
         return self.nb_run - self.nb_succeed - self.nb_acknoledge
 
index 7332cb4956bb413501e4db61c38c1879131042a7..c125c5124999487eb06cf2eba62fb16a012c9c7b 100644 (file)
@@ -169,3 +169,20 @@ def append_node_attrib(root_node, attrib):
     :param attrib dixt: The attrib to append
     '''
     root_node.attrib.update(attrib)
+
+def write_report(filename, xmlroot, stylesheet):
+    """Writes a report file from a XML tree.
+    
+    :param filename str: The path to the file to create
+    :param xmlroot etree.Element: the Etree element to write to the file
+    :param stylesheet str: The stylesheet to add to the begin of the file
+    """
+    if not os.path.exists(os.path.dirname(filename)):
+        os.makedirs(os.path.dirname(filename))
+
+    f = open(filename, "w")
+    f.write("<?xml version='1.0' encoding='utf-8'?>\n")
+    if len(stylesheet) > 0:
+        f.write("<?xml-stylesheet type='text/xsl' href='%s'?>\n" % stylesheet)
+    f.write(etree.tostring(xmlroot, encoding='utf-8'))
+    f.close()
\ No newline at end of file
index 0ebe1405259bcce54b02e59cb199523674147e6c..f517cacf78e06def781626896251728661c610d7 100644 (file)
@@ -79,6 +79,7 @@
 </style>
 <script language="JavaScript"><![CDATA[
       function Toggle(id) {
+        collapsealltext();
         var element = document.getElementById(id);
 
         if ( element.style.display == "none" )
           {
               divlist[i].style.display = "none";
           }
+          }
+        function collapsealltext() {
+          var divlist = document.getElementsByName("text");
+          for (i = 0; i < divlist.length; i++)
+          {
+              divlist[i].style.display = "none";
+          }          
       }
 
     ]]></script>
         <xsl:choose>
           <xsl:when test="count(./callback) != 0">
             <tr>
-              <td align="left"><xsl:attribute name="class"><xsl:value-of select="@res" /></xsl:attribute><xsl:value-of select="@script" /></td>
+              <td align="left">
+                   <xsl:attribute name="class"><xsl:value-of select="@res" /></xsl:attribute>
+                   <a href="#content">
+                           <xsl:attribute name="onclick">javascript:Toggle('<xsl:value-of select="@script"/>')</xsl:attribute>
+                           <xsl:attribute name="title">Click to see the script content</xsl:attribute>
+                           <xsl:value-of select="@script" />
+                   </a>
+                   &#160;
+                   <a href="#content">
+                           <xsl:attribute name="onclick">javascript:Toggle('<xsl:value-of select="@script"/>log')</xsl:attribute>
+                           <xsl:attribute name="title">Click to see the execution log</xsl:attribute>
+                           log
+                   </a>
+              </td>
               <td align="center"><xsl:attribute name="class"><xsl:value-of select="@res" /></xsl:attribute><xsl:value-of select="@res" /></td>
               <td align="right"><xsl:value-of select="format-number(@exec_time, '0.0')" /></td>
             </tr>
           </xsl:when>
           <xsl:otherwise>
             <tr>
-              <td align="left"><xsl:value-of select="@script" /></td>
+              <td align="left">
+                   <a href="#content">
+                           <xsl:attribute name="onclick">javascript:Toggle('<xsl:value-of select="@script"/>')</xsl:attribute>
+                           <xsl:attribute name="title">Click to see the script content</xsl:attribute>
+                           <xsl:value-of select="@script" />
+                   </a>
+                   &#160;
+                   <a href="#content">
+                           <xsl:attribute name="onclick">javascript:Toggle('<xsl:value-of select="@script"/>log')</xsl:attribute>
+                           <xsl:attribute name="title">Click to see the execution log</xsl:attribute>
+                           log
+                   </a>
+              </td>
               <td align="center"><xsl:attribute name="class"><xsl:value-of select="@res" /></xsl:attribute><xsl:value-of select="@res" /></td>
               <td align="right"><xsl:value-of select="format-number(@exec_time, '0.0')" /></td>
             </tr>
         </xsl:choose>
           <xsl:if test="count(./amend) != 0">
             <tr>
-              <td class="ko"><b>Amended</b></td>
+              <td class="ko"><b>Amended</b></td>       
               <td align="left" colspan="3"><xsl:value-of select="./amend" /></td>
             </tr>
           </xsl:if>
     </table>
     </div>
   </xsl:for-each>
-
+  
+  <xsl:for-each select="./module">
+    <xsl:for-each select="./type">
+      <xsl:for-each select="./test">
+         <div style="display:none" name="text"><xsl:attribute name="id"><xsl:value-of select="@script"/></xsl:attribute>
+           <PRE><xsl:value-of select="./content"/></PRE>
+         </div>
+         <div style="display:none" name="text"><xsl:attribute name="id"><xsl:value-of select="@script"/>log</xsl:attribute>
+           <PRE><xsl:value-of select="./out"/></PRE>
+         </div>
+      </xsl:for-each>
+    </xsl:for-each>
+  </xsl:for-each>
+  
 </xsl:template>
 
 <xsl:template name="display-percent">