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

svn_grass at osgeo.org svn_grass at osgeo.org
Sat Jun 28 21:18:50 PDT 2014


Author: wenzeslaus
Date: 2014-06-28 21:18:50 -0700 (Sat, 28 Jun 2014)
New Revision: 61047

Added:
   sandbox/wenzeslaus/gunittest/testsuite/test_module_assertions.py
Modified:
   sandbox/wenzeslaus/gunittest/case.py
Log:
gunittest: first version of functions to run PyGRASS Module instances in controled way (after discussion with huhabla)

Modified: sandbox/wenzeslaus/gunittest/case.py
===================================================================
--- sandbox/wenzeslaus/gunittest/case.py	2014-06-29 01:03:50 UTC (rev 61046)
+++ sandbox/wenzeslaus/gunittest/case.py	2014-06-29 04:18:50 UTC (rev 61047)
@@ -13,10 +13,11 @@
 """
 
 import os
+import subprocess
 import unittest
 from unittest.util import safe_repr
 
-from .gmodules import call_module
+from .gmodules import call_module, CalledModuleError
 from .checkers import (check_text_ellipsis,
                        text_to_keyvalue, compare_keyvalue, diff_keyvalue,
                        file_md5, files_equal_md5)
@@ -284,6 +285,98 @@
         output = call_module(module, stdin, merge_stderr=False, **kwargs)
         return output
 
+    def runModule(self, module):
+        """Run PyGRASS module.
+
+        Runs the module and raises an expception if the module ends with
+        non-zero return code. Usually, this is the same as testing the
+        return code and raising exception but by using this method,
+        you give testing framework more control over the execution,
+        error handling and storing of output.
+
+        In terms of testing framework, this function causes a common error,
+        not a test failure.
+
+        :raises CalledModuleError: if the module failed
+        """
+        if module.run_:
+            raise ValueError('Do not run the module manually, set run_=False')
+        if not module.finish_:
+            raise ValueError('This function will always finish module run,'
+                             ' set finish_=None or finish_=True.')
+        # we expect most of the usages with stdout=PIPE
+        # TODO: in any case capture PIPE always?
+        if module.stdout_ is None:
+            module.stdout_ = subprocess.PIPE
+        elif module.stdout_ != subprocess.PIPE:
+            raise ValueError('stdout_ can be only PIPE or None')
+        if module.stderr_ is None:
+            module.stderr_ = subprocess.PIPE
+        elif module.stderr_ != subprocess.PIPE:
+            raise ValueError('stderr_ can be only PIPE or None')
+            # because we want to capture it
+        module.run()
+        if module.popen.returncode:
+            # TODO: message format, parameters
+            raise CalledModuleError(module.popen.returncode, module.name,
+                                    module.get_python(),
+                                    errors=module.outputs['stderr'].value)
+
+    # TODO: it asserts the rc but it does much more, so testModule?
+    # TODO: do we need special function for testing module failures or just add parameter returncode=0?
+    # TODO: consider allwing to call this method more than once
+    # the original idea was to run this method just once for test method
+    # but for "integration" tests  (script-like tests with more than one module)
+    # it would be better to be able to use this multiple times
+    def assertModule(self, module, msg=None):
+        """Run PyGRASS module in controled way and assert non-zero return code.
+
+        You should use this method to invoke module you are testing.
+        By using this method, you give testing framework more control over
+        the execution, error handling and storing of output.
+
+        It will not print module stdout and stderr, instead it will always
+        store them for furthere examination.
+        ? If you don't specify stdout_=PIPE, it will merge stderr into
+        stdout. ?
+
+        This function is not suitable for testing error states of the module.
+        If you want to test behavior which involves non-zero return code
+        and examine stderr in test, use PyGRASS directly.
+
+        Runs the module and causes test failure if module ends with
+        non-zero return code.
+        """
+        # TODO: merge stderr to stdout? if caller gives PIPE, for sure not
+        if module.run_:
+            raise ValueError('Do not run the module manually, set run_=False')
+        if not module.finish_:
+            raise ValueError('This function will always finish module run,'
+                             ' set finish_=None or finish_=True.')
+        if module.stdout_ is None:
+            module.stdout_ = subprocess.PIPE
+        elif module.stdout_ != subprocess.PIPE:
+            raise ValueError('stdout_ can be only PIPE or None')
+            # because we want to capture it
+        if module.stderr_ is None:
+            module.stderr_ = subprocess.PIPE
+        elif module.stderr_ != subprocess.PIPE:
+            raise ValueError('stderr_ can be only PIPE or None')
+            # because we want to capture it
+
+        module.run()
+        if module.popen.returncode:
+            # TODO: message format
+            # TODO: stderr?
+            stdmsg = 'Running <%s> ended with non-zero return code' % module.get_python()
+            self.fail(self._formatMessage(msg, stdmsg))
+
+        # log these to final report
+        # TODO: always or only if the calling test method failed?
+        module.outputs['stdout'].value
+        module.outputs['stderr'].value
+
+
 # the following lines are for code coverage
 def endcov(cov):
     cov.stop()

Added: sandbox/wenzeslaus/gunittest/testsuite/test_module_assertions.py
===================================================================
--- sandbox/wenzeslaus/gunittest/testsuite/test_module_assertions.py	                        (rev 0)
+++ sandbox/wenzeslaus/gunittest/testsuite/test_module_assertions.py	2014-06-29 04:18:50 UTC (rev 61047)
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+
+import sys
+import os
+import copy
+import subprocess
+
+from grass.pygrass.modules import Module
+
+# import gunittest as a package so that relative imports there works
+sys.path.insert(0, os.path.split(os.path.split((os.path.dirname(__file__)))[0])[0])
+from gunittest.case import GrassTestCase
+from gunittest.gmodules import CalledModuleError
+
+
+class TestModuleAssertions(GrassTestCase):
+    # pylint: disable=R0904
+
+    def test_runModule(self):
+        rinfo = Module('r.info', map='elevation', flags='g',
+                       stdout_=subprocess.PIPE, run_=False)
+        rinfo_wrong = copy.deepcopy(rinfo)
+        rinfo_wrong.inputs['map'].value = 'does_not_exists'
+
+        self.runModule(rinfo)
+        self.assertTrue(rinfo.outputs['stdout'])
+        self.assertRaises(CalledModuleError, self.runModule, rinfo_wrong)
+
+    def test_assertModule(self):
+        rinfo = Module('r.info', map='elevation', flags='g',
+                       stdout_=subprocess.PIPE, run_=False)
+        rinfo_wrong = copy.deepcopy(rinfo)
+        rinfo_wrong.inputs['map'].value = 'does_not_exists'
+
+        self.assertModule(rinfo)
+        self.assertTrue(rinfo.outputs['stdout'])
+        self.assertRaises(self.failureException, self.assertModule, rinfo_wrong)



More information about the grass-commit mailing list