[GRASS-SVN] r61145 - in sandbox/wenzeslaus/gunittest: . testsuite

svn_grass at osgeo.org svn_grass at osgeo.org
Thu Jul 3 18:26:39 PDT 2014


Author: wenzeslaus
Date: 2014-07-03 18:26:39 -0700 (Thu, 03 Jul 2014)
New Revision: 61145

Added:
   sandbox/wenzeslaus/gunittest/reporters.py
Modified:
   sandbox/wenzeslaus/gunittest/invoker.py
   sandbox/wenzeslaus/gunittest/main.py
   sandbox/wenzeslaus/gunittest/testsuite/test_checkers.py
Log:
gunittest: move report generation to a separate class and file, add separated text and html stdoutand stderr

Modified: sandbox/wenzeslaus/gunittest/invoker.py
===================================================================
--- sandbox/wenzeslaus/gunittest/invoker.py	2014-07-03 23:10:12 UTC (rev 61144)
+++ sandbox/wenzeslaus/gunittest/invoker.py	2014-07-04 01:26:39 UTC (rev 61145)
@@ -11,6 +11,7 @@
 TestProgram.USAGE = USAGE_AS_MAIN
 
 from loader import GrassTestLoader, discover_modules
+from reporters import GrassTestFilesReporter
 import utils
 
 import grass.script.setup as gsetup
@@ -38,6 +39,8 @@
         self.clean_outputs = clean_outputs
         self.clean_before = clean_before
         self.testsuite_dir = testsuite_dir
