1#! /usr/bin/env python
2#
3# Gramps - a GTK+/GNOME based genealogy program
4#
5# Copyright (C) 2000-2005  Donald N. Allingham
6#
7# This program is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation; either version 2 of the License, or
10# (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with this program; if not, write to the Free Software
19# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20#
21# test/regrtest.py
22# Original: RunAllTests.py Written by Richard Taylor
23# (jgs: revised for embedded "test" subdirs as regrtest.py )
24
25"""
26Testing framework for performing a variety of unttests for Gramps.
27"""
28
29# TODO: review whether logging is really useful for unittest
30#  it does seem to work .. try -v5
31import logging
32
33import os
34import sys
35import unittest
36from optparse import OptionParser
37
38from .test import test_util as tu
39gramps_root=tu.path_append_parent()
40
41def make_parser():
42    usage = "usage: %prog [options]"
43    parser = OptionParser(usage)
44    parser.add_option("-v", "--verbosity", type="int",
45                      dest="verbose_level", default=0,
46                      help="Level of verboseness")
47    parser.add_option("-p", "--performance", action="store_true",
48                      dest="performance", default=False,
49                      help="Run the performance tests.")
50    return parser
51
52
53def getTestSuites(loc=gramps_root):
54    # in a developer's checkout, it is worth filtering-out .git
55    #  and we only need to look inside test subdirs
56    #   (this might change)
57    # this is not so performance critical that we can't afford
58    # a couple of function calls to make it readable
59    # TODO: handle parts of a module (see unittest.py)
60
61    ldr= unittest.defaultTestLoader
62
63    test_dirname = "test"
64    test_suffix = "_test.py"
65    def test_mod(p,ds):
66        """ test for path p=test dir; removes a dir '.git' in ds """
67        if ".git" in ds:
68            ds.remove(".git")
69        return os.path.basename(p) == test_dirname
70    def match_mod(fs):
71        """ test for any test modules; deletes all non-tests  """
72        # NB: do not delete fs elements within a "for f in fs"
73        dels= [f for f in fs if not f.endswith(test_suffix)]
74        for f in dels:
75            fs.remove(f)
76        return len(fs) > 0
77
78    test_suites = []
79    perf_suites = []
80    # note that test_mod and match_mod modify passed-in lists
81    paths = [(path,files) for path,dirs,files in os.walk(loc)
82                if test_mod(path,dirs) and match_mod(files)]
83
84    ## NO -- see explanation below
85    ##  oldpath = list(sys.path)
86    for (dir,test_modules) in paths:
87        sys.path.append(dir)
88
89        for module in test_modules:
90            if not module.endswith(test_suffix):
91                raise ValueError
92            mod = __import__(module[:-len(".py")])
93            if getattr(mod,"suite",None):
94                test_suites.append(mod.suite())
95            else:
96                test_suites.append(ldr.loadTestsFromModule(mod))
97            try:
98                perf_suites.append(mod.perfSuite())
99            except:
100                pass
101        # NO: was: remove temporary paths added
102        # this seems like it should be reasonable,
103        # but it causes failure in _GrampsDbWRFactories_test.py
104        #  (I suspect it is an actual bug in the runner
105        #   but the easiest fix is to keep the imports,
106        #   which is what other loaders seem to do)
107        # ==>  this aspect of test frameworks is *hard*
108        ## NO -- do NOT:
109        ## remove temporary paths added
110        ## sys.path = list(oldpath)
111    return (test_suites,perf_suites)
112
113
114if __name__ == '__main__':
115    def logging_init():
116        global logger
117        global console
118        console = logging.StreamHandler()
119        console.setLevel(logging.INFO)
120        console.setFormatter(logging.Formatter(
121            '%(name)-12s: %(levelname)-8s %(message)s'))
122        logger = logging.getLogger('Gramps')
123        logger.addHandler(console)
124        return console, logger
125
126    def logging_adjust(verbose_level):
127        if verbose_level == 1:
128            logger.setLevel(logging.INFO)
129            console.setLevel(logging.INFO)
130        elif verbose_level == 2:
131            logger.setLevel(logging.DEBUG)
132            console.setLevel(logging.DEBUG)
133        elif verbose_level == 3:
134            logger.setLevel(logging.NOTSET)
135            console.setLevel(logging.NOTSET)
136        elif verbose_level >= 4:
137            logger.setLevel(logging.NOTSET)
138            console.setLevel(logging.NOTSET)
139            os.environ['GRAMPS_SIGNAL'] = "1"
140        else:
141            logger.setLevel(logging.ERROR)
142            console.setLevel(logging.ERROR)
143
144    console,logger = logging_init()
145    options,args = make_parser().parse_args()
146    logging_adjust(options.verbose_level)
147
148    # TODO allow multiple subdirs, modules, or testnames
149    #  (see unittest.py)
150    # hmmm this is starting to look like a unittest.Testprog
151    # (maybe with a custom TestLoader)
152    if args and os.path.isdir(args[0]):
153        loc = args[0].rstrip(os.path.sep)
154    else:
155        loc = gramps_root
156
157    utests, ptests = getTestSuites(loc)
158    if options.performance:
159        suite = unittest.TestSuite(ptests)
160    else:
161        suite = unittest.TestSuite(utests)
162
163    unittest.TextTestRunner(verbosity=options.verbose_level).run(suite)
164
165#===eof===
166