source: grass/trunk/lib/python/docs/src/gunittest_testing.rst

Last change on this file was 74315, checked in by neteler, 5 years ago

gunittest: mention Travis-CI and 'nc_spm_full_v2alpha' sample dataset available from http://fatra.cnr.ncsu.edu/data/

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id
  • Property svn:mime-type set to text/plain
File size: 30.9 KB
Line 
1Testing GRASS GIS source code and modules
2=========================================
3
4If you are already familiar with the basic concepts
5of GRASS testing framework, you might want to skip to one of:
6
7* :ref:`test-module` section
8* :ref:`test-c` section
9* :ref:`test-python` section
10* :ref:`test-doctest` section
11* :class:`~gunittest.case.TestCase` class
12* :ref:`running-tests-report` section
13
14
15Introduction
16------------
17
18For the testing in GRASS GIS, we are using a `gunittest` package and
19we usually refer to the system of writing and running tests
20as to a *GRASS testing framework*.
21
22The framework is based on Python `unittest`_ package with a large number
23of GRASS-specific improvements, extensions and changes. These include
24things such as creation of GRASS-aware HTML test reports,
25or running of test in the way that process terminations potentially
26caused by C library functions does not influence the main testing process.
27
28Some tests will run without any data but many tests require
29the small (basic) version of GRASS GIS sample Location for North Carolina
30(see `GRASS GIS sample data`).
31
32Basic example
33-------------
34
35If you are writing a test of a GRASS module,
36create a Python script with the content derived from the example below.
37When using existing existing maps, suppose you are in North Carolina SPM
38GRASS sample location.
39
40The file can contain one or more test case classes. Each class
41can contain one or more test methods (functions).
42Here we create one test case class with one test method.
43The other two methods are class methods ensuring the right environment
44for all test methods inside a test case class.
45When a test file becomes part of source code (which is the usual case)
46it must be placed into a directory named ``testsuite``.
47
48.. code-block:: python
49
50 from grass.gunittest.case import TestCase
51 from grass.gunittest.main import test
52
53
54 # test case class must be derived from grass.gunittest.TestCase
55 class TestSlopeAspect(TestCase):
56
57 @classmethod
58 def setUpClass(cls):
59 """Ensures expected computational region"""
60 # to not override mapset's region (which might be used by other tests)
61 cls.use_temp_region()
62 # cls.runModule or self.runModule is used for general module calls
63 cls.runModule('g.region', raster='elevation')
64 # note that the region set by default for NC location is the same as
65 # the elevation raster map, this is an example shows what to do
66 # in the general case
67
68 @classmethod
69 def tearDownClass(cls):
70 cls.del_temp_region()
71
72 # test method must start with test_
73 def test_limits(self):
74 """Test that slope and aspect are in expected limits"""
75 # we don't have to delete (g.remove) the maps
76 # but we need to use unique names within one test file
77 slope = 'limits_slope'
78 aspect = 'limits_aspect'
79 # self.assertModule is used to call module which we test
80 # we expect module to finish successfully
81 self.assertModule('r.slope.aspect', elevation='elevation',
82 slope=slope, aspect=aspect)
83 # function tests if map's min and max are within expected interval
84 self.assertRasterMinMax(map=slope, refmin=0, refmax=90,
85 msg="Slope in degrees must be between 0 and 90")
86 self.assertRasterMinMax(map=aspect, refmin=0, refmax=360,
87 msg="Aspect in degrees must be between 0 and 360")
88
89
90 if __name__ == '__main__':
91 test()
92
93In the example we have used only two assert methods, one to check that
94module runs and end successfully and the other to test that map values are
95within an expect interval. There is a much larger selection of assert methods
96in :class:`~gunittest.case.TestCase` class documentation
97and also in Python `unittest`_ package documentation.
98
99To run the test, run GRASS GIS, use NC SPM sample location and create
100a separate mapset (name it ``test`` for example). Then go to the directory
101with the test file and run it:
102
103.. code-block:: sh
104
105 python some_test_file.py
106
107The output goes to the terminal in this case. Read further to see
108also more advanced ways of invoking the tests.
109
110We have shown a test of a GRASS module using NC sample location.
111However, tests can be written also for C and Python library and also
112for internal functions in modules. See the rests of this document
113for a complete guide.
114
115
116Building blocks and terminology
117-------------------------------
118
119.. note::
120 Some parts of the terminology should be revised to ensure understanding and
121 acceptance.
122
123test function and test method
124 A *test function* is a test of one particular feature or a test of
125 one particular result.
126 A *test function* is referred to as *test method*, *individual test*
127 or just *test*.
128
129assert function and assert method
130 An *assert function* (or *assert method*) refers to a function
131 which checks that some predicate is fulfilled. For example,
132 predicate can be that two raster maps does not differ from each
133 other or that module run ends with successfully.
134
135test case
136 The test methods testing one particular topic or feature are in one
137 test case class.
138
139 From another point of view, one test case class contains all tests
140 which require the same preparation and cleanup steps.
141 In other words, a *test case* class contains all tests which are
142 using the same *test fixture*.
143
144 There is also a general :class:`~gunittest.case.TestCase` class which
145 all concrete test case classes should inherit from to get all
146 GRASS-specific testing functionality and also to be found
147 by the testing framework.
148
149test suite
150 A *test suite*, or also *testsuite*, is a set of tests focused on one
151 topic, functionality or unit (similarly to test case).
152 In GRASS GIS, it is a set of files in one ``testsuite`` directory.
153 The test files in one ``testsuite``
154 directory are expected to test what is in the parent directory
155 of a given ``testsuite`` directory. This is used to organize
156 tests in the source code and also to generate test reports.
157
158 The term *test suite* may also refer to ``TestSuite`` class
159 which is part of Python `unittest`_ test invocation mechanism
160 used by `gunittest` internally.
161
162 More generally, a *test suite* is a group of test cases or any tests
163 (test methods, test cases and other test suites) in one or more files.
164
165test file
166 A *test file* is a Python script executable as a standalone process.
167 It does not set up any special environment and runs where it was invoked.
168 The testing framework does not rely on the file to end in a standard
169 way which means that if one file ends with segmentation fault
170 the testing framework can continue in testing of other test files.
171 Test files are central part `gunittest` system and are also the biggest
172 difference from Python `unittest`_. Test file name should be unique
173 but does not have to contain all parent directory names, for example
174 it can consist from a simplified name of a module plus a word or two
175 describing which functionality is tested. The name should not contain
176 dots (except for the ``.py`` suffix).
177
178 Alternatively, a test file could be called *test script* or
179 *test module* (both in Python and GRASS sense) but note that
180 none of these is used.
181
182test runner and test invoker
183 Both *test runner* and *test invoker* refer to classes, functions or
184 scripts used to run (invoke) tests or test files. One of the terms may
185 fade of in the future (probably *invoke* because it is not used by
186 Python `unittest`_).
187
188test fixture (test set up and tear down)
189 The preparation of the test is called *setup* or *set up* and the cleaning
190 after the test is called *teardown* or *tear down*. A *test fixture* refers
191 to these two steps and also to the environment where the test or tests
192 are executed.
193
194 Each test case class can define ``setUp``, ``setUpClass``, ``tearDown``
195 and ``tearDownClass`` methods to implement preparation and cleanup
196 steps for tests it contains. The methods ending with ``Class`` are
197 class methods (in Python terminology) and should be defined using
198 ``@classmethod`` decorator and with ``cls`` as first argument. These
199 methods are executed once for the whole class while the methods
200 without ``Class`` are executed for each test method.
201
202 In GRASS GIS, the preparation may, but does not have to, contain imports
203 of maps, using temporary region, setting computational region,
204 or generating random maps. The cleanup step should remove temporary
205 region as well as remove all created maps and files.
206
207test report
208 A *test report* is a document or set of documents with results of
209 all executed tests together with additional information such as output
210 of test.
211
212 Note that also *test result* is used also used in similar context
213 because the class responsible for representing or creating the report
214 in Python `unittest`_ package is called ``TestResult``.
215
216test failure and test error
217 A *test failure* occurs when a assert fails, e.g. value of
218 a parameter given to ``assertTrue()`` function is ``False``.
219 A *test error* occurs when something what is not tested fails,
220 i.e. when exception is risen for example preparation code or
221 a test method itself.
222
223.. _test-general:
224
225Testing with gunittest package in general
226-----------------------------------------
227
228The tests should be in files in a ``testsuite`` directory which is a subdirectory
229of the directory with tested files (module, package, library). Each test file
230(testing file) can have can have several test cases (testing classes).
231All test file names should have pattern ``test*.py`` or ``*.py``
232if another naming convention seems more appropriate.
233
234GRASS GIS `gunittest` package and testing framework is similar to the standard
235Python ``unittest`` package, so the ways to build tests are very similar.
236Test methods are in a test test case class and each test method tests one
237think using one or more assert methods.
238
239::
240
241 from grass.gunittest.case import TestCase
242 from grass.gunittest.main import test
243
244
245 class TestPython(TestCase):
246
247 def test_counting(self):
248 """Test that Python can count to two"""
249 self.assertEqual(1 + 1, 2)
250
251
252 if __name__ == '__main__':
253 test()
254
255Each test file should be able to run by itself accept certain set of command
256line parameters (currently none). This is done using
257``if __name__ == '__main__'`` and ``gunittest.test()`` function.
258
259To run a test file, start GRASS session in the location and mapset suitable for
260testing (typically, NC sample location) and go to the test file's directory
261(it will be usually some ``testsuite`` directory in the source code)
262and run it as a Python script::
263
264 python test_something.py
265
266When running individual test files, it is advisable to be in a separate
267mapset, so for example when using NC sample location, you should use
268a new mapset of arbitrary name but not one of the predefined mapsets).
269
270To run all tests in the source tree, you have to be in the source code
271directory where you want to find tests, also you need to be inside
272a GRASS session and use command similar to this one::
273
274 python -m grass.gunittest.main --location nc_spm_grass7 --location-type nc
275
276All test files in all ``testsuite`` directories will be executed and
277a report will be created in a newly created ``testreport`` directory.
278Open the file ``testreport/index.html`` to browse though the results.
279Note that again you need to be in GRASS session to run the tests in this way.
280
281The ``--location-type`` parameter serves to filter tests according to data
282they can run successfully with. It is ignored for tests which does not have
283this specified.
284
285In this case each running test file gets its own mapset and
286current working directory but all run are in one location.
287
288.. warning::
289 The current location is ignored but you should not run tests
290 in the location which is precious to you for the case that something fails
291 and current location is used for tests.
292
293When your are writing tests you can rely on having maps which are present
294in the NC sample location, or you can generate random maps. You can also
295import your data which you store inside ``data`` directory inside the
296given ``testsuite`` directory (for maps, ASCII formats are usually used).
297If you can create tests independent on location projection and location data
298it is much better then relying on given data but it is not at all required
299and all approaches are encouraged.
300
301Whenever possible it is advantageous to use available assert methods.
302GRASS-specific assert methods are in :class:`gunittest.case.TestCase` class.
303For general assert methods refer to Python `unittest`_ package documentation.
304Both are used in the same way; they are methods of a given test case class.
305In cases (which should be rare) when no assert methods fits the purpose,
306you can use your own checking finalized with a call of ``assertTrue()``
307or ``assertFalse()`` method with the ``msg`` parameter parameter set
308to an informative message.
309
310When you are using multiple assert methods in one test method, you must
311carefully consider what assert methods are testing and in which order
312you should put them. Consider the following example::
313
314 # incorrect order
315 def test_map_in_list_wrong(self):
316 maps = get_list_of_maps()
317 self.assertIn('elevation', maps)
318 # there is no point in testing that
319 # if list (or string) was empty or None execution of test ended
320 # at the line with assertIn
321 self.assertTrue(maps)
322
323 # correct order
324 def test_map_in_list_correct(self):
325 maps = get_list_of_maps()
326 # see if list (or string) is not empty (or None)
327 self.assertTrue(maps)
328 # and then see if the list fulfills more advanced conditions
329 self.assertIn('elevation', maps)
330
331If you are not sure when you would use multiple asserts consider the case
332when using only ``assertIn()`` function::
333
334 def test_map_in_list_short(self):
335 maps = get_list_of_maps()
336 self.assertIn('elevation', maps)
337
338If the list (or string) is empty, the test fails and the message says
339something about ``elevation''`` not being in the ``maps`` but
340it might be much more useful if it would tell us that the list ``maps``
341does not contain any items. In case of ``maps`` being ``None``, the situation
342is more complicated since we using ``assertIn`` with ``None`` will
343cause test error (not only failure). We must consider what is
344expected behavior of ``get_list_of_maps()`` function and what
345we are actually testing. For example, if we would be testing function
346interface, we probably should test separately different possibilities
347using ``assertIsNotNone()`` and then ``assertTrue()`` and then anything else.
348
349Another reason for using multiple assert methods is that we may want to
350test different qualities of a result. Following the previous example,
351we can test that a list contains some map and does not contain some other.
352If you are testing a lot of things and they don't have any clear order
353or dependencies, it might be more advantageous to split
354testing into several testing methods and do the preparation (creating a list
355in our example) in ``setUpClass()`` or ``setUp()`` method.
356
357
358.. _test-module:
359
360Tests of GRASS modules
361----------------------
362
363This is applicable for both GRASS modules written in C or C++ and
364GRASS modules written in Python since we are testing the whole module
365(which is invoked as a subprocess).
366
367::
368
369 def test_elevation(self):
370 self.assertModule('r.info', map='elevation', flags='g')
371 ...
372
373Use method ``assertRasterMinMax()`` to test that a result is within
374expected range. This is a very general test which checks the basic
375correctness of the result and can be used with different maps
376in different locations.
377
378::
379
380 def test_slope_limits(self):
381 slope = 'limits_slope'
382 self.assertModule('r.slope.aspect', elevation='elevation',
383 slope=slope)
384 self.assertRasterMinMax(map=slope, refmin=0, refmax=90,
385 msg="Slope in degrees must be between 0 and 90")
386
387.. todo::
388 Add example of assertions of key-value results.
389
390Especially if a module module has a lot of different parameters allowed
391in different combinations, you should test the if the wrong ones are really
392disallowed and proper error messages are provided (in addition, you can
393test things such as creation and removal of maps in error states).
394
395::
396
397 from grass.gunittest.gmodules import SimpleModule
398
399 class TestRInfoParameterHandling(TestCase):
400 """Test r.info handling of wrong input of parameters."""
401
402 def test_rinfo_wrong_map(self):
403 """Test input of map which does not exist."""
404 map_name = 'does_not_exist'
405 # create a module instance suitable for testing
406 rinfo = SimpleModule('r.info', map=map_name, flags='g')
407 # test that module fails (ends with non-zero return code)
408 self.assertModuleFail(rinfo)
409 # test that error output is not empty
410 self.assertTrue(rinfo.outputs.stderr)
411 # test that the right map is mentioned in the error message
412 self.assertIn(map_name, stderr)
413
414In some cases it might be advantageous to create a module instance
415in `setUp()` method and then modify it in test methods.
416
417.. note:
418 Test should be (natural) language, i.e. locale, independent
419 to allow testing the functionality under different locale settings.
420 So, if you are testing content of messages (which should be usually
421 translated), use `assertIn()` method (regular expression might be
422 applicable in some cases but in most cases `in` is exactly the
423 operation needed).
424
425.. _test-c:
426
427Tests of C and C++ code
428-----------------------
429
430There are basically two possibilities how to test C and C++ code.
431If you are testing GRASS library code the functions which are part of API
432these functions are exposed through Python ``ctypes`` and thus can be tested
433in Python. See section :ref:`test-python` for reference.
434
435However, more advantageous and more preferable (although sometimes
436more complicated) solution is to write a special program, preferably
437GRASS module (i.e., using ``G_parser``). The dedicated program can
438provide more direct interface to C and C++ functions used by
439a GRASS module then the module and can also serve for doing benchmarks
440which are not part of the testing.
441This can approach can be applied to both
442
443See the example in ``lib/raster3d`` GRASS source code directory
444to create a proper Makefiles. A ``main()`` function should be written
445in the same way as for a standard module.
446
447Having a GRASS module for the purpose of testing you can write test
448as if it would be standard GRASS module.
449
450
451.. _test-python:
452
453Tests of Python code
454--------------------
455
456For testing of Python code contained in some package, use
457`gunittest` in the same way as `unittest`_ would be used.
458This basically means that if you will write tests of Python functions
459and C functions exposed to Python
460through ``ctypes`` API, you might want to focus more on `unittest`_
461documentation since you will perhaps need the more standard
462assert functions rather then the GRASS-specific ones.
463
464
465.. _test-doctest:
466
467Testing Python code with doctest
468--------------------------------
469
470.. note::
471 The primary use of ``doctest`` is to ensure that the documentation
472 for functions and classes is valid. Additionally, it can increase
473 the number of tests when executed together with other tests.
474
475In Python, the easiest thing to test are functions which performs some
476computations or string manipulations, i.e. they have some numbers or strings
477on the input and some other numbers or strings on the output.
478
479At the beginning you can use doctest for this purpose. The syntax is as follows::
480
481 def sum_list(list_to_sum):
482 """Here is some documentation in docstring.
483
484 And here is the test::
485
486 >>> sum_list([2, 5, 3])
487 10
488 """
489
490In case of GRASS modules which are Python scripts, you can add something like
491this to your script::
492
493 if __name__ == "__main__":
494 if len(sys.argv) == 2 and sys.argv[1] == '--doctest':
495 import doctest
496 doctest.testmod()
497 else:
498 main()
499
500No output means that everything was successful. Note that you cannot use all
501the ways of running doctest since doctest will fail don the module file due
502to the dot or dots in the file name. Moreover, it is sometimes required that
503the file is accessible through sys.path which is not true for case of GRASS modules.
504
505However, do not use use doctest for tests of edge cases, for tests which require
506generate complex data first, etc. In these cases use `gunittest`.
507
508
509.. _test-as-scripts:
510
511Tests as general scripts
512------------------------
513
514GRASS testing framework supports also general Python or Shell scripts
515to be used as test files. This is strongly discouraged because it
516is not using standard ``gnunittest`` assert functions which only leads
517to reimplementing the functionality, relying on a person examining the data,
518or improper tests such as mere testing
519if the module executed without an error without looking at the actual results.
520Moreover, the testing framework does not have a control over what is
521executed and how which limits potential usage and features of testing
522framework. Doing this also prevents testing framework from creating a
523detailed report and thus better understanding of what is tested and what is
524failing. Shell scripts are also harder to execute on MS Windows where the
525interpreter might not be available or might not be on path.
526
527The testing framework uses Shell interpreter with ``-e`` flag when executing
528the tests, so the tests does not have to use ``set -e`` and can rely on it being
529set from outside. The flag ensures that if some command fails, i.e. ends with
530non-zero return code (exit status), the execution of the script ends too.
531The testing framework also uses ``-x`` flag to print the executed commands
532which usually makes examining of the test output easier.
533
534If multiple test files are executed using ``grass.gunittest.main`` module,
535the testing framework creates a temporary Mapset for the general Python and
536Shell scripts in the same way as it does for ``gunittest``-based test files.
537When the tests are executed separately, the clean up in current Mapset
538and current working directory must be ensured by the user or the script itself
539(which is generally true for all test files).
540
541.. warning::
542 This is a bad practice which prevents creation of detailed reports and
543 usage of advanced ``gunittest`` features, so you should avoid it
544 whenever possible.
545
546
547Data
548----
549
550.. note::
551 Both the section and the practice itself are under development.
552
553Most of the tests requires some input data. However, it is good to write
554a test in the way that it is independent on the available data.
555In case of GRASS, we have we can have tests of functions where
556some numbers or strings are input and some numbers or string are output.
557These tests does not require any data to be provided since the numbers
558can be part of the test. Then we have another category of tests, typically
559tests of GRASS modules, which require some maps to be on the input
560and thus the output (and test) depends on the specific data.
561Again, it it best to have tests which does not require any special data
562or generally environment settings (e.g. geographic projection)
563but it is much easier to write good tests with a given set of data.
564So, an compromises must be made and tests of different types should be written.
565
566In the GRASS testing framework, each test file should be marked according to
567category it belongs to. Each category corresponds to GRASS location or locations
568where the test file can run successfully.
569
570Universal tests
571 First category is *universal*. The tests in this category use some some
572 hard coded constants, generated data, random data, or their own imported
573 data as in input to function and GRASS modules. All the tests, input data
574 and reference results should be projection independent. These tests will
575 runs always regardless of available locations.
576
577Standard names tests
578 Second category are tests using *standard names*. Tests rely on a
579 certain set of maps with particular names to be present in the location.
580 Moreover, the tests can rely also on the (semantic) meaning of the
581 names, i.e. raster map named elevation will always contain some kind of
582 digital elevation model of some area, so raster map elevation can be
583 used to compute aspect. In other words, these tests should be able to
584 (successfully) run in any location with a maps named in the same way as
585 in the standard testing location(s).
586
587Standard data tests
588 Third category of tests rely on *standard data*. These tests expect that the
589 GRASS location they run in not only contains the maps with particular names
590 as in the *standard names* but the tests rely also on the data being the
591 same as in the standard testing location(s). However, the (geographic)
592 projection or data storage can be different. This is expected to be the
593 most common case but it is much better if the tests is one of the previous
594 categories (*universal* or *standard names*). If it is possible the
595 functions or modules with tests in this category should have also tests
596 which will fit into one of the previous categories, even though these
597 additional tests will not be as precise as the other tests.
598
599Location specific tests
600 Finally, there are tests which requires certain concrete location. There
601 is (or will be) a set of standard testing locations each will have the same
602 data (maps) but the projections and data storage types will be different.
603 The suggested locations are: NC sample location in SPM projection,
604 NC in SPF, NC in LL, NC in XY, and perhaps NC in UTM, and NC in some
605 custom projection (in case of strange not-fitting projection, there is
606 a danger that the results of analyses can differer significantly).
607 Moreover, the set can be extended by GRASS locations which are using
608 different storage backends, e.g. PostGIS for vectors and PostgreSQL for
609 temporal database. Tests can specify one or preferably more of these
610 standard locations.
611
612Specialized location tests
613 Additionally, an specialized location with a collection of strange,
614 incorrect, or generally extreme data will be provided. In theory, more
615 than one location like this can be created if the data cannot be
616 together in one location or if the location itself is somehow special,
617 e.g. because of projection.
618
619Each category, or perhaps each location (will) have a set of external data
620available for import or other purposes. The standardization of this data
621is in question and thus this may be specific to each location or this
622can be a separate resource common to all tests using one of the standardized
623locations, or alternatively this data can be associated with the location
624with special data.
625
626.. note::
627 The more general category you choose for your tests the more testing data
628 can applied to your tests and the more different circumstances can be tried
629 with your tests.
630
631
632Data specific to one test
633-------------------------
634
635If the data required by the test are not part of standard location
636and cannot be part of the test file itself, this data should be stored
637in files in ``data`` subdirectory of ``testsuite`` directory.
638The test should access the data using a relative path from its location,
639i.e. all data will be accessed using ``data/...``. This ``data`` directory
640might be used directly when running test file directly in the directory
641in the source code or might be copied to the test current working directory
642when running tests by the main test invoking tool.
643
644
645Tests creating separate Mapsets, Locations and GRASS Databases
646--------------------------------------------------------------
647
648If test is creating a custom Mapset or Mapsets, it can create them in
649the current Location or create a custom GRASS Database in the current
650directory. In any case, test has to take care of cleaning up (deleting)
651the created directories and it has to use names which will be unique
652enough (name of the test case class or the file is probably a good choice
653but completely unique identifier is probably much better).
654
655If test needs custom Location or it tests something related to GRASS Database,
656it must always create a new GRASS Database in the current directory.
657
658In any case, the author must try the tests cautiously and several times
659in the same Location to see if everything works as expected. Testing
660framework is using Mapsets to separate the tests and the functions
661does not explicitly check for the case where a test is using different
662Mapset then the one which has been given to it by the framework.
663
664
665Analyzing quality of source code
666--------------------------------
667
668Besides testing, you can also use some tools to check the quality of your code
669according to various standards and occurrence of certain code patterns.
670
671For C/C++ code use third party solution `Coverity Scan`_ where GRASS GIS
672is registered as project number `1038`_. Also you can use `Cppcheck`_
673which will show a lot of errors which compilers do not check.
674In any case, set your compiler to high error and warning levels,
675check them and fix them in your code. Furthermore, `Travis-CI`_ is used
676to check if the source code can still be compiled after submitting changes
677to the repository.
678
679For Python, we recommend pylint and then for style issues pep8 tool
680(and perhaps also pep257 tool). However, there is more tools available
681you can use them together with the recommend ones.
682
683To provide a way to evaluate the Python source code in the whole GRASS source
684tree there is a Python script ``grass_py_static_check.py`` which uses
685pylint and pep8 with GRASS-specific settings. Run the tool in GRASS session
686in the source code root directory. A HTML report will be created in
687``pylint_report`` directory.
688
689::
690
691 grass_py_static_check.py
692
693.. note::
694 ``grass_py_static_check.py`` is available in `sandbox`_.
695
696Additionally, if you are invoking your Python code manually using python command,
697e.g. when testing, use parameters::
698
699 python -Qwarn -tt -3 some_module.py
700
701This will warn you about usage of old division semantics for integers
702and about incompatibilities with Python 3 (if you are using Python 2)
703which 2to3 tool cannot fix. Finally, it will issue errors if are using tabs
704for indentation inconsistently (note that you should not use tabs for
705indentation at all).
706
707
708Further reading
709---------------
710
711.. toctree::
712 :maxdepth: 2
713
714 gunittest
715 gunittest_running_tests
716
717
718.. _unittest: https://docs.python.org/2/library/unittest.html
719.. _doctest: https://docs.python.org/2/library/doctest.html
720.. _Coverity Scan: https://scan.coverity.com/
721.. _Travis-CI: https://travis-ci.org/GRASS-GIS/grass-ci
722.. _1038: https://scan.coverity.com/projects/1038
723.. _Cppcheck: http://cppcheck.sourceforge.net/
724.. _sandbox: https://svn.osgeo.org/grass/sandbox/wenzeslaus/grass_py_static_check.py
725.. _GRASS GIS sample data: https://grass.osgeo.org/download/sample-data and http://fatra.cnr.ncsu.edu/data/ (nc_spm_full_v2alpha)
Note: See TracBrowser for help on using the repository browser.