Test Suite: Difference between revisions
Line 45: | Line 45: | ||
* BaseTest: | * BaseTest: | ||
** Creation of a test mapset for each test case in a specific test location located in the grass sources | |||
** Setting the environment variables to external data sources (for import and data comparison) and to the test location | |||
** Handling of region settings specific for single module tests. Using test specific mapsets the region settings of one test does not effect the region settings of another test. | |||
** Handles module test results codes and messages | ** Handles module test results codes and messages | ||
** Creates a HTML report from these | ** Creates a HTML report from these | ||
** Deletion of the generated test mapset to clean up the test location | |||
* RasterTest(BaseTest): | * RasterTest(BaseTest): | ||
** Raster data generator functions | ** Raster data generator functions | ||
** Raster data comparison functions | ** Raster data comparison functions (map by map, map by file, map by md5 value) | ||
* VectorTest(BaseTest): | * VectorTest(BaseTest): | ||
** | ** Vector data comparison functions | ||
* ... | * ... | ||
Line 60: | Line 64: | ||
* RMapcalcTest(RasterTest): | * RMapcalcTest(RasterTest): | ||
** Region setting | |||
** generates data | ** generates data | ||
** runs r.mapcalc | ** runs r.mapcalc | ||
Line 65: | Line 70: | ||
** output the results of the test as messages, to be prettified in HTML | ** output the results of the test as messages, to be prettified in HTML | ||
Example Python code for r.series: | |||
<source lang="python"> | |||
# Example test for raster module r.series | |||
# Import the grass test suite package | |||
import GrassTestSuite | |||
# Create the test class | |||
class RSeriesTest(GrassTestSuite.Raster.TestCase): | |||
# Add the dependencies in the constructor, this may be modules or libraries (gdal, proj, ...) | |||
def __init__(self): | |||
self.AddModuleDependency("r.mapcalc") | |||
# Setup the input data and the result using r.mapcalc | |||
# This method is specified in the framework and is called before any test method | |||
def SetUp(self): | |||
self.SetRegion(n=100, s=0, w=0, e=100, res=1) | |||
self.CreateData("r.mapcalc", expression="testmap1 = 1") | |||
self.CreateData("r.mapcalc", expression="testmap2 = 2") | |||
self.CreateData("r.mapcalc", expression="average = (testmap1 + testmap2)/2.0") | |||
self.CreateData("r.mapcalc", expression="sum = (testmap1 + testmap2)") | |||
self.CreateData("r.mapcalc", expression="max = testmap2") | |||
# The test functions. All tests should start with "test" and will called in alphabetic order | |||
# by the framework. The RunModuleTest and CompareRasterMaps are method specified by the framework | |||
# and must be used to run tests and compare results | |||
# Test the average method | |||
def testAverage(self): | |||
self.RunModuleTest("r.series", input="testmap1,testmap2", output="resmap", method="average") | |||
self.CompareRasterMaps(result="resmap", threshold=3, reference="average", message="Error in average method of r.series") | |||
# Test the sum method | |||
def testSum(self): | |||
self.RunModuleTest("r.series", input="testmap1,testmap2", output="resmap", method="sum") | |||
self.CompareRasterMaps(result="resmap", threshold=3, reference="sum", message="Error in sum method of r.series") | |||
# Test the max method | |||
def testMax(self): | |||
self.RunModuleTest("r.series", input="testmap1,testmap2", output="resmap", method="max") | |||
self.CompareRasterMaps(result="resmap", threshold=3, reference="max", message="Error in max method of r.series") | |||
</source> | |||
== Timeline and status == | == Timeline and status == |
Revision as of 23:01, 2 June 2011
GRASS Test Suite
We aim at creating a comprehensive test suite for GRASS modules and libraries.
Background
See what has been done so far by Sören Gebbert and others here: Development#QA and the good [| VKT test suite]
Keep an eye on GRASS 7 ideas collection
Main picture
We plan to run unittests and integration tests for both libraries and modules. The test suite will be run after compilation, with a command like:
$ make tests [ proj [ libs | modules | all ] ]
Options:
- proj: run the tests with a [list of] CRS, so that reprojection and map unit handling are tested.
- libs: run tests for libs only
- modules: run tests for modules only, assuming that libs are error-free
- all: run tests on libs first, then if they pass, test the modules. It's the opposite of regression tests.
Tests
Modules
Tests are targeted to cover all modules as well as library test modules.
The modules tests should as independent as possible from other GRASS modules.
Where independence is impossible, then try to run called modules first and check if they break. Therefor a recursive module dependency check must be implemented. The tests should specify from which other modules they depend. The test suite must check this and decide if the dependencies are fulfilled to run the test or generate an error message otherwise.
Tests are in each module's folder (written in Python), and in each library's folder (written in Python calling library test modules). Library test modules test library functions directly and are written in C. Have a look at the test directories in the gpde and gmath libraries of grass65 and grass7.
Framework to generate and compare grass data types: raster, vector, raster3d, general, db, icon, imagery, d.*?
wxGUI testing should be tested separately.
Automated tests on server generates HTML report. Test several platforms.
Test framework:
The test framework is something like:
- BaseTest:
- Creation of a test mapset for each test case in a specific test location located in the grass sources
- Setting the environment variables to external data sources (for import and data comparison) and to the test location
- Handling of region settings specific for single module tests. Using test specific mapsets the region settings of one test does not effect the region settings of another test.
- Handles module test results codes and messages
- Creates a HTML report from these
- Deletion of the generated test mapset to clean up the test location
- RasterTest(BaseTest):
- Raster data generator functions
- Raster data comparison functions (map by map, map by file, map by md5 value)
- VectorTest(BaseTest):
- Vector data comparison functions
- ...
Using these classes, each module will have its own test class, like:
- RMapcalcTest(RasterTest):
- Region setting
- generates data
- runs r.mapcalc
- compare results with the expected ones
- output the results of the test as messages, to be prettified in HTML
Example Python code for r.series:
# Example test for raster module r.series
# Import the grass test suite package
import GrassTestSuite
# Create the test class
class RSeriesTest(GrassTestSuite.Raster.TestCase):
# Add the dependencies in the constructor, this may be modules or libraries (gdal, proj, ...)
def __init__(self):
self.AddModuleDependency("r.mapcalc")
# Setup the input data and the result using r.mapcalc
# This method is specified in the framework and is called before any test method
def SetUp(self):
self.SetRegion(n=100, s=0, w=0, e=100, res=1)
self.CreateData("r.mapcalc", expression="testmap1 = 1")
self.CreateData("r.mapcalc", expression="testmap2 = 2")
self.CreateData("r.mapcalc", expression="average = (testmap1 + testmap2)/2.0")
self.CreateData("r.mapcalc", expression="sum = (testmap1 + testmap2)")
self.CreateData("r.mapcalc", expression="max = testmap2")
# The test functions. All tests should start with "test" and will called in alphabetic order
# by the framework. The RunModuleTest and CompareRasterMaps are method specified by the framework
# and must be used to run tests and compare results
# Test the average method
def testAverage(self):
self.RunModuleTest("r.series", input="testmap1,testmap2", output="resmap", method="average")
self.CompareRasterMaps(result="resmap", threshold=3, reference="average", message="Error in average method of r.series")
# Test the sum method
def testSum(self):
self.RunModuleTest("r.series", input="testmap1,testmap2", output="resmap", method="sum")
self.CompareRasterMaps(result="resmap", threshold=3, reference="sum", message="Error in sum method of r.series")
# Test the max method
def testMax(self):
self.RunModuleTest("r.series", input="testmap1,testmap2", output="resmap", method="max")
self.CompareRasterMaps(result="resmap", threshold=3, reference="max", message="Error in max method of r.series")
Timeline and status
TBD
Interested people
- Sören Gebbert
- Anne Ghisla
- Martin Landa
- Add your name here