<div dir="ltr">Hi Nikos,<div class="gmail_extra"><br><div class="gmail_quote">2016-10-06 1:39 GMT+02:00 Nikos Alexandris <span dir="ltr"><<a href="mailto:nik@nikosalexandris.net" target="_blank">nik@nikosalexandris.net</a>></span>:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex">Apologies for removing all but Soeren's last post.<br>
<br>
* Sören Gebbert:<div><div class="gmail-h5"><br>
<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex">
I would like to put the GRASS test framework into perspective, since i<br>
think that its capabilities are not well known.<br>
The gunittest framework is not about unit tests. It was designed to test<br>
all aspects of the GRASS development. This framework allows you to:<br>
<br>
* Implement unit tests for the Python libraries, their mthods and classes<br>
* Implement and run doctests in the source code of the Python libraries<br>
* Run integration tests for all modules, checking correct output for almost<br>
all datatypes in GRASS (raster, vector, 3D raster, space-time datasets,<br>
categories, color definitions, stdout, ...). Module tests are IMHO<br>
integration tests, since module make use of different library methods and<br>
classes and combine them.<br>
* Run C-library tests as unit and integration tests. C-library unit and<br>
integration tests can either be implemented in C or via ctypes in Python<br>
* Run tests on library level, module level or for all libraries and modules<br>
in the whole GRASS source tree using a single command, ...<br>
* Perform regression tests in dedicated test locations, autimatically<br>
triggered by a cronjob or a commit<br>
* The framework allows you to run all library unit tests, before module<br>
integration tests are performed<br>
* It creates temporary mapsest to run without problems in production<br>
locations<br>
* It logs all tests in detail and generates easy to inspect HTML output at<br>
runtime, so you can check the progress of the tests and its gradually<br>
available results<br>
* It allows on the fly mapset creation and deletion<br>
* It supports temporary region environments<br>
* It support user defined test data for input generation and output<br>
validation<br>
<br>
These capabilities allow a wide range of tests to be created, covering most<br>
aspects of the GRASS development, with the exception of the GUI.<br>
So please no excuses that the gunittest framework is not capable of<br>
implementing a test that is required to assure module correctness.<br>
</blockquote>
<br></div></div>
Soeren, could you name some good examples (not to the<br>
manual/s), some real modules with integrated tests? I am much in need<br>
for good code.<br></blockquote><div><br></div><div>Some examples:</div><div>*******************</div><div><br></div><div>C-Code</div><div>----------</div><div><br></div><div>Unittest for the linear equation solver in gmath library:</div><div><br></div><div><a href="https://trac.osgeo.org/grass/browser/grass/trunk/lib/gmath/test/test_solvers.c">https://trac.osgeo.org/grass/browser/grass/trunk/lib/gmath/test/test_solvers.c</a><br></div><div><br></div><div>Integration test of the groundwater flow module, that make use of many gmath functions. The result of the simulation is tested against reference values that are based on literature, see the header of the file:</div><div><br></div><div><a href="https://trac.osgeo.org/grass/browser/grass/trunk/raster/r.gwflow/testsuite/validation_7x7_grid.py">https://trac.osgeo.org/grass/browser/grass/trunk/raster/r.gwflow/testsuite/validation_7x7_grid.py</a><br></div><div> </div><div>Python-Code</div><div>-----------------</div><div><br></div><div>The PyGRASS unittests are a great example and inspiration for testing:</div><div><br></div><div><a href="https://trac.osgeo.org/grass/browser/grass/trunk/lib/python/pygrass/raster/testsuite">https://trac.osgeo.org/grass/browser/grass/trunk/lib/python/pygrass/raster/testsuite</a> </div><div><a href="https://trac.osgeo.org/grass/browser/grass/trunk/lib/python/pygrass/vector/testsuite">https://trac.osgeo.org/grass/browser/grass/trunk/lib/python/pygrass/vector/testsuite</a><br></div><div><br></div><div>Integration tests:</div><div><br></div><div>The v.stream.order uses the PyGRASS vector library and implements two integration tests:</div><div><br></div><div><a href="https://trac.osgeo.org/grass/browser/grass-addons/grass7/vector/v.stream.order/testsuite/test_stream_order.py">https://trac.osgeo.org/grass/browser/grass-addons/grass7/vector/v.stream.order/testsuite/test_stream_order.py</a><br></div><div><br></div><div>The temporal module t.rast.univar uses integration tests to validate the combination of the temporal framework, PyGRASS and the functionality of r.univar:</div><div><br></div><div><a href="https://trac.osgeo.org/grass/browser/grass/trunk/temporal/t.rast.univar/testsuite/test_univar.py">https://trac.osgeo.org/grass/browser/grass/trunk/temporal/t.rast.univar/testsuite/test_univar.py</a><br></div><div><br></div><div>The module t.rast.aggreagte combines the temporal framework, PyGRASS and r.series. Its functionality is tested in several integration tests:</div><div><br></div><div><a href="https://trac.osgeo.org/grass/browser/grass/trunk/temporal/t.rast.aggregate#testsuite">https://trac.osgeo.org/grass/browser/grass/trunk/temporal/t.rast.aggregate#testsuite</a><br></div><div><br></div><div>Best regards</div><div>Soeren</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex">
<br>
By the way, working code does not necessarily mean good code. And vice<br>
versa, good code does not mean that it works the way it should.<br>
Yet, broken but "good" code (cleanly documented, tested as much as possible)<br>
can be easily fixed and probably easier optimised. Working, though<br>
poor/uncommented/untested code, is frequently, if not always, a<br>
big-time-consuming mission.<br>
<br>
The question, the way I understand things, is not if and at what extent<br>
we need tests. GRASS-GIS needs them.<br>
However, no matter the effort, tests will almost never be complete.-<br>
That's what I was told by computer scientists, and what I can confirm<br>
with my minimal experiences by doing, for at least two years now, in a<br>
dozen of mini-projects.<br>
<br>
Rather, the question is how can we bring, most, of the theory of testing in to<br>
reality, put it in real action, beautify GRASS' code, whether core or<br>
addons. My understanding is that "our" common understanding is to focus<br>
in raising the overall quality level, make it easy for some-one to read<br>
the code, to understand the code almost as if reading simple text, to enable<br>
some-one to improve or adapt a piece of code relatively fast.<br>
<br>
Step-by-step. Nothing is going to change overnight.<br>
Not to forget, the community is a mixture of members with a high<br>
diversity degree when looking at coding skills. Everyone should be<br>
invited. And everyone is invited. Experienced developers, are asked<br>
and, with all the respect, (you) carry the responsibility to shed light for<br>
the newcomers in coding for GRASS-GIS.<br>
<br>
Allow me please to reiterate what I have repeated indirectly<br>
or directly, some times: please, dear reader/coder/scripter, when you write code, no matter what you write, comment your code,<br>
use longer variable names, don't hesitate to repeat explaining, document<br>
here and there. Test. Use assertions in your code, even for simple,<br>
single functions. Write code that "invites" the reader.<br>
<br>
Yes, testing costs a lot of time. But, if comparing it with the time<br>
spent afterwards in debugging bad code, therein lies the wish to have spent the "less"<br>
time right in the beginning.<br>
<br>
Testing will boldly save big, valuable time.-<br>
It'll beautify GRASS-GIS and grow the community.<br>
It'll work for us, not against us.<span class="gmail-HOEnZb"><font color="#888888"><br>
<br>
Nikos<br>
</font></span></blockquote></div><br></div></div>