+        # reporter is created for each call of run_in_location()
+        self.reporter = None
 
     def _create_mapset(self, gisdbase, location, module):
         """Create mapset according to informations in module.
@@ -64,12 +67,43 @@
                     os.path.join(mapset_dir))
         return mapset, mapset_dir
 
+    def _run_test_module(self, module, results_dir, gisdbase, location):
+        cwd = os.path.join(results_dir, module.tested_dir, module.name)
+        utils.ensure_dir(os.path.abspath(cwd))
+        # TODO: put this to constructor and copy here again
+        env = os.environ.copy()
+        mapset, mapset_dir = self._create_mapset(gisdbase, location, module)
+        gisrc = gsetup.write_gisrc(gisdbase, location, mapset)
+        env['GISRC'] = gisrc
+
+        stdout_path = os.path.join(cwd, 'stdout.txt')
+        stderr_path = os.path.join(cwd, 'stderr.txt')
+        stdout = open(stdout_path, 'w')
+        stderr = open(stderr_path, 'w')
+
+        # TODO: we might clean the directory here before test if non-empty
+        # TODO: use some grass function to run?
+        p = subprocess.Popen([sys.executable, module.abs_file_path],
+                             cwd=cwd, env=env,
+                             stdout=stdout, stderr=stderr)
+        returncode = p.wait()
+        stdout.close()
+        stderr.close()
+        self.reporter.add_test_results(module=module, cwd=cwd,
+                                       returncode=returncode,
+                                       stdout=stdout_path, stderr=stderr_path)
+        # TODO: add some try-except or with for better error handling
+        os.remove(gisrc)
+        # TODO: only if clean up
+        if self.clean_mapsets:
+            shutil.rmtree(mapset_dir)
+
     def run_in_location(self, gisdbase, location, location_shortcut,
                         results_dir):
         if os.path.abspath(results_dir) == os.path.abspath(self.start_dir):
             raise RuntimeError("Results root directory should not be the same"
                                " as discovery start directory")
-        main_start_time = datetime.datetime.now()
+        self.reporter = GrassTestFilesReporter(results_dir=results_dir)
 
         # TODO: move constants out of loader class or even module
         modules = discover_modules(start_dir=self.start_dir,
@@ -80,62 +114,9 @@
                                    all_locations_value=GrassTestLoader.all_tests_value,
                                    universal_location_value=GrassTestLoader.universal_tests_value,
                                    import_modules=False)
-        # TODO: no directory cleaning (self.clean_before)? now cleaned by caller
-        utils.ensure_dir(os.path.abspath(results_dir))
-        main_index = open(os.path.join(results_dir, 'index.html'), 'w')
-        main_index.write('<html><body>'
-                         '<h1>Test results</h1>'
-                         '{time:%Y-%m-%d %H:%M:%S}'
-                         '<ul>'.format(time=main_start_time))
+
         for module in modules:
-            cwd = os.path.join(results_dir, module.tested_dir, module.name)
-            utils.ensure_dir(os.path.abspath(cwd))
-            # TODO: put this to constructor and copy here again
-            env = os.environ.copy()
-            mapset, mapset_dir = self._create_mapset(gisdbase, location, module)
-            gisrc = gsetup.write_gisrc(gisdbase, location, mapset)
-            env['GISRC'] = gisrc
+            self._run_test_module(module=module, results_dir=results_dir,
+                                  gisdbase=gisdbase, location=location)
 
-            # TODO: we don't do any HTML escaping, use txt file
-            stdout = open(os.path.join(cwd, 'stdout.html'), 'w')
-            stderr = open(os.path.join(cwd, 'stderr.html'), 'w')
-            stdout.write('<html><body><h1>%s</h1><pre>' % (module.name + ' stdout'))
-            stderr.write('<html><body><h1>%s</h1><pre>' % (module.name + ' stderr'))
-            stdout.flush()  # we need to flush to write our changes before stdout
-            stderr.flush()
-
-            # TODO: we might clean the directory here before test if non-empty
-            # TODO: use some grass function to run?
-            p = subprocess.Popen([sys.executable, module.abs_file_path],
-                                 cwd=cwd, env=env,
-                                 stdout=stdout, stderr=stderr)
-            returncode = p.wait()
-            stdout.flush()
-            stderr.flush()
-            stdout.write('</pre></body></html>')
-            stderr.write('</pre></body></html>')
-            file_index_path = os.path.join(cwd, 'index.html')        
-            if returncode:
-                sys.stderr.write('{d}/{m} failed (see {f})\n'.format(d=module.tested_dir,
-                                                                     m=module.name,
-                                                                     f=file_index_path))
-            main_index.write('<li><a href="{d}/{m}/index.html">{d}/{m}</a>'.format(d=module.tested_dir, m=module.name))
-            file_index = open(file_index_path, 'w')
-            file_index.write('<html><body>'
-                             '<ul>'
-                             '<li><a href="stdout.html">standard output (stdout)</a>'
-                             '<li><a href="stderr.html">standard error output (stderr)</a>'
-                             '<li><a href="testcodecoverage/index.html">code coverage</a>'
-                             '</ul>'
-                             '</body></html>')
-            stdout.close()
-            stderr.close()
-            file_index.close()
-            # TODO: add some try-except or with for better error handling
-            os.remove(gisrc)
-            # TODO: only if clean up
-            if self.clean_mapsets:
-                shutil.rmtree(mapset_dir)
-        main_index.write('</ul>'
-                         '</body></html>')
-        main_index.close()
+        self.reporter.finish()

Modified: sandbox/wenzeslaus/gunittest/main.py
===================================================================
--- sandbox/wenzeslaus/gunittest/main.py	2014-07-03 23:10:12 UTC (rev 61144)
+++ sandbox/wenzeslaus/gunittest/main.py	2014-07-04 01:26:39 UTC (rev 61145)
@@ -104,7 +104,7 @@
     if not os.path.exists(gisdbase):
         sys.stderr.write("GISDBASE <%s> does not exist\n" % gisdbase)
         sys.exit(1)
-    results_dir = 'testresults'
+    results_dir = 'testreport'
     utils.silent_rmtree(results_dir)  # TODO: too brute force?
 
     invoker = GrassTestFilesInvoker(start_dir='.')

Added: sandbox/wenzeslaus/gunittest/reporters.py
===================================================================
--- sandbox/wenzeslaus/gunittest/reporters.py	                        (rev 0)
+++ sandbox/wenzeslaus/gunittest/reporters.py	2014-07-04 01:26:39 UTC (rev 61145)
@@ -0,0 +1,89 @@
+# -*- coding: utf-8 -*-
+
+import os
+import sys
+import datetime
+import xml.sax.saxutils as saxutils
+
+import utils
+
+
+def html_escape(text):
+    """Escape ``'&'``, ``'<'``, and ``'>'`` in a string of data."""
+    return saxutils.escape(text)
+
+
+def html_unescape(text):
+    """Unescape ``'&'``, ``'<'``, and ``'>'`` in a string of data."""
+    return saxutils.unescape(text)
+
+
+def color_error_line(line):
+    if line.startswith('ERROR: '):
+        # TODO: use CSS class
+        # ignoring the issue with \n at the end, HTML don't mind
+        line = '<span style="color: red">' + line + "</span>"
+    if line.startswith('WARNING: '):
+        # TODO: use CSS class
+        # ignoring the issue with \n at the end, HTML don't mind
+        line = '<span style="color: blue">' + line + "</span>"
+    return line
+
+
+class GrassTestFilesReporter(object):
+
+    def __init__(self, results_dir):
+        # TODO: no directory cleaning (self.clean_before)? now cleaned by caller
+        utils.ensure_dir(os.path.abspath(results_dir))
+
+        # having all variables public although not really part of API
+        self.main_index = open(os.path.join(results_dir, 'index.html'), 'w')
+        # this might be moved to some report start method
+        self.main_start_time = datetime.datetime.now()
+        self.main_index.write('<html><body>'
+                              '<h1>Test results</h1>'
+                              '{time:%Y-%m-%d %H:%M:%S}'
+                              '<ul>'.format(time=self.main_start_time))
+
+    def finish(self):
+        self.main_index.write('</ul>'
+                              '</body></html>')
+        self.main_index.close()
+
+    def add_test_results(self, module, cwd, returncode, stdout, stderr):
+        self.main_index.write(
+            '<li><a href="{d}/{m}/index.html">{d}/{m}</a>'.format(
+                d=module.tested_dir, m=module.name))
+        # TODO: we don't do any HTML escaping, use txt file
+        stdout_html = open(os.path.join(cwd, 'stdout.html'), 'w')
+        stderr_html = open(os.path.join(cwd, 'stderr.html'), 'w')
+        stdout_html.write('<html><body><h1>%s</h1><pre>' % (module.name + ' stdout'))
+        stderr_html.write('<html><body><h1>%s</h1><pre>' % (module.name + ' stderr'))
+
+        with open(stdout) as text:
+            for line in text:
+                stdout_html.write(color_error_line(html_escape(line)))
+        with open(stderr) as text:
+            for line in text:
+                stderr_html.write(color_error_line(html_escape(line)))
+
+        stdout_html.write('</pre></body></html>')
+        stderr_html.write('</pre></body></html>')
+        stdout_html.close()
+        stderr_html.close()
+
+        file_index_path = os.path.join(cwd, 'index.html')
+        file_index = open(file_index_path, 'w')
+        file_index.write('<html><body>'
+                         '<ul>'
+                         '<li><a href="stdout.html">standard output (stdout)</a>'
+                         '<li><a href="stderr.html">standard error output (stderr)</a>'
+                         '<li><a href="testcodecoverage/index.html">code coverage</a>'
+                         '</ul>'
+                         '</body></html>')
+        file_index.close()
+
+        if returncode:
+            sys.stderr.write('{d}/{m} failed (see {f})\n'.format(d=module.tested_dir,
+                                                                 m=module.name,
+                                                                 f=file_index_path))


Property changes on: sandbox/wenzeslaus/gunittest/reporters.py
___________________________________________________________________
Added: svn:mime-type
   + text/x-python
Added: svn:eol-style
   + native

Modified: sandbox/wenzeslaus/gunittest/testsuite/test_checkers.py
===================================================================
--- sandbox/wenzeslaus/gunittest/testsuite/test_checkers.py	2014-07-03 23:10:12 UTC (rev 61144)
+++ sandbox/wenzeslaus/gunittest/testsuite/test_checkers.py	2014-07-04 01:26:39 UTC (rev 61145)
@@ -315,4 +315,4 @@
 
 if __name__ == '__main__':
     from gunittest.main import test
-    test()
\ No newline at end of file
+    test()



More information about the grass-commit mailing list