[GRASS-SVN] r61562 - grass/trunk/lib/python/docs/src
svn_grass at osgeo.org
svn_grass at osgeo.org
Thu Aug 7 15:04:18 PDT 2014
Author: wenzeslaus
Date: 2014-08-07 15:04:18 -0700 (Thu, 07 Aug 2014)
New Revision: 61562
Modified:
grass/trunk/lib/python/docs/src/gunittest_testing.rst
Log:
gunittest: more for the general documentation part
Modified: grass/trunk/lib/python/docs/src/gunittest_testing.rst
===================================================================
--- grass/trunk/lib/python/docs/src/gunittest_testing.rst 2014-08-07 18:38:45 UTC (rev 61561)
+++ grass/trunk/lib/python/docs/src/gunittest_testing.rst 2014-08-07 22:04:18 UTC (rev 61562)
@@ -196,27 +196,39 @@
region as well as remove all created maps and files.
test report
- A *test report* is a document or set of documents.
+ A *test report* is a document or set of documents with results of
+ all executed tests together with additional information such as output
+ of test.
Note that also *test result* is used also used in similar context
because the class responsible for representing or creating the report
in Python `unittest`_ package is called ``TestResult``.
+test failure and test error
+ A *test failure* occurs when a assert fails, e.g. value of
+ a parameter given to ``assertTrue()`` function is ``False``.
+ A *test error* occurs when something what is not tested fails,
+ i.e. when exception is risen for example preparation code or
+ a test method itself.
+
Testing with gunittest package in general
-----------------------------------------
The tests should be in files in a ``testsuite`` directory which is a subdirectory
-of the directory with tested files (module, package, library). Each testing file
-(test file) can have can have several testing classes (test cases).
-All test files names should have pattern ``test*.py``.
+of the directory with tested files (module, package, library). Each test file
+(testing file) can have can have several test cases (testing classes).
+All test file names should have pattern ``test*.py`` or ``*.py``
+if another naming convention seems more appropriate.
GRASS GIS `gunittest` package and testing framework is similar to the standard
Python ``unittest`` package, so the ways to build tests are very similar.
+Test methods are in a test test case class and each test method tests one
+think using one or more assert methods.
::
- from grass.guinttest import TestCase
+ from grass.guinttest import TestCase, test
class TestPython(TestCase):
@@ -227,45 +239,111 @@
if __name__ == '__main__':
- from grass.guinttest import test
test()
-Each test file should be able to run by itself and accept certain set of command
-line parameters. This is ensured using `gunittest.test()`.
+Each test file should be able to run by itself accept certain set of command
+line parameters (currently none). This is done using
+``if __name__ == '__main__'`` and ``gunittest.test()`` function.
-To run (invoke) all tests in the source tree, you have to be in the source code
-directory, inside GRASS session and use command similar to this one::
+To run a test file, start GRASS session in the location and mapset suitable for
+testing (typically, NC sample location) and go to the test file's directory
+(it will be usually some ``testsuite`` directory in the source code)
+and run it as a Python script::
+ python test_something.py
+
+When running individual test files, it is advisable to be in a separate
+mapset, so for example when using NC sample location, you should use
+a new mapset of arbitrary name but not one of the predefined mapsets).
+
+To run all tests in the source tree, you have to be in the source code
+directory where you want to find tests, also you need to be inside
+a GRASS session and use command similar to this one::
+
python -m grass.gunittest.main --location nc_spm_grass7 --location-type nc
All test files in all ``testsuite`` directories will be executed and
a report will be created in a newly created ``testreport`` directory.
Open the file ``testreport/index.html`` to browse though the results.
-Note that you need to be in GRASS session to run the tests in this way.
+Note that again you need to be in GRASS session to run the tests in this way.
The ``--location-type`` parameter serves to filter tests according to data
they can run successfully with. It is ignored for tests which does not have
this specified.
-Each running test file gets its own mapset and current working directory
-but all run are in one location.
+In this case each running test file gets its own mapset and
+current working directory but all run are in one location.
.. warning::
- The current location is ignored but you should run not invoke tests
- in the location which is precious to you for the case that something fails.
+ The current location is ignored but you should not run tests
+ in the location which is precious to you for the case that something fails
+ and current location is used for tests.
-To run individual tests file you should be in GRASS session in GRASS NC sample
-location in a mapset of arbitrary name (except for the predefined mapsets).
+When your are writing tests you can rely on having maps which are present
+in the NC sample location, or you can generate random maps. You can also
+import your data which you store inside ``data`` directory inside the
+given ``testsuite`` directory (for maps, ASCII formats are usually used).
+If you can create tests independent on location projection and location data
+it is much better then relying on given data but it is not at all required
+and all approaches are encouraged.
-Your tests can rely on maps which are present in the GRASS NC sample location.
-But if you can provide tests which are independent on location it is better.
+Whenever possible it is advantageous to use available assert methods.
+GRASS-specific assert methods are in :class:`gunittest.case.TestCase` class.
+For general assert methods refer to Python `unittest`_ package documentation.
+Both are used in the same way; they are methods of a given test case class.
+In cases (which should be rare) when no assert methods fits the purpose,
+you can use your own checking finalized with a call of ``assertTrue()``
+or ``assertFalse()`` method with the ``msg`` parameter parameter set
+to an informative message.
-Read the documentation of Python ``unittest`` package for a list of assert
-methods which you can use to test your results. For test of more complex
-GRASS-specific results refer to :class:`gunittest.case.TestCase` class
-documentation.
+When you are using multiple assert methods in one test method, you must
+carefully consider what assert methods are testing and in which order
+you should put them. Consider the following example::
+ # incorrect order
+ def test_map_in_list_wrong(self):
+ maps = get_list_of_maps()
+ self.assertIn('elevation', maps)
+ # there is no point in testing that
+ # if list (or string) was empty or None execution of test ended
+ # at the line with assertIn
+ self.assertTrue(maps)
+ # correct order
+ def test_map_in_list_correct(self):
+ maps = get_list_of_maps()
+ # see if list (or string) is not empty (or None)
+ self.assertTrue(maps)
+ # and then see if the list fulfills more advanced conditions
+ self.assertIn('elevation', maps)
+
+If you are not sure when you would use multiple asserts consider the case
+when using only ``assertIn()`` function::
+
+ def test_map_in_list_short(self):
+ maps = get_list_of_maps()
+ self.assertIn('elevation', maps)
+
+If the list (or string) is empty, the test fails and the message says
+something about ``elevation''`` not being in the ``maps`` but
+it might be much more useful if it would tell us that the list ``maps``
+does not contain any items. In case of ``maps`` being ``None``, the situation
+is more complicated since we using ``assertIn`` with ``None`` will
+cause test error (not only failure). We must consider what is
+expected behavior of ``get_list_of_maps()`` function and what
+we are actually testing. For example, if we would be testing function
+interface, we probably should test separately different possibilities
+using ``assertIsNotNone()`` and then ``assertTrue()`` and then anything else.
+
+Another reason for using multiple assert methods is that we may want to
+test different qualities of a result. Following the previous example,
+we can test that a list contains some map and does not contain some other.
+If you are testing a lot of things and they don't have any clear order
+or dependencies, it might be more advantageous to split
+testing into several testing methods and do the preparation (creating a list
+in our example) in ``setUpClass()`` or ``setUp()`` method.
+
+
.. _test-module:
Tests of GRASS modules
More information about the grass-commit
mailing list