[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