| 1 | #!/usr/bin/env python |
|---|
| 2 | |
|---|
| 3 | # Deejayd, a media player daemon |
|---|
| 4 | # Copyright (C) 2007-2009 Mickael Royer <mickael.royer@gmail.com> |
|---|
| 5 | # Alexandre Rossi <alexandre.rossi@gmail.com> |
|---|
| 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 along |
|---|
| 18 | # with this program; if not, write to the Free Software Foundation, Inc., |
|---|
| 19 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
|---|
| 20 | |
|---|
| 21 | """ |
|---|
| 22 | This is the test suite launcher : |
|---|
| 23 | * Without arguments, it runs the whole test suite. |
|---|
| 24 | * It accepts a list of arguments which can be : |
|---|
| 25 | - a test module name without the 'test_' prefix. |
|---|
| 26 | e.g. : ./tests.py xmlprocessing |
|---|
| 27 | - a test module name without the 'test_' prefix, a slash, and a test |
|---|
| 28 | name in unittest dotted notation (See the documentation of |
|---|
| 29 | loadTestsFromName at |
|---|
| 30 | http://docs.python.org/lib/testloader-objects.html) |
|---|
| 31 | e.g. : ./tests.py xmlprocessing/TestAnswerParser |
|---|
| 32 | or ./tests.py xmlprocessing/TestAnswerParser.testAnswerParserError |
|---|
| 33 | * If the fist argument is 'list', list all the possibles tests that can be |
|---|
| 34 | combined on the command line restricted by the same arguments. |
|---|
| 35 | e.g. : ./tests.py list xmlprocessing client |
|---|
| 36 | would list all the tests that are to be run from those test modules. |
|---|
| 37 | """ |
|---|
| 38 | |
|---|
| 39 | import sys, os, glob |
|---|
| 40 | from optparse import OptionParser |
|---|
| 41 | import unittest |
|---|
| 42 | |
|---|
| 43 | import testdeejayd |
|---|
| 44 | |
|---|
| 45 | TEST_NAMESPACE = 'testdeejayd' |
|---|
| 46 | test_suites_dir = os.path.join(os.path.dirname(__file__), TEST_NAMESPACE) |
|---|
| 47 | |
|---|
| 48 | # Workaround for __import__ behavior, see |
|---|
| 49 | # http://docs.python.org/lib/built-in-funcs.html |
|---|
| 50 | def my_import(name): |
|---|
| 51 | mod = __import__(name) |
|---|
| 52 | components = name.split('.') |
|---|
| 53 | for comp in components[1:]: |
|---|
| 54 | mod = getattr(mod, comp) |
|---|
| 55 | return mod |
|---|
| 56 | |
|---|
| 57 | def get_testfile_from_id(id): |
|---|
| 58 | return os.path.join(test_suites_dir, "test_%s.py" % id) |
|---|
| 59 | |
|---|
| 60 | def get_id_from_module(module): |
|---|
| 61 | return module.__name__[len(TEST_NAMESPACE+'.'+'test_'):] |
|---|
| 62 | |
|---|
| 63 | def get_all_tests(): |
|---|
| 64 | return [(x, None) for x in glob.glob(get_testfile_from_id("*"))] |
|---|
| 65 | |
|---|
| 66 | usage = "usage: %prog [options] [tests-list]" |
|---|
| 67 | parser = OptionParser(usage=usage) |
|---|
| 68 | parser.add_option("-p","--profile",dest="profile",type="string",\ |
|---|
| 69 | help="testserver profile used for this test suite") |
|---|
| 70 | parser.set_defaults(profile="default") |
|---|
| 71 | (options, myargs) = parser.parse_args() |
|---|
| 72 | |
|---|
| 73 | # update profiles |
|---|
| 74 | from testdeejayd import TestCaseWithServer |
|---|
| 75 | TestCaseWithServer.profiles = options.profile |
|---|
| 76 | |
|---|
| 77 | tests_to_run = None |
|---|
| 78 | list_only = False |
|---|
| 79 | args = None |
|---|
| 80 | if len(myargs) > 0: |
|---|
| 81 | if myargs[0] == 'list': |
|---|
| 82 | list_only = True |
|---|
| 83 | args = myargs[1:] |
|---|
| 84 | else: |
|---|
| 85 | args = myargs |
|---|
| 86 | |
|---|
| 87 | if args: |
|---|
| 88 | tests_to_consider = [] |
|---|
| 89 | for test_id in args: |
|---|
| 90 | try: |
|---|
| 91 | test_module, test_name = test_id.split('/') |
|---|
| 92 | except ValueError: |
|---|
| 93 | test_module = test_id |
|---|
| 94 | test_name = None |
|---|
| 95 | |
|---|
| 96 | tests_to_consider.append((get_testfile_from_id(test_module), test_name)) |
|---|
| 97 | else: |
|---|
| 98 | tests_to_consider = get_all_tests() |
|---|
| 99 | |
|---|
| 100 | def get_test_suite(test_module, test_name=None): |
|---|
| 101 | test_suite = None |
|---|
| 102 | if test_name: |
|---|
| 103 | test_suite = unittest.defaultTestLoader.loadTestsFromName(test_name, |
|---|
| 104 | test_module) |
|---|
| 105 | else: |
|---|
| 106 | test_suite = unittest.defaultTestLoader.loadTestsFromModule(test_module) |
|---|
| 107 | return test_suite |
|---|
| 108 | |
|---|
| 109 | def get_module_and_name(test_id): |
|---|
| 110 | fn, test_name = test_id |
|---|
| 111 | module_path = '.'.join([TEST_NAMESPACE, os.path.basename(fn[:-3])]) |
|---|
| 112 | test_module = my_import(module_path) |
|---|
| 113 | return test_module, test_name |
|---|
| 114 | |
|---|
| 115 | def print_tests(class_name, test_name=None): |
|---|
| 116 | if class_name.startswith('Test'): |
|---|
| 117 | has_tests = False |
|---|
| 118 | for fun_name in dir(getattr(test_module, class_name)): |
|---|
| 119 | if fun_name.startswith('test')\ |
|---|
| 120 | and (not test_name or fun_name == test_name): |
|---|
| 121 | has_tests = True |
|---|
| 122 | print "%s/%s.%s" % (get_id_from_module(test_module), |
|---|
| 123 | class_name, fun_name) |
|---|
| 124 | if has_tests: |
|---|
| 125 | print "%s/%s" % (get_id_from_module(test_module), class_name) |
|---|
| 126 | |
|---|
| 127 | if list_only: |
|---|
| 128 | for test_id in tests_to_consider: |
|---|
| 129 | test_module, test_name = get_module_and_name(test_id) |
|---|
| 130 | if test_name: |
|---|
| 131 | splitted_test_name = test_name.split('.') |
|---|
| 132 | if len(splitted_test_name) > 1: |
|---|
| 133 | class_name, test_name = splitted_test_name |
|---|
| 134 | else: |
|---|
| 135 | class_name, test_name = splitted_test_name[0], None |
|---|
| 136 | print_tests(class_name, test_name) |
|---|
| 137 | else: |
|---|
| 138 | for class_name in dir(test_module): |
|---|
| 139 | print_tests(class_name) |
|---|
| 140 | else: |
|---|
| 141 | suitelist = [] |
|---|
| 142 | runner = unittest.TextTestRunner(verbosity = 2) |
|---|
| 143 | for test_id in tests_to_consider: |
|---|
| 144 | test_module, test_name = get_module_and_name(test_id) |
|---|
| 145 | suitelist.append(get_test_suite(test_module, test_name)) |
|---|
| 146 | runner.run(unittest.TestSuite(suitelist)) |
|---|
| 147 | |
|---|
| 148 | |
|---|
| 149 | # vim: ts=4 sw=4 expandtab |
|---|