[GRASS-SVN] r64662 - in grass/trunk/lib/python/gunittest: . testsuite

svn_grass at osgeo.org svn_grass at osgeo.org
Tue Feb 17 08:42:58 PST 2015


Author: wenzeslaus
Date: 2015-02-17 08:42:58 -0800 (Tue, 17 Feb 2015)
New Revision: 64662

Modified:
   grass/trunk/lib/python/gunittest/case.py
   grass/trunk/lib/python/gunittest/main.py
   grass/trunk/lib/python/gunittest/testsuite/test_assertions.py
Log:
gunittest: improvements to make it work better on MS Windows

 * use short, although unreadable, map and file names to overcome problems with 260 character limit (MAX_PATH) of Win32 API (GPATH_MAX is 4096)
 * override assertMultiLineEqual() to replace CRLF by LF, so that test authors can just use unix line endings
 * register assertMultiLineEqual() for strings so that the CRLF replacement happens for assertEqual() as expected
 * explicitly check for existence of a provided Location
 

Modified: grass/trunk/lib/python/gunittest/case.py
===================================================================
--- grass/trunk/lib/python/gunittest/case.py	2015-02-17 14:37:57 UTC (rev 64661)
+++ grass/trunk/lib/python/gunittest/case.py	2015-02-17 16:42:58 UTC (rev 64662)
@@ -12,7 +12,8 @@
 import os
 import subprocess
 import StringIO
-
+import hashlib
+import uuid
 import unittest
 
 from grass.pygrass.modules import Module
@@ -39,11 +40,16 @@
     maxDiff = None  # we can afford long diffs
     _temp_region = None  # to control the temporary region
     html_reports = False  # output additional HTML files with failure details
+    readable_names = False  # prefer shorter but unreadable map and file names
 
     def __init__(self, methodName):
         super(TestCase, self).__init__(methodName)
         self.grass_modules = []
         self.supplementary_files = []
+        # Python unittest doc is saying that strings use assertMultiLineEqual
+        # but only unicode type is registered
+        # TODO: report this as a bug? is this in Python 3.x?
+        self.addTypeEqualityFunc(str, 'assertMultiLineEqual')
 
     def _formatMessage(self, msg, standardMsg):
         """Honor the longMessage attribute when generating failure messages.
@@ -129,6 +135,28 @@
         # but we have zero chance of infuencing another test class
         # since we use class-specific name for temporary region
 
+    def assertMultiLineEqual(self, first, second, msg=None):
+        r"""Test that the multiline string first is equal to the string second.
+
+        When not equal a diff of the two strings highlighting the differences
+        will be included in the error message. This method is used by default
+        when comparing strings with assertEqual().
+
+        This method replaces ``\r\n`` by ``\n`` in both parameters. This is
+        different from the same method implemented in Python ``unittest``
+        package which preserves the original line endings. This removes the
+        burden of getting the line endings right on each platfrom. You can
+        just use ``\n`` everywhere. However, note that ``\r`` is not supported.
+
+        .. warning::
+            If you need to test the actual line endings, use the standard
+            string comparison and functions such as ``find()``.
+        """
+        return super(TestCase, self).assertMultiLineEqual(
+            first=first.replace('\r\n', '\n'),
+            second=second.replace('\r\n', '\n'),
+            msg=None)
+
     def assertLooksLike(self, actual, reference, msg=None):
         """Test that ``actual`` text is the same as ``referece`` with ellipses.
 
@@ -548,6 +576,26 @@
                                                                         reference)
             self.fail(self._formatMessage(msg, stdmsg))
 
+    def _get_unique_name(self, name):
+        """Create standardized map or file name which is unique
+
+        If ``readable_names`` attribute is `True`, it uses the *name* string
+        to create the unique name. Otherwise, it creates a unique name.
+        Even if you expect ``readable_names`` to be `True`, provide *name*
+        which is unique
+
+        The *name* parameter should be valid raster name, vector name and file
+        name and should be always provided.
+        """
+        # TODO: possible improvement is to require some descriptive name
+        # and ensure uniqueness by add UUID 
+        if self.readable_names:
+            return 'tmp_' + self.id().replace('.', '_') + '_' + name
+        else:
+            # UUID might be overkill (and expensive) but it's safe and simple
+            # alternative is to create hash from the readable name
+            return 'tmp_' + str(uuid.uuid4()).replace('-', '')
+
     def _compute_difference_raster(self, first, second, name_part):
         """Compute difference of two rasters (first - second)
 
@@ -560,8 +608,8 @@
 
         :returns: name of a new raster
         """
-        diff = ('tmp_' + self.id() + '_compute_difference_raster_'
-                + name_part + '_' + first + '_minus_' + second)
+        diff = self._get_unique_name('compute_difference_raster_' + name_part
+                                     + '_' + first + '_minus_' + second)
         call_module('r.mapcalc',
                     stdin='"{d}" = "{f}" - "{s}"'.format(d=diff,
                                                          f=first,
@@ -582,8 +630,9 @@
 
         :returns: name of a new raster
         """
-        diff = ('tmp_' + self.id() + '_compute_difference_raster_'
-                + name_part + '_' + first + '_minus_' + second)
+        diff = self._get_unique_name('compute_difference_raster_' + name_part
+                                     + '_' + first + '_minus_' + second)
+
         call_module('r3.mapcalc',
                     stdin='"{d}" = "{f}" - "{s}"'.format(d=diff,
                                                          f=first,
@@ -595,9 +644,9 @@
 
         :returns: name of a new vector
         """
-        diff = ('tmp_' + self.id() + '_compute_difference_vector_'
-                + name_part + '_' + ainput + '_' + alayer
-                + '_minus_' + binput + '_' + blayer)
+        diff = self._get_unique_name('compute_difference_vector_' + name_part
+                                     + '_' + ainput + '_' + alayer + '_minus_'
+                                     + binput + '_' + blayer)
         call_module('v.overlay', operator='xor', ainput=ainput, binput=binput,
                     alayer=alayer, blayer=blayer,
                     output=diff, atype='area', btype='area', olayer='')
@@ -612,15 +661,13 @@
 
         :returns: name of a new vector
         """
-        import hashlib
         # hash is the easiest way how to get a valied vector name
         # TODO: introduce some function which will make file valid
         hasher = hashlib.md5()
         hasher.update(filename)
         namehash = hasher.hexdigest()
-        vector = ('tmp_' + self.id().replace('.', '_')
-                  + '_import_ascii_vector_'
-                  + name_part + '_' + namehash)
+        vector = self._get_unique_name('import_ascii_vector_' + name_part
+                                       + '_' + namehash)
         call_module('v.in.ascii', input=filename,
                     output=vector, format='standard')
         return vector
@@ -632,10 +679,11 @@
         :returns: name of a new vector
         """
         # TODO: perhaps we can afford just simple file name
-        filename = ('tmp_' + self.id() + '_export_ascii_vector_'
-                    + name_part + '_' + vector)
+        filename = self._get_unique_name('export_ascii_vector_'
+                                         + name_part + '_' + vector)
         call_module('v.out.ascii', input=vector,
-                    output=filename, format='standard', layer='-1', dp=digits)
+                    output=filename, format='standard', layer='-1',
+                    precision=digits)
         return filename
 
     def assertRastersNoDifference(self, actual, reference,

Modified: grass/trunk/lib/python/gunittest/main.py
===================================================================
--- grass/trunk/lib/python/gunittest/main.py	2015-02-17 14:37:57 UTC (rev 64661)
+++ grass/trunk/lib/python/gunittest/main.py	2015-02-17 16:42:58 UTC (rev 64662)
@@ -151,6 +151,11 @@
         sys.stderr.write("GISDBASE (grassdata directory) <%s>"
                          " does not exist\n" % gisdbase)
         sys.exit(1)
+    if not os.path.exists(os.path.join(gisdbase, location)):
+        sys.stderr.write("GRASS Location <{loc}>"
+                         " does not exist in GRASS Database <{db}>\n".format(
+                             location, gisdbase))
+        sys.exit(1)
     results_dir = args.output
     silent_rmtree(results_dir)  # TODO: too brute force?
 

Modified: grass/trunk/lib/python/gunittest/testsuite/test_assertions.py
===================================================================
--- grass/trunk/lib/python/gunittest/testsuite/test_assertions.py	2015-02-17 14:37:57 UTC (rev 64661)
+++ grass/trunk/lib/python/gunittest/testsuite/test_assertions.py	2015-02-17 16:42:58 UTC (rev 64662)
@@ -44,7 +44,36 @@
                           "abc = 689.159589",
                           "abc = 689....")
 
+    def do_all_combidnations(self, first, second):
+        self.assertMultiLineEqual(first, first)
+        self.assertMultiLineEqual(first, second)
+        self.assertMultiLineEqual(second, first)
+        self.assertMultiLineEqual(second, second)
 
+    def test_assertMultiLineEqual(self):
+        unix_end = "aaa\nbbb\n"
+        mswindows_end = "aaa\r\nbbb\r\n"
+        self.do_all_combidnations(unix_end, mswindows_end)
+
+    def test_assertMultiLineEqual_raises(self):
+        """Test mixed line endings"""
+        self.assertRaises(self.failureException,
+                          self.assertMultiLineEqual,
+                          "aaa\n\rbbb\r",
+                          "aaa\nbbb\n")
+
+    def test_assertEqual(self):
+        """Test for strings (uses overwritten assertMultiLineEqual())"""
+        unix_end = "aaa\nbbb\n"
+        mswindows_end = "aaa\r\nbbb\r\n"
+        self.do_all_combidnations(unix_end, mswindows_end)
+
+        self.assertRaises(self.failureException,
+                          self.assertEqual,
+                          "aaa\n\rbbb\r",
+                          "aaa\nbbb\n")
+
+
 R_UNIVAR_ELEVATION_SUBSET = """n=2025000
 null_cells=0
 min=55.5787925720215



More information about the grass-commit mailing list