123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163 |
- # -*- coding: utf-8 -*-
- """!@package grass.gunittest.main
- @brief GRASS Python testing framework module for running from command line
- Copyright (C) 2014 by the GRASS Development Team
- This program is free software under the GNU General Public
- License (>=v2). Read the file COPYING that comes with GRASS GIS
- for details.
- @author Vaclav Petras
- """
- import os
- import sys
- from unittest.main import TestProgram, USAGE_AS_MAIN
- TestProgram.USAGE = USAGE_AS_MAIN
- from .loader import GrassTestLoader
- from .runner import (GrassTestRunner, MultiTestResult,
- TextTestResult, KeyValueTestResult)
- from .invoker import GrassTestFilesInvoker
- from .utils import silent_rmtree
- import grass.script.core as gcore
- class GrassTestProgram(TestProgram):
- """A class to be used by individual test files (wrapped in the function)"""
- def __init__(self, exit_at_end, grass_location, clean_outputs=True,
- unittest_argv=None, module=None,
- verbosity=1,
- failfast=None, catchbreak=None):
- """Prepares the tests in GRASS way and then runs the tests.
- :param bool clean_outputs: if outputs in mapset and in ?
- """
- self.test = None
- self.grass_location = grass_location
- # it is unclear what the exact behavior is in unittest
- # buffer stdout and stderr during tests
- buffer_stdout_stderr = False
- grass_loader = GrassTestLoader(grass_location=self.grass_location)
- text_result = TextTestResult(stream=sys.stderr,
- descriptions=True,
- verbosity=verbosity)
- keyval_file = open('test_keyvalue_result.txt', 'w')
- keyval_result = KeyValueTestResult(stream=keyval_file)
- result = MultiTestResult(results=[text_result, keyval_result])
- grass_runner = GrassTestRunner(verbosity=verbosity,
- failfast=failfast,
- buffer=buffer_stdout_stderr,
- result=result)
- super(GrassTestProgram, self).__init__(module=module,
- argv=unittest_argv,
- testLoader=grass_loader,
- testRunner=grass_runner,
- exit=exit_at_end,
- verbosity=verbosity,
- failfast=failfast,
- catchbreak=catchbreak,
- buffer=buffer_stdout_stderr)
- keyval_file.close()
- def test():
- """Run a test of a module.
- """
- # TODO: put the link to to the report only if available
- # TODO: how to disable Python code coverage for module and C tests?
- # TODO: we probably need to have different test functions for C, Python modules, and Python code
- # TODO: combine the results using python -m coverage --help | grep combine
- # TODO: function to anonymize/beautify file names (in content and actual filenames)
- doing_coverage = False
- try:
- import coverage
- doing_coverage = True
- cov = coverage.coverage(omit="*testsuite*")
- cov.start()
- except ImportError:
- pass
- # TODO: add some message somewhere
- # TODO: enable passing omit to exclude also gunittest or nothing
- program = GrassTestProgram(module='__main__', exit_at_end=False, grass_location='all')
- # TODO: check if we are in the directory where the test file is
- # this will ensure that data directory is available when it is requested
- if doing_coverage:
- cov.stop()
- cov.html_report(directory='testcodecoverage')
- # TODO: is sys.exit the right thing here
- sys.exit(not program.result.wasSuccessful())
- # TODO: test or main? test looks more general
- # unittest has main() but doctest has testmod()
- main = test
- def discovery():
- """Recursively find all tests in testsuite directories and run them
- Everything is imported and runs in this process.
- Runs using::
- python main.py discovery [start_directory]
- """
- doing_coverage = False
- try:
- import coverage
- doing_coverage = True
- cov = coverage.coverage(omit="*testsuite*")
- cov.start()
- except ImportError:
- pass
- # TODO: add some message somewhere
- program = GrassTestProgram(grass_location='nc', exit_at_end=False)
- if doing_coverage:
- cov.stop()
- cov.html_report(directory='testcodecoverage')
- sys.exit(not program.result.wasSuccessful())
- # TODO: makefile rule should depend on the whole build
- # TODO: create a full interface (using grass parser or argparse)
- if __name__ == '__main__':
- if len(sys.argv) == 4:
- gisdbase = sys.argv[1]
- location = sys.argv[2]
- location_shortcut = sys.argv[3]
- elif len(sys.argv) == 3:
- location = sys.argv[1]
- location_shortcut = sys.argv[2]
- gisdbase = gcore.gisenv()['GISDBASE']
- else:
- sys.stderr.write("Usage: %s [gisdbase] location location_shortcut\n" % sys.argv[0])
- sys.exit(1)
- assert gisdbase
- if not os.path.exists(gisdbase):
- sys.stderr.write("GISDBASE <%s> does not exist\n" % gisdbase)
- sys.exit(1)
- results_dir = 'testreport'
- silent_rmtree(results_dir) # TODO: too brute force?
- invoker = GrassTestFilesInvoker(start_dir='.')
- # we can just iterate over all locations available in database
- # but the we don't know the right location label/shortcut
- invoker.run_in_location(gisdbase=gisdbase,
- location=location,
- location_shortcut=location_shortcut,
- results_dir=results_dir)
|