Changes between Version 21 and Version 22 of GSoC/2014/TestingFrameworkForGRASS


Ignore:
Timestamp:
May 26, 2014, 8:12:49 PM (10 years ago)
Author:
wenzeslaus
Comment:

how the test methods are invoked

Legend:

Unmodified
Added
Removed
Modified
  • GSoC/2014/TestingFrameworkForGRASS

    v21 v22  
    141141There is no easy way how to test that (GRASS) fatal errors are invoked when appropriate. Even if the test method (`test_*`) itself would run in separate process (not only the whole script) the process will be ended without proper reporting of the test result (considering we want detailed test results). However, since this applies also to fatal errors invoked by unintentional failure and to fatal errors, it seems that it will be necessary to invoke the test methods (`test_*`) in a separate process to at least finish the other tests and not break the final report. This might be done by function decorator so that we don't invoke new process for each function but only for those who need it (the ones using things which use `ctypes`).
    142142
     143=== How the individual test methods are invoked ===
     144
     145This describes how `unittest` is doing it and we want to use as many classes (directly or by inheriting) from `unittest` as possible, so it will be probably also our system.
     146
     147Loading of tests:
     148
     149{{{
     150# finds all test methods of a given test case and creates test suite
     151# suite class will get a list of instances of test case class with a method name (test method)
     152# getTestCaseNames == test method names
     153TestLoader.loadTestsFromTestCase()
     154        testCaseNames = filter(isTestMethod, dir(testCaseClass))
     155    loaded_suite = self.suiteClass(map(testCaseClass, testCaseNames))
     156
     157# finds all test cases in the module/script
     158TestLoader.loadTestsFromModule()
     159    for each object in module:
     160        if isinstance(obj, type) and issubclass(obj, case.TestCase):
     161                        tests.append(self.loadTestsFromTestCase(obj))
     162    suiteClass = suite.TestSuite
     163    tests = self.suiteClass(tests)
     164
     165# finds all tests passes them to test runner
     166TestProgram.runTests()
     167    self.test = self.testLoader.loadTestsFromModule(self.module)
     168    self.result = testRunner.run(self.test)
     169
     170# triggers the top level test suite
     171TextTestRunner.run(test)
     172    test(result)
     173}}}
     174
     175Running of tests (test suite can contain test suite or test case instances):
     176
     177{{{
     178# invokes the separate tests
     179# does setup and teardown for class
     180TestSuite.run(result)
     181    for each test:
     182        test(result)
     183
     184# runs the test method and adds the information to the result
     185# does setup and teardown for instance
     186TestCase.run(result)
     187}}}
     188
    143189=== Analyzing module run using Valgrind or others ===
    144190
    145191Modules (or perhaps any tests) can run with `valgrind` (probably `--tool=memcheck`). This could be done on the level of testing classes but the better option is to integrate this functionality (optional running with `valgrind`) into PyGRASS, so it could be easily usable through it. Environmental variable (GRASS_PYGRASS_VALGRIND) or additional option `valgrind_=True` (similarly to overwrite) would invoke module with `valgrind` (works for both binaries and scripts). Additional options can be passed to `valgrind` using `valgrind`'s environmental variable `$VALGRIND_OPTS`. Output would be saved in file to not interfere with module output.
    146192
    147 We may want to use also some (runtime checking) tools other than `valgrind`, for example clang/LLVM sanitizers (as for example [https://docs.python.org/devguide/clang.html Python does]). However, it is unclear how to handle more than one tool as well as it is unclear how to store the results for any of these (including `valgrind`) because one test can have multiple module calls (or none), module calls can be indirect (function in Python lib which calls a module or module calling module) and there is no standard way in `unittest` to pass additional test details.
     193We may want to use also some (runtime checking) tools other than `valgrind`, for example clang/LLVM sanitizers (as for example [https://docs.python.org/devguide/clang.html Python does]) or profiling (these would be different for C/C++ and Python). However, it is unclear how to handle more than one tool as well as it is unclear how to store the results for any of these (including `valgrind`) because one test can have multiple module calls (or none), module calls can be indirect (function in Python lib which calls a module or module calling module) and there is no standard way in `unittest` to pass additional test details.
    148194
    149195PyGRASS or specialized PyGRASS module runner (function) in testing framework can have function, global variable, or environmental variable which would specify which tool should run a module (if any) and what are the parameters (besides the possibility to set parameters by environmental variable defined by the tool). The should ideally be separated from the module output and go to a file in the test output directory (and it could be later linked from/included into the main report).