1import functools
2import sys
3import types
4import warnings
5
6import unittest
7
8class Test_TestLoader(unittest.TestCase):
9
10    ### Basic object tests
11    ################################################################
12
13    def test___init__(self):
14        loader = unittest.TestLoader()
15        self.assertEqual([], loader.errors)
16
17    ### Tests for TestLoader.loadTestsFromTestCase
18    ################################################################
19
20    # "Return a suite of all test cases contained in the TestCase-derived
21    # class testCaseClass"
22    def test_loadTestsFromTestCase(self):
23        class Foo(unittest.TestCase):
24            def test_1(self): pass
25            def test_2(self): pass
26            def foo_bar(self): pass
27
28        tests = unittest.TestSuite([Foo('test_1'), Foo('test_2')])
29
30        loader = unittest.TestLoader()
31        self.assertEqual(loader.loadTestsFromTestCase(Foo), tests)
32
33    # "Return a suite of all test cases contained in the TestCase-derived
34    # class testCaseClass"
35    #
36    # Make sure it does the right thing even if no tests were found
37    def test_loadTestsFromTestCase__no_matches(self):
38        class Foo(unittest.TestCase):
39            def foo_bar(self): pass
40
41        empty_suite = unittest.TestSuite()
42
43        loader = unittest.TestLoader()
44        self.assertEqual(loader.loadTestsFromTestCase(Foo), empty_suite)
45
46    # "Return a suite of all test cases contained in the TestCase-derived
47    # class testCaseClass"
48    #
49    # What happens if loadTestsFromTestCase() is given an object
50    # that isn't a subclass of TestCase? Specifically, what happens
51    # if testCaseClass is a subclass of TestSuite?
52    #
53    # This is checked for specifically in the code, so we better add a
54    # test for it.
55    def test_loadTestsFromTestCase__TestSuite_subclass(self):
56        class NotATestCase(unittest.TestSuite):
57            pass
58
59        loader = unittest.TestLoader()
60        try:
61            loader.loadTestsFromTestCase(NotATestCase)
62        except TypeError:
63            pass
64        else:
65            self.fail('Should raise TypeError')
66
67    # "Return a suite of all test cases contained in the TestCase-derived
68    # class testCaseClass"
69    #
70    # Make sure loadTestsFromTestCase() picks up the default test method
71    # name (as specified by TestCase), even though the method name does
72    # not match the default TestLoader.testMethodPrefix string
73    def test_loadTestsFromTestCase__default_method_name(self):
74        class Foo(unittest.TestCase):
75            def runTest(self):
76                pass
77
78        loader = unittest.TestLoader()
79        # This has to be false for the test to succeed
80        self.assertFalse('runTest'.startswith(loader.testMethodPrefix))
81
82        suite = loader.loadTestsFromTestCase(Foo)
83        self.assertIsInstance(suite, loader.suiteClass)
84        self.assertEqual(list(suite), [Foo('runTest')])
85
86    ################################################################
87    ### /Tests for TestLoader.loadTestsFromTestCase
88
89    ### Tests for TestLoader.loadTestsFromModule
90    ################################################################
91
92    # "This method searches `module` for classes derived from TestCase"
93    def test_loadTestsFromModule__TestCase_subclass(self):
94        m = types.ModuleType('m')
95        class MyTestCase(unittest.TestCase):
96            def test(self):
97                pass
98        m.testcase_1 = MyTestCase
99
100        loader = unittest.TestLoader()
101        suite = loader.loadTestsFromModule(m)
102        self.assertIsInstance(suite, loader.suiteClass)
103
104        expected = [loader.suiteClass([MyTestCase('test')])]
105        self.assertEqual(list(suite), expected)
106
107    # "This method searches `module` for classes derived from TestCase"
108    #
109    # What happens if no tests are found (no TestCase instances)?
110    def test_loadTestsFromModule__no_TestCase_instances(self):
111        m = types.ModuleType('m')
112
113        loader = unittest.TestLoader()
114        suite = loader.loadTestsFromModule(m)
115        self.assertIsInstance(suite, loader.suiteClass)
116        self.assertEqual(list(suite), [])
117
118    # "This method searches `module` for classes derived from TestCase"
119    #
120    # What happens if no tests are found (TestCases instances, but no tests)?
121    def test_loadTestsFromModule__no_TestCase_tests(self):
122        m = types.ModuleType('m')
123        class MyTestCase(unittest.TestCase):
124            pass
125        m.testcase_1 = MyTestCase
126
127        loader = unittest.TestLoader()
128        suite = loader.loadTestsFromModule(m)
129        self.assertIsInstance(suite, loader.suiteClass)
130
131        self.assertEqual(list(suite), [loader.suiteClass()])
132
133    # "This method searches `module` for classes derived from TestCase"s
134    #
135    # What happens if loadTestsFromModule() is given something other
136    # than a module?
137    #
138    # XXX Currently, it succeeds anyway. This flexibility
139    # should either be documented or loadTestsFromModule() should
140    # raise a TypeError
141    #
142    # XXX Certain people are using this behaviour. We'll add a test for it
143    def test_loadTestsFromModule__not_a_module(self):
144        class MyTestCase(unittest.TestCase):
145            def test(self):
146                pass
147
148        class NotAModule(object):
149            test_2 = MyTestCase
150
151        loader = unittest.TestLoader()
152        suite = loader.loadTestsFromModule(NotAModule)
153
154        reference = [unittest.TestSuite([MyTestCase('test')])]
155        self.assertEqual(list(suite), reference)
156
157
158    # Check that loadTestsFromModule honors a module
159    # with a load_tests function.
160    def test_loadTestsFromModule__load_tests(self):
161        m = types.ModuleType('m')
162        class MyTestCase(unittest.TestCase):
163            def test(self):
164                pass
165        m.testcase_1 = MyTestCase
166
167        load_tests_args = []
168        def load_tests(loader, tests, pattern):
169            self.assertIsInstance(tests, unittest.TestSuite)
170            load_tests_args.extend((loader, tests, pattern))
171            return tests
172        m.load_tests = load_tests
173
174        loader = unittest.TestLoader()
175        suite = loader.loadTestsFromModule(m)
176        self.assertIsInstance(suite, unittest.TestSuite)
177        self.assertEqual(load_tests_args, [loader, suite, None])
178
179        # In Python 3.11, the undocumented and unofficial use_load_tests has
180        # been removed.
181        with self.assertRaises(TypeError):
182            loader.loadTestsFromModule(m, False)
183        with self.assertRaises(TypeError):
184            loader.loadTestsFromModule(m, use_load_tests=False)
185
186    def test_loadTestsFromModule__pattern(self):
187        m = types.ModuleType('m')
188        class MyTestCase(unittest.TestCase):
189            def test(self):
190                pass
191        m.testcase_1 = MyTestCase
192
193        load_tests_args = []
194        def load_tests(loader, tests, pattern):
195            self.assertIsInstance(tests, unittest.TestSuite)
196            load_tests_args.extend((loader, tests, pattern))
197            return tests
198        m.load_tests = load_tests
199
200        loader = unittest.TestLoader()
201        suite = loader.loadTestsFromModule(m, pattern='testme.*')
202        self.assertIsInstance(suite, unittest.TestSuite)
203        self.assertEqual(load_tests_args, [loader, suite, 'testme.*'])
204
205    def test_loadTestsFromModule__faulty_load_tests(self):
206        m = types.ModuleType('m')
207
208        def load_tests(loader, tests, pattern):
209            raise TypeError('some failure')
210        m.load_tests = load_tests
211
212        loader = unittest.TestLoader()
213        suite = loader.loadTestsFromModule(m)
214        self.assertIsInstance(suite, unittest.TestSuite)
215        self.assertEqual(suite.countTestCases(), 1)
216        # Errors loading the suite are also captured for introspection.
217        self.assertNotEqual([], loader.errors)
218        self.assertEqual(1, len(loader.errors))
219        error = loader.errors[0]
220        self.assertTrue(
221            'Failed to call load_tests:' in error,
222            'missing error string in %r' % error)
223        test = list(suite)[0]
224
225        self.assertRaisesRegex(TypeError, "some failure", test.m)
226
227    ################################################################
228    ### /Tests for TestLoader.loadTestsFromModule()
229
230    ### Tests for TestLoader.loadTestsFromName()
231    ################################################################
232
233    # "The specifier name is a ``dotted name'' that may resolve either to
234    # a module, a test case class, a TestSuite instance, a test method
235    # within a test case class, or a callable object which returns a
236    # TestCase or TestSuite instance."
237    #
238    # Is ValueError raised in response to an empty name?
239    def test_loadTestsFromName__empty_name(self):
240        loader = unittest.TestLoader()
241
242        try:
243            loader.loadTestsFromName('')
244        except ValueError as e:
245            self.assertEqual(str(e), "Empty module name")
246        else:
247            self.fail("TestLoader.loadTestsFromName failed to raise ValueError")
248
249    # "The specifier name is a ``dotted name'' that may resolve either to
250    # a module, a test case class, a TestSuite instance, a test method
251    # within a test case class, or a callable object which returns a
252    # TestCase or TestSuite instance."
253    #
254    # What happens when the name contains invalid characters?
255    def test_loadTestsFromName__malformed_name(self):
256        loader = unittest.TestLoader()
257
258        suite = loader.loadTestsFromName('abc () //')
259        error, test = self.check_deferred_error(loader, suite)
260        expected = "Failed to import test module: abc () //"
261        expected_regex = r"Failed to import test module: abc \(\) //"
262        self.assertIn(
263            expected, error,
264            'missing error string in %r' % error)
265        self.assertRaisesRegex(
266            ImportError, expected_regex, getattr(test, 'abc () //'))
267
268    # "The specifier name is a ``dotted name'' that may resolve ... to a
269    # module"
270    #
271    # What happens when a module by that name can't be found?
272    def test_loadTestsFromName__unknown_module_name(self):
273        loader = unittest.TestLoader()
274
275        suite = loader.loadTestsFromName('sdasfasfasdf')
276        expected = "No module named 'sdasfasfasdf'"
277        error, test = self.check_deferred_error(loader, suite)
278        self.assertIn(
279            expected, error,
280            'missing error string in %r' % error)
281        self.assertRaisesRegex(ImportError, expected, test.sdasfasfasdf)
282
283    # "The specifier name is a ``dotted name'' that may resolve either to
284    # a module, a test case class, a TestSuite instance, a test method
285    # within a test case class, or a callable object which returns a
286    # TestCase or TestSuite instance."
287    #
288    # What happens when the module is found, but the attribute isn't?
289    def test_loadTestsFromName__unknown_attr_name_on_module(self):
290        loader = unittest.TestLoader()
291
292        suite = loader.loadTestsFromName('unittest.loader.sdasfasfasdf')
293        expected = "module 'unittest.loader' has no attribute 'sdasfasfasdf'"
294        error, test = self.check_deferred_error(loader, suite)
295        self.assertIn(
296            expected, error,
297            'missing error string in %r' % error)
298        self.assertRaisesRegex(AttributeError, expected, test.sdasfasfasdf)
299
300    # "The specifier name is a ``dotted name'' that may resolve either to
301    # a module, a test case class, a TestSuite instance, a test method
302    # within a test case class, or a callable object which returns a
303    # TestCase or TestSuite instance."
304    #
305    # What happens when the module is found, but the attribute isn't?
306    def test_loadTestsFromName__unknown_attr_name_on_package(self):
307        loader = unittest.TestLoader()
308
309        suite = loader.loadTestsFromName('unittest.sdasfasfasdf')
310        expected = "No module named 'unittest.sdasfasfasdf'"
311        error, test = self.check_deferred_error(loader, suite)
312        self.assertIn(
313            expected, error,
314            'missing error string in %r' % error)
315        self.assertRaisesRegex(ImportError, expected, test.sdasfasfasdf)
316
317    # "The specifier name is a ``dotted name'' that may resolve either to
318    # a module, a test case class, a TestSuite instance, a test method
319    # within a test case class, or a callable object which returns a
320    # TestCase or TestSuite instance."
321    #
322    # What happens when we provide the module, but the attribute can't be
323    # found?
324    def test_loadTestsFromName__relative_unknown_name(self):
325        loader = unittest.TestLoader()
326
327        suite = loader.loadTestsFromName('sdasfasfasdf', unittest)
328        expected = "module 'unittest' has no attribute 'sdasfasfasdf'"
329        error, test = self.check_deferred_error(loader, suite)
330        self.assertIn(
331            expected, error,
332            'missing error string in %r' % error)
333        self.assertRaisesRegex(AttributeError, expected, test.sdasfasfasdf)
334
335    # "The specifier name is a ``dotted name'' that may resolve either to
336    # a module, a test case class, a TestSuite instance, a test method
337    # within a test case class, or a callable object which returns a
338    # TestCase or TestSuite instance."
339    # ...
340    # "The method optionally resolves name relative to the given module"
341    #
342    # Does loadTestsFromName raise ValueError when passed an empty
343    # name relative to a provided module?
344    #
345    # XXX Should probably raise a ValueError instead of an AttributeError
346    def test_loadTestsFromName__relative_empty_name(self):
347        loader = unittest.TestLoader()
348
349        suite = loader.loadTestsFromName('', unittest)
350        error, test = self.check_deferred_error(loader, suite)
351        expected = "has no attribute ''"
352        self.assertIn(
353            expected, error,
354            'missing error string in %r' % error)
355        self.assertRaisesRegex(AttributeError, expected, getattr(test, ''))
356
357    # "The specifier name is a ``dotted name'' that may resolve either to
358    # a module, a test case class, a TestSuite instance, a test method
359    # within a test case class, or a callable object which returns a
360    # TestCase or TestSuite instance."
361    # ...
362    # "The method optionally resolves name relative to the given module"
363    #
364    # What happens when an impossible name is given, relative to the provided
365    # `module`?
366    def test_loadTestsFromName__relative_malformed_name(self):
367        loader = unittest.TestLoader()
368
369        # XXX Should this raise AttributeError or ValueError?
370        suite = loader.loadTestsFromName('abc () //', unittest)
371        error, test = self.check_deferred_error(loader, suite)
372        expected = "module 'unittest' has no attribute 'abc () //'"
373        expected_regex = r"module 'unittest' has no attribute 'abc \(\) //'"
374        self.assertIn(
375            expected, error,
376            'missing error string in %r' % error)
377        self.assertRaisesRegex(
378            AttributeError, expected_regex, getattr(test, 'abc () //'))
379
380    # "The method optionally resolves name relative to the given module"
381    #
382    # Does loadTestsFromName raise TypeError when the `module` argument
383    # isn't a module object?
384    #
385    # XXX Accepts the not-a-module object, ignoring the object's type
386    # This should raise an exception or the method name should be changed
387    #
388    # XXX Some people are relying on this, so keep it for now
389    def test_loadTestsFromName__relative_not_a_module(self):
390        class MyTestCase(unittest.TestCase):
391            def test(self):
392                pass
393
394        class NotAModule(object):
395            test_2 = MyTestCase
396
397        loader = unittest.TestLoader()
398        suite = loader.loadTestsFromName('test_2', NotAModule)
399
400        reference = [MyTestCase('test')]
401        self.assertEqual(list(suite), reference)
402
403    # "The specifier name is a ``dotted name'' that may resolve either to
404    # a module, a test case class, a TestSuite instance, a test method
405    # within a test case class, or a callable object which returns a
406    # TestCase or TestSuite instance."
407    #
408    # Does it raise an exception if the name resolves to an invalid
409    # object?
410    def test_loadTestsFromName__relative_bad_object(self):
411        m = types.ModuleType('m')
412        m.testcase_1 = object()
413
414        loader = unittest.TestLoader()
415        try:
416            loader.loadTestsFromName('testcase_1', m)
417        except TypeError:
418            pass
419        else:
420            self.fail("Should have raised TypeError")
421
422    # "The specifier name is a ``dotted name'' that may
423    # resolve either to ... a test case class"
424    def test_loadTestsFromName__relative_TestCase_subclass(self):
425        m = types.ModuleType('m')
426        class MyTestCase(unittest.TestCase):
427            def test(self):
428                pass
429        m.testcase_1 = MyTestCase
430
431        loader = unittest.TestLoader()
432        suite = loader.loadTestsFromName('testcase_1', m)
433        self.assertIsInstance(suite, loader.suiteClass)
434        self.assertEqual(list(suite), [MyTestCase('test')])
435
436    # "The specifier name is a ``dotted name'' that may resolve either to
437    # a module, a test case class, a TestSuite instance, a test method
438    # within a test case class, or a callable object which returns a
439    # TestCase or TestSuite instance."
440    def test_loadTestsFromName__relative_TestSuite(self):
441        m = types.ModuleType('m')
442        class MyTestCase(unittest.TestCase):
443            def test(self):
444                pass
445        m.testsuite = unittest.TestSuite([MyTestCase('test')])
446
447        loader = unittest.TestLoader()
448        suite = loader.loadTestsFromName('testsuite', m)
449        self.assertIsInstance(suite, loader.suiteClass)
450
451        self.assertEqual(list(suite), [MyTestCase('test')])
452
453    # "The specifier name is a ``dotted name'' that may resolve ... to
454    # ... a test method within a test case class"
455    def test_loadTestsFromName__relative_testmethod(self):
456        m = types.ModuleType('m')
457        class MyTestCase(unittest.TestCase):
458            def test(self):
459                pass
460        m.testcase_1 = MyTestCase
461
462        loader = unittest.TestLoader()
463        suite = loader.loadTestsFromName('testcase_1.test', m)
464        self.assertIsInstance(suite, loader.suiteClass)
465
466        self.assertEqual(list(suite), [MyTestCase('test')])
467
468    # "The specifier name is a ``dotted name'' that may resolve either to
469    # a module, a test case class, a TestSuite instance, a test method
470    # within a test case class, or a callable object which returns a
471    # TestCase or TestSuite instance."
472    #
473    # Does loadTestsFromName() raise the proper exception when trying to
474    # resolve "a test method within a test case class" that doesn't exist
475    # for the given name (relative to a provided module)?
476    def test_loadTestsFromName__relative_invalid_testmethod(self):
477        m = types.ModuleType('m')
478        class MyTestCase(unittest.TestCase):
479            def test(self):
480                pass
481        m.testcase_1 = MyTestCase
482
483        loader = unittest.TestLoader()
484        suite = loader.loadTestsFromName('testcase_1.testfoo', m)
485        expected = "type object 'MyTestCase' has no attribute 'testfoo'"
486        error, test = self.check_deferred_error(loader, suite)
487        self.assertIn(
488            expected, error,
489            'missing error string in %r' % error)
490        self.assertRaisesRegex(AttributeError, expected, test.testfoo)
491
492    # "The specifier name is a ``dotted name'' that may resolve ... to
493    # ... a callable object which returns a ... TestSuite instance"
494    def test_loadTestsFromName__callable__TestSuite(self):
495        m = types.ModuleType('m')
496        testcase_1 = unittest.FunctionTestCase(lambda: None)
497        testcase_2 = unittest.FunctionTestCase(lambda: None)
498        def return_TestSuite():
499            return unittest.TestSuite([testcase_1, testcase_2])
500        m.return_TestSuite = return_TestSuite
501
502        loader = unittest.TestLoader()
503        suite = loader.loadTestsFromName('return_TestSuite', m)
504        self.assertIsInstance(suite, loader.suiteClass)
505        self.assertEqual(list(suite), [testcase_1, testcase_2])
506
507    # "The specifier name is a ``dotted name'' that may resolve ... to
508    # ... a callable object which returns a TestCase ... instance"
509    def test_loadTestsFromName__callable__TestCase_instance(self):
510        m = types.ModuleType('m')
511        testcase_1 = unittest.FunctionTestCase(lambda: None)
512        def return_TestCase():
513            return testcase_1
514        m.return_TestCase = return_TestCase
515
516        loader = unittest.TestLoader()
517        suite = loader.loadTestsFromName('return_TestCase', m)
518        self.assertIsInstance(suite, loader.suiteClass)
519        self.assertEqual(list(suite), [testcase_1])
520
521    # "The specifier name is a ``dotted name'' that may resolve ... to
522    # ... a callable object which returns a TestCase ... instance"
523    #*****************************************************************
524    #Override the suiteClass attribute to ensure that the suiteClass
525    #attribute is used
526    def test_loadTestsFromName__callable__TestCase_instance_ProperSuiteClass(self):
527        class SubTestSuite(unittest.TestSuite):
528            pass
529        m = types.ModuleType('m')
530        testcase_1 = unittest.FunctionTestCase(lambda: None)
531        def return_TestCase():
532            return testcase_1
533        m.return_TestCase = return_TestCase
534
535        loader = unittest.TestLoader()
536        loader.suiteClass = SubTestSuite
537        suite = loader.loadTestsFromName('return_TestCase', m)
538        self.assertIsInstance(suite, loader.suiteClass)
539        self.assertEqual(list(suite), [testcase_1])
540
541    # "The specifier name is a ``dotted name'' that may resolve ... to
542    # ... a test method within a test case class"
543    #*****************************************************************
544    #Override the suiteClass attribute to ensure that the suiteClass
545    #attribute is used
546    def test_loadTestsFromName__relative_testmethod_ProperSuiteClass(self):
547        class SubTestSuite(unittest.TestSuite):
548            pass
549        m = types.ModuleType('m')
550        class MyTestCase(unittest.TestCase):
551            def test(self):
552                pass
553        m.testcase_1 = MyTestCase
554
555        loader = unittest.TestLoader()
556        loader.suiteClass=SubTestSuite
557        suite = loader.loadTestsFromName('testcase_1.test', m)
558        self.assertIsInstance(suite, loader.suiteClass)
559
560        self.assertEqual(list(suite), [MyTestCase('test')])
561
562    # "The specifier name is a ``dotted name'' that may resolve ... to
563    # ... a callable object which returns a TestCase or TestSuite instance"
564    #
565    # What happens if the callable returns something else?
566    def test_loadTestsFromName__callable__wrong_type(self):
567        m = types.ModuleType('m')
568        def return_wrong():
569            return 6
570        m.return_wrong = return_wrong
571
572        loader = unittest.TestLoader()
573        try:
574            suite = loader.loadTestsFromName('return_wrong', m)
575        except TypeError:
576            pass
577        else:
578            self.fail("TestLoader.loadTestsFromName failed to raise TypeError")
579
580    # "The specifier can refer to modules and packages which have not been
581    # imported; they will be imported as a side-effect"
582    def test_loadTestsFromName__module_not_loaded(self):
583        # We're going to try to load this module as a side-effect, so it
584        # better not be loaded before we try.
585        #
586        module_name = 'unittest.test.dummy'
587        sys.modules.pop(module_name, None)
588
589        loader = unittest.TestLoader()
590        try:
591            suite = loader.loadTestsFromName(module_name)
592
593            self.assertIsInstance(suite, loader.suiteClass)
594            self.assertEqual(list(suite), [])
595
596            # module should now be loaded, thanks to loadTestsFromName()
597            self.assertIn(module_name, sys.modules)
598        finally:
599            if module_name in sys.modules:
600                del sys.modules[module_name]
601
602    ################################################################
603    ### Tests for TestLoader.loadTestsFromName()
604
605    ### Tests for TestLoader.loadTestsFromNames()
606    ################################################################
607
608    def check_deferred_error(self, loader, suite):
609        """Helper function for checking that errors in loading are reported.
610
611        :param loader: A loader with some errors.
612        :param suite: A suite that should have a late bound error.
613        :return: The first error message from the loader and the test object
614            from the suite.
615        """
616        self.assertIsInstance(suite, unittest.TestSuite)
617        self.assertEqual(suite.countTestCases(), 1)
618        # Errors loading the suite are also captured for introspection.
619        self.assertNotEqual([], loader.errors)
620        self.assertEqual(1, len(loader.errors))
621        error = loader.errors[0]
622        test = list(suite)[0]
623        return error, test
624
625    # "Similar to loadTestsFromName(), but takes a sequence of names rather
626    # than a single name."
627    #
628    # What happens if that sequence of names is empty?
629    def test_loadTestsFromNames__empty_name_list(self):
630        loader = unittest.TestLoader()
631
632        suite = loader.loadTestsFromNames([])
633        self.assertIsInstance(suite, loader.suiteClass)
634        self.assertEqual(list(suite), [])
635
636    # "Similar to loadTestsFromName(), but takes a sequence of names rather
637    # than a single name."
638    # ...
639    # "The method optionally resolves name relative to the given module"
640    #
641    # What happens if that sequence of names is empty?
642    #
643    # XXX Should this raise a ValueError or just return an empty TestSuite?
644    def test_loadTestsFromNames__relative_empty_name_list(self):
645        loader = unittest.TestLoader()
646
647        suite = loader.loadTestsFromNames([], unittest)
648        self.assertIsInstance(suite, loader.suiteClass)
649        self.assertEqual(list(suite), [])
650
651    # "The specifier name is a ``dotted name'' that may resolve either to
652    # a module, a test case class, a TestSuite instance, a test method
653    # within a test case class, or a callable object which returns a
654    # TestCase or TestSuite instance."
655    #
656    # Is ValueError raised in response to an empty name?
657    def test_loadTestsFromNames__empty_name(self):
658        loader = unittest.TestLoader()
659
660        try:
661            loader.loadTestsFromNames([''])
662        except ValueError as e:
663            self.assertEqual(str(e), "Empty module name")
664        else:
665            self.fail("TestLoader.loadTestsFromNames failed to raise ValueError")
666
667    # "The specifier name is a ``dotted name'' that may resolve either to
668    # a module, a test case class, a TestSuite instance, a test method
669    # within a test case class, or a callable object which returns a
670    # TestCase or TestSuite instance."
671    #
672    # What happens when presented with an impossible module name?
673    def test_loadTestsFromNames__malformed_name(self):
674        loader = unittest.TestLoader()
675
676        # XXX Should this raise ValueError or ImportError?
677        suite = loader.loadTestsFromNames(['abc () //'])
678        error, test = self.check_deferred_error(loader, list(suite)[0])
679        expected = "Failed to import test module: abc () //"
680        expected_regex = r"Failed to import test module: abc \(\) //"
681        self.assertIn(
682            expected,  error,
683            'missing error string in %r' % error)
684        self.assertRaisesRegex(
685            ImportError, expected_regex, getattr(test, 'abc () //'))
686
687    # "The specifier name is a ``dotted name'' that may resolve either to
688    # a module, a test case class, a TestSuite instance, a test method
689    # within a test case class, or a callable object which returns a
690    # TestCase or TestSuite instance."
691    #
692    # What happens when no module can be found for the given name?
693    def test_loadTestsFromNames__unknown_module_name(self):
694        loader = unittest.TestLoader()
695
696        suite = loader.loadTestsFromNames(['sdasfasfasdf'])
697        error, test = self.check_deferred_error(loader, list(suite)[0])
698        expected = "Failed to import test module: sdasfasfasdf"
699        self.assertIn(
700            expected, error,
701            'missing error string in %r' % error)
702        self.assertRaisesRegex(ImportError, expected, test.sdasfasfasdf)
703
704    # "The specifier name is a ``dotted name'' that may resolve either to
705    # a module, a test case class, a TestSuite instance, a test method
706    # within a test case class, or a callable object which returns a
707    # TestCase or TestSuite instance."
708    #
709    # What happens when the module can be found, but not the attribute?
710    def test_loadTestsFromNames__unknown_attr_name(self):
711        loader = unittest.TestLoader()
712
713        suite = loader.loadTestsFromNames(
714            ['unittest.loader.sdasfasfasdf', 'unittest.test.dummy'])
715        error, test = self.check_deferred_error(loader, list(suite)[0])
716        expected = "module 'unittest.loader' has no attribute 'sdasfasfasdf'"
717        self.assertIn(
718            expected, error,
719            'missing error string in %r' % error)
720        self.assertRaisesRegex(AttributeError, expected, test.sdasfasfasdf)
721
722    # "The specifier name is a ``dotted name'' that may resolve either to
723    # a module, a test case class, a TestSuite instance, a test method
724    # within a test case class, or a callable object which returns a
725    # TestCase or TestSuite instance."
726    # ...
727    # "The method optionally resolves name relative to the given module"
728    #
729    # What happens when given an unknown attribute on a specified `module`
730    # argument?
731    def test_loadTestsFromNames__unknown_name_relative_1(self):
732        loader = unittest.TestLoader()
733
734        suite = loader.loadTestsFromNames(['sdasfasfasdf'], unittest)
735        error, test = self.check_deferred_error(loader, list(suite)[0])
736        expected = "module 'unittest' has no attribute 'sdasfasfasdf'"
737        self.assertIn(
738            expected, error,
739            'missing error string in %r' % error)
740        self.assertRaisesRegex(AttributeError, expected, test.sdasfasfasdf)
741
742    # "The specifier name is a ``dotted name'' that may resolve either to
743    # a module, a test case class, a TestSuite instance, a test method
744    # within a test case class, or a callable object which returns a
745    # TestCase or TestSuite instance."
746    # ...
747    # "The method optionally resolves name relative to the given module"
748    #
749    # Do unknown attributes (relative to a provided module) still raise an
750    # exception even in the presence of valid attribute names?
751    def test_loadTestsFromNames__unknown_name_relative_2(self):
752        loader = unittest.TestLoader()
753
754        suite = loader.loadTestsFromNames(['TestCase', 'sdasfasfasdf'], unittest)
755        error, test = self.check_deferred_error(loader, list(suite)[1])
756        expected = "module 'unittest' has no attribute 'sdasfasfasdf'"
757        self.assertIn(
758            expected, error,
759            'missing error string in %r' % error)
760        self.assertRaisesRegex(AttributeError, expected, test.sdasfasfasdf)
761
762    # "The specifier name is a ``dotted name'' that may resolve either to
763    # a module, a test case class, a TestSuite instance, a test method
764    # within a test case class, or a callable object which returns a
765    # TestCase or TestSuite instance."
766    # ...
767    # "The method optionally resolves name relative to the given module"
768    #
769    # What happens when faced with the empty string?
770    #
771    # XXX This currently raises AttributeError, though ValueError is probably
772    # more appropriate
773    def test_loadTestsFromNames__relative_empty_name(self):
774        loader = unittest.TestLoader()
775
776        suite = loader.loadTestsFromNames([''], unittest)
777        error, test = self.check_deferred_error(loader, list(suite)[0])
778        expected = "has no attribute ''"
779        self.assertIn(
780            expected, error,
781            'missing error string in %r' % error)
782        self.assertRaisesRegex(AttributeError, expected, getattr(test, ''))
783
784    # "The specifier name is a ``dotted name'' that may resolve either to
785    # a module, a test case class, a TestSuite instance, a test method
786    # within a test case class, or a callable object which returns a
787    # TestCase or TestSuite instance."
788    # ...
789    # "The method optionally resolves name relative to the given module"
790    #
791    # What happens when presented with an impossible attribute name?
792    def test_loadTestsFromNames__relative_malformed_name(self):
793        loader = unittest.TestLoader()
794
795        # XXX Should this raise AttributeError or ValueError?
796        suite = loader.loadTestsFromNames(['abc () //'], unittest)
797        error, test = self.check_deferred_error(loader, list(suite)[0])
798        expected = "module 'unittest' has no attribute 'abc () //'"
799        expected_regex = r"module 'unittest' has no attribute 'abc \(\) //'"
800        self.assertIn(
801            expected, error,
802            'missing error string in %r' % error)
803        self.assertRaisesRegex(
804            AttributeError, expected_regex, getattr(test, 'abc () //'))
805
806    # "The method optionally resolves name relative to the given module"
807    #
808    # Does loadTestsFromNames() make sure the provided `module` is in fact
809    # a module?
810    #
811    # XXX This validation is currently not done. This flexibility should
812    # either be documented or a TypeError should be raised.
813    def test_loadTestsFromNames__relative_not_a_module(self):
814        class MyTestCase(unittest.TestCase):
815            def test(self):
816                pass
817
818        class NotAModule(object):
819            test_2 = MyTestCase
820
821        loader = unittest.TestLoader()
822        suite = loader.loadTestsFromNames(['test_2'], NotAModule)
823
824        reference = [unittest.TestSuite([MyTestCase('test')])]
825        self.assertEqual(list(suite), reference)
826
827    # "The specifier name is a ``dotted name'' that may resolve either to
828    # a module, a test case class, a TestSuite instance, a test method
829    # within a test case class, or a callable object which returns a
830    # TestCase or TestSuite instance."
831    #
832    # Does it raise an exception if the name resolves to an invalid
833    # object?
834    def test_loadTestsFromNames__relative_bad_object(self):
835        m = types.ModuleType('m')
836        m.testcase_1 = object()
837
838        loader = unittest.TestLoader()
839        try:
840            loader.loadTestsFromNames(['testcase_1'], m)
841        except TypeError:
842            pass
843        else:
844            self.fail("Should have raised TypeError")
845
846    # "The specifier name is a ``dotted name'' that may resolve ... to
847    # ... a test case class"
848    def test_loadTestsFromNames__relative_TestCase_subclass(self):
849        m = types.ModuleType('m')
850        class MyTestCase(unittest.TestCase):
851            def test(self):
852                pass
853        m.testcase_1 = MyTestCase
854
855        loader = unittest.TestLoader()
856        suite = loader.loadTestsFromNames(['testcase_1'], m)
857        self.assertIsInstance(suite, loader.suiteClass)
858
859        expected = loader.suiteClass([MyTestCase('test')])
860        self.assertEqual(list(suite), [expected])
861
862    # "The specifier name is a ``dotted name'' that may resolve ... to
863    # ... a TestSuite instance"
864    def test_loadTestsFromNames__relative_TestSuite(self):
865        m = types.ModuleType('m')
866        class MyTestCase(unittest.TestCase):
867            def test(self):
868                pass
869        m.testsuite = unittest.TestSuite([MyTestCase('test')])
870
871        loader = unittest.TestLoader()
872        suite = loader.loadTestsFromNames(['testsuite'], m)
873        self.assertIsInstance(suite, loader.suiteClass)
874
875        self.assertEqual(list(suite), [m.testsuite])
876
877    # "The specifier name is a ``dotted name'' that may resolve ... to ... a
878    # test method within a test case class"
879    def test_loadTestsFromNames__relative_testmethod(self):
880        m = types.ModuleType('m')
881        class MyTestCase(unittest.TestCase):
882            def test(self):
883                pass
884        m.testcase_1 = MyTestCase
885
886        loader = unittest.TestLoader()
887        suite = loader.loadTestsFromNames(['testcase_1.test'], m)
888        self.assertIsInstance(suite, loader.suiteClass)
889
890        ref_suite = unittest.TestSuite([MyTestCase('test')])
891        self.assertEqual(list(suite), [ref_suite])
892
893    # #14971: Make sure the dotted name resolution works even if the actual
894    # function doesn't have the same name as is used to find it.
895    def test_loadTestsFromName__function_with_different_name_than_method(self):
896        # lambdas have the name '<lambda>'.
897        m = types.ModuleType('m')
898        class MyTestCase(unittest.TestCase):
899            test = lambda: 1
900        m.testcase_1 = MyTestCase
901
902        loader = unittest.TestLoader()
903        suite = loader.loadTestsFromNames(['testcase_1.test'], m)
904        self.assertIsInstance(suite, loader.suiteClass)
905
906        ref_suite = unittest.TestSuite([MyTestCase('test')])
907        self.assertEqual(list(suite), [ref_suite])
908
909    # "The specifier name is a ``dotted name'' that may resolve ... to ... a
910    # test method within a test case class"
911    #
912    # Does the method gracefully handle names that initially look like they
913    # resolve to "a test method within a test case class" but don't?
914    def test_loadTestsFromNames__relative_invalid_testmethod(self):
915        m = types.ModuleType('m')
916        class MyTestCase(unittest.TestCase):
917            def test(self):
918                pass
919        m.testcase_1 = MyTestCase
920
921        loader = unittest.TestLoader()
922        suite = loader.loadTestsFromNames(['testcase_1.testfoo'], m)
923        error, test = self.check_deferred_error(loader, list(suite)[0])
924        expected = "type object 'MyTestCase' has no attribute 'testfoo'"
925        self.assertIn(
926            expected, error,
927            'missing error string in %r' % error)
928        self.assertRaisesRegex(AttributeError, expected, test.testfoo)
929
930    # "The specifier name is a ``dotted name'' that may resolve ... to
931    # ... a callable object which returns a ... TestSuite instance"
932    def test_loadTestsFromNames__callable__TestSuite(self):
933        m = types.ModuleType('m')
934        testcase_1 = unittest.FunctionTestCase(lambda: None)
935        testcase_2 = unittest.FunctionTestCase(lambda: None)
936        def return_TestSuite():
937            return unittest.TestSuite([testcase_1, testcase_2])
938        m.return_TestSuite = return_TestSuite
939
940        loader = unittest.TestLoader()
941        suite = loader.loadTestsFromNames(['return_TestSuite'], m)
942        self.assertIsInstance(suite, loader.suiteClass)
943
944        expected = unittest.TestSuite([testcase_1, testcase_2])
945        self.assertEqual(list(suite), [expected])
946
947    # "The specifier name is a ``dotted name'' that may resolve ... to
948    # ... a callable object which returns a TestCase ... instance"
949    def test_loadTestsFromNames__callable__TestCase_instance(self):
950        m = types.ModuleType('m')
951        testcase_1 = unittest.FunctionTestCase(lambda: None)
952        def return_TestCase():
953            return testcase_1
954        m.return_TestCase = return_TestCase
955
956        loader = unittest.TestLoader()
957        suite = loader.loadTestsFromNames(['return_TestCase'], m)
958        self.assertIsInstance(suite, loader.suiteClass)
959
960        ref_suite = unittest.TestSuite([testcase_1])
961        self.assertEqual(list(suite), [ref_suite])
962
963    # "The specifier name is a ``dotted name'' that may resolve ... to
964    # ... a callable object which returns a TestCase or TestSuite instance"
965    #
966    # Are staticmethods handled correctly?
967    def test_loadTestsFromNames__callable__call_staticmethod(self):
968        m = types.ModuleType('m')
969        class Test1(unittest.TestCase):
970            def test(self):
971                pass
972
973        testcase_1 = Test1('test')
974        class Foo(unittest.TestCase):
975            @staticmethod
976            def foo():
977                return testcase_1
978        m.Foo = Foo
979
980        loader = unittest.TestLoader()
981        suite = loader.loadTestsFromNames(['Foo.foo'], m)
982        self.assertIsInstance(suite, loader.suiteClass)
983
984        ref_suite = unittest.TestSuite([testcase_1])
985        self.assertEqual(list(suite), [ref_suite])
986
987    # "The specifier name is a ``dotted name'' that may resolve ... to
988    # ... a callable object which returns a TestCase or TestSuite instance"
989    #
990    # What happens when the callable returns something else?
991    def test_loadTestsFromNames__callable__wrong_type(self):
992        m = types.ModuleType('m')
993        def return_wrong():
994            return 6
995        m.return_wrong = return_wrong
996
997        loader = unittest.TestLoader()
998        try:
999            suite = loader.loadTestsFromNames(['return_wrong'], m)
1000        except TypeError:
1001            pass
1002        else:
1003            self.fail("TestLoader.loadTestsFromNames failed to raise TypeError")
1004
1005    # "The specifier can refer to modules and packages which have not been
1006    # imported; they will be imported as a side-effect"
1007    def test_loadTestsFromNames__module_not_loaded(self):
1008        # We're going to try to load this module as a side-effect, so it
1009        # better not be loaded before we try.
1010        #
1011        module_name = 'unittest.test.dummy'
1012        sys.modules.pop(module_name, None)
1013
1014        loader = unittest.TestLoader()
1015        try:
1016            suite = loader.loadTestsFromNames([module_name])
1017
1018            self.assertIsInstance(suite, loader.suiteClass)
1019            self.assertEqual(list(suite), [unittest.TestSuite()])
1020
1021            # module should now be loaded, thanks to loadTestsFromName()
1022            self.assertIn(module_name, sys.modules)
1023        finally:
1024            if module_name in sys.modules:
1025                del sys.modules[module_name]
1026
1027    ################################################################
1028    ### /Tests for TestLoader.loadTestsFromNames()
1029
1030    ### Tests for TestLoader.getTestCaseNames()
1031    ################################################################
1032
1033    # "Return a sorted sequence of method names found within testCaseClass"
1034    #
1035    # Test.foobar is defined to make sure getTestCaseNames() respects
1036    # loader.testMethodPrefix
1037    def test_getTestCaseNames(self):
1038        class Test(unittest.TestCase):
1039            def test_1(self): pass
1040            def test_2(self): pass
1041            def foobar(self): pass
1042
1043        loader = unittest.TestLoader()
1044
1045        self.assertEqual(loader.getTestCaseNames(Test), ['test_1', 'test_2'])
1046
1047    # "Return a sorted sequence of method names found within testCaseClass"
1048    #
1049    # Does getTestCaseNames() behave appropriately if no tests are found?
1050    def test_getTestCaseNames__no_tests(self):
1051        class Test(unittest.TestCase):
1052            def foobar(self): pass
1053
1054        loader = unittest.TestLoader()
1055
1056        self.assertEqual(loader.getTestCaseNames(Test), [])
1057
1058    # "Return a sorted sequence of method names found within testCaseClass"
1059    #
1060    # Are not-TestCases handled gracefully?
1061    #
1062    # XXX This should raise a TypeError, not return a list
1063    #
1064    # XXX It's too late in the 2.5 release cycle to fix this, but it should
1065    # probably be revisited for 2.6
1066    def test_getTestCaseNames__not_a_TestCase(self):
1067        class BadCase(int):
1068            def test_foo(self):
1069                pass
1070
1071        loader = unittest.TestLoader()
1072        names = loader.getTestCaseNames(BadCase)
1073
1074        self.assertEqual(names, ['test_foo'])
1075
1076    # "Return a sorted sequence of method names found within testCaseClass"
1077    #
1078    # Make sure inherited names are handled.
1079    #
1080    # TestP.foobar is defined to make sure getTestCaseNames() respects
1081    # loader.testMethodPrefix
1082    def test_getTestCaseNames__inheritance(self):
1083        class TestP(unittest.TestCase):
1084            def test_1(self): pass
1085            def test_2(self): pass
1086            def foobar(self): pass
1087
1088        class TestC(TestP):
1089            def test_1(self): pass
1090            def test_3(self): pass
1091
1092        loader = unittest.TestLoader()
1093
1094        names = ['test_1', 'test_2', 'test_3']
1095        self.assertEqual(loader.getTestCaseNames(TestC), names)
1096
1097    # "Return a sorted sequence of method names found within testCaseClass"
1098    #
1099    # If TestLoader.testNamePatterns is set, only tests that match one of these
1100    # patterns should be included.
1101    def test_getTestCaseNames__testNamePatterns(self):
1102        class MyTest(unittest.TestCase):
1103            def test_1(self): pass
1104            def test_2(self): pass
1105            def foobar(self): pass
1106
1107        loader = unittest.TestLoader()
1108
1109        loader.testNamePatterns = []
1110        self.assertEqual(loader.getTestCaseNames(MyTest), [])
1111
1112        loader.testNamePatterns = ['*1']
1113        self.assertEqual(loader.getTestCaseNames(MyTest), ['test_1'])
1114
1115        loader.testNamePatterns = ['*1', '*2']
1116        self.assertEqual(loader.getTestCaseNames(MyTest), ['test_1', 'test_2'])
1117
1118        loader.testNamePatterns = ['*My*']
1119        self.assertEqual(loader.getTestCaseNames(MyTest), ['test_1', 'test_2'])
1120
1121        loader.testNamePatterns = ['*my*']
1122        self.assertEqual(loader.getTestCaseNames(MyTest), [])
1123
1124    # "Return a sorted sequence of method names found within testCaseClass"
1125    #
1126    # If TestLoader.testNamePatterns is set, only tests that match one of these
1127    # patterns should be included.
1128    #
1129    # For backwards compatibility reasons (see bpo-32071), the check may only
1130    # touch a TestCase's attribute if it starts with the test method prefix.
1131    def test_getTestCaseNames__testNamePatterns__attribute_access_regression(self):
1132        class Trap:
1133            def __get__(*ignored):
1134                self.fail('Non-test attribute accessed')
1135
1136        class MyTest(unittest.TestCase):
1137            def test_1(self): pass
1138            foobar = Trap()
1139
1140        loader = unittest.TestLoader()
1141        self.assertEqual(loader.getTestCaseNames(MyTest), ['test_1'])
1142
1143        loader = unittest.TestLoader()
1144        loader.testNamePatterns = []
1145        self.assertEqual(loader.getTestCaseNames(MyTest), [])
1146
1147    ################################################################
1148    ### /Tests for TestLoader.getTestCaseNames()
1149
1150    ### Tests for TestLoader.testMethodPrefix
1151    ################################################################
1152
1153    # "String giving the prefix of method names which will be interpreted as
1154    # test methods"
1155    #
1156    # Implicit in the documentation is that testMethodPrefix is respected by
1157    # all loadTestsFrom* methods.
1158    def test_testMethodPrefix__loadTestsFromTestCase(self):
1159        class Foo(unittest.TestCase):
1160            def test_1(self): pass
1161            def test_2(self): pass
1162            def foo_bar(self): pass
1163
1164        tests_1 = unittest.TestSuite([Foo('foo_bar')])
1165        tests_2 = unittest.TestSuite([Foo('test_1'), Foo('test_2')])
1166
1167        loader = unittest.TestLoader()
1168        loader.testMethodPrefix = 'foo'
1169        self.assertEqual(loader.loadTestsFromTestCase(Foo), tests_1)
1170
1171        loader.testMethodPrefix = 'test'
1172        self.assertEqual(loader.loadTestsFromTestCase(Foo), tests_2)
1173
1174    # "String giving the prefix of method names which will be interpreted as
1175    # test methods"
1176    #
1177    # Implicit in the documentation is that testMethodPrefix is respected by
1178    # all loadTestsFrom* methods.
1179    def test_testMethodPrefix__loadTestsFromModule(self):
1180        m = types.ModuleType('m')
1181        class Foo(unittest.TestCase):
1182            def test_1(self): pass
1183            def test_2(self): pass
1184            def foo_bar(self): pass
1185        m.Foo = Foo
1186
1187        tests_1 = [unittest.TestSuite([Foo('foo_bar')])]
1188        tests_2 = [unittest.TestSuite([Foo('test_1'), Foo('test_2')])]
1189
1190        loader = unittest.TestLoader()
1191        loader.testMethodPrefix = 'foo'
1192        self.assertEqual(list(loader.loadTestsFromModule(m)), tests_1)
1193
1194        loader.testMethodPrefix = 'test'
1195        self.assertEqual(list(loader.loadTestsFromModule(m)), tests_2)
1196
1197    # "String giving the prefix of method names which will be interpreted as
1198    # test methods"
1199    #
1200    # Implicit in the documentation is that testMethodPrefix is respected by
1201    # all loadTestsFrom* methods.
1202    def test_testMethodPrefix__loadTestsFromName(self):
1203        m = types.ModuleType('m')
1204        class Foo(unittest.TestCase):
1205            def test_1(self): pass
1206            def test_2(self): pass
1207            def foo_bar(self): pass
1208        m.Foo = Foo
1209
1210        tests_1 = unittest.TestSuite([Foo('foo_bar')])
1211        tests_2 = unittest.TestSuite([Foo('test_1'), Foo('test_2')])
1212
1213        loader = unittest.TestLoader()
1214        loader.testMethodPrefix = 'foo'
1215        self.assertEqual(loader.loadTestsFromName('Foo', m), tests_1)
1216
1217        loader.testMethodPrefix = 'test'
1218        self.assertEqual(loader.loadTestsFromName('Foo', m), tests_2)
1219
1220    # "String giving the prefix of method names which will be interpreted as
1221    # test methods"
1222    #
1223    # Implicit in the documentation is that testMethodPrefix is respected by
1224    # all loadTestsFrom* methods.
1225    def test_testMethodPrefix__loadTestsFromNames(self):
1226        m = types.ModuleType('m')
1227        class Foo(unittest.TestCase):
1228            def test_1(self): pass
1229            def test_2(self): pass
1230            def foo_bar(self): pass
1231        m.Foo = Foo
1232
1233        tests_1 = unittest.TestSuite([unittest.TestSuite([Foo('foo_bar')])])
1234        tests_2 = unittest.TestSuite([Foo('test_1'), Foo('test_2')])
1235        tests_2 = unittest.TestSuite([tests_2])
1236
1237        loader = unittest.TestLoader()
1238        loader.testMethodPrefix = 'foo'
1239        self.assertEqual(loader.loadTestsFromNames(['Foo'], m), tests_1)
1240
1241        loader.testMethodPrefix = 'test'
1242        self.assertEqual(loader.loadTestsFromNames(['Foo'], m), tests_2)
1243
1244    # "The default value is 'test'"
1245    def test_testMethodPrefix__default_value(self):
1246        loader = unittest.TestLoader()
1247        self.assertEqual(loader.testMethodPrefix, 'test')
1248
1249    ################################################################
1250    ### /Tests for TestLoader.testMethodPrefix
1251
1252    ### Tests for TestLoader.sortTestMethodsUsing
1253    ################################################################
1254
1255    # "Function to be used to compare method names when sorting them in
1256    # getTestCaseNames() and all the loadTestsFromX() methods"
1257    def test_sortTestMethodsUsing__loadTestsFromTestCase(self):
1258        def reversed_cmp(x, y):
1259            return -((x > y) - (x < y))
1260
1261        class Foo(unittest.TestCase):
1262            def test_1(self): pass
1263            def test_2(self): pass
1264
1265        loader = unittest.TestLoader()
1266        loader.sortTestMethodsUsing = reversed_cmp
1267
1268        tests = loader.suiteClass([Foo('test_2'), Foo('test_1')])
1269        self.assertEqual(loader.loadTestsFromTestCase(Foo), tests)
1270
1271    # "Function to be used to compare method names when sorting them in
1272    # getTestCaseNames() and all the loadTestsFromX() methods"
1273    def test_sortTestMethodsUsing__loadTestsFromModule(self):
1274        def reversed_cmp(x, y):
1275            return -((x > y) - (x < y))
1276
1277        m = types.ModuleType('m')
1278        class Foo(unittest.TestCase):
1279            def test_1(self): pass
1280            def test_2(self): pass
1281        m.Foo = Foo
1282
1283        loader = unittest.TestLoader()
1284        loader.sortTestMethodsUsing = reversed_cmp
1285
1286        tests = [loader.suiteClass([Foo('test_2'), Foo('test_1')])]
1287        self.assertEqual(list(loader.loadTestsFromModule(m)), tests)
1288
1289    # "Function to be used to compare method names when sorting them in
1290    # getTestCaseNames() and all the loadTestsFromX() methods"
1291    def test_sortTestMethodsUsing__loadTestsFromName(self):
1292        def reversed_cmp(x, y):
1293            return -((x > y) - (x < y))
1294
1295        m = types.ModuleType('m')
1296        class Foo(unittest.TestCase):
1297            def test_1(self): pass
1298            def test_2(self): pass
1299        m.Foo = Foo
1300
1301        loader = unittest.TestLoader()
1302        loader.sortTestMethodsUsing = reversed_cmp
1303
1304        tests = loader.suiteClass([Foo('test_2'), Foo('test_1')])
1305        self.assertEqual(loader.loadTestsFromName('Foo', m), tests)
1306
1307    # "Function to be used to compare method names when sorting them in
1308    # getTestCaseNames() and all the loadTestsFromX() methods"
1309    def test_sortTestMethodsUsing__loadTestsFromNames(self):
1310        def reversed_cmp(x, y):
1311            return -((x > y) - (x < y))
1312
1313        m = types.ModuleType('m')
1314        class Foo(unittest.TestCase):
1315            def test_1(self): pass
1316            def test_2(self): pass
1317        m.Foo = Foo
1318
1319        loader = unittest.TestLoader()
1320        loader.sortTestMethodsUsing = reversed_cmp
1321
1322        tests = [loader.suiteClass([Foo('test_2'), Foo('test_1')])]
1323        self.assertEqual(list(loader.loadTestsFromNames(['Foo'], m)), tests)
1324
1325    # "Function to be used to compare method names when sorting them in
1326    # getTestCaseNames()"
1327    #
1328    # Does it actually affect getTestCaseNames()?
1329    def test_sortTestMethodsUsing__getTestCaseNames(self):
1330        def reversed_cmp(x, y):
1331            return -((x > y) - (x < y))
1332
1333        class Foo(unittest.TestCase):
1334            def test_1(self): pass
1335            def test_2(self): pass
1336
1337        loader = unittest.TestLoader()
1338        loader.sortTestMethodsUsing = reversed_cmp
1339
1340        test_names = ['test_2', 'test_1']
1341        self.assertEqual(loader.getTestCaseNames(Foo), test_names)
1342
1343    # "The default value is the built-in cmp() function"
1344    # Since cmp is now defunct, we simply verify that the results
1345    # occur in the same order as they would with the default sort.
1346    def test_sortTestMethodsUsing__default_value(self):
1347        loader = unittest.TestLoader()
1348
1349        class Foo(unittest.TestCase):
1350            def test_2(self): pass
1351            def test_3(self): pass
1352            def test_1(self): pass
1353
1354        test_names = ['test_2', 'test_3', 'test_1']
1355        self.assertEqual(loader.getTestCaseNames(Foo), sorted(test_names))
1356
1357
1358    # "it can be set to None to disable the sort."
1359    #
1360    # XXX How is this different from reassigning cmp? Are the tests returned
1361    # in a random order or something? This behaviour should die
1362    def test_sortTestMethodsUsing__None(self):
1363        class Foo(unittest.TestCase):
1364            def test_1(self): pass
1365            def test_2(self): pass
1366
1367        loader = unittest.TestLoader()
1368        loader.sortTestMethodsUsing = None
1369
1370        test_names = ['test_2', 'test_1']
1371        self.assertEqual(set(loader.getTestCaseNames(Foo)), set(test_names))
1372
1373    ################################################################
1374    ### /Tests for TestLoader.sortTestMethodsUsing
1375
1376    ### Tests for TestLoader.suiteClass
1377    ################################################################
1378
1379    # "Callable object that constructs a test suite from a list of tests."
1380    def test_suiteClass__loadTestsFromTestCase(self):
1381        class Foo(unittest.TestCase):
1382            def test_1(self): pass
1383            def test_2(self): pass
1384            def foo_bar(self): pass
1385
1386        tests = [Foo('test_1'), Foo('test_2')]
1387
1388        loader = unittest.TestLoader()
1389        loader.suiteClass = list
1390        self.assertEqual(loader.loadTestsFromTestCase(Foo), tests)
1391
1392    # It is implicit in the documentation for TestLoader.suiteClass that
1393    # all TestLoader.loadTestsFrom* methods respect it. Let's make sure
1394    def test_suiteClass__loadTestsFromModule(self):
1395        m = types.ModuleType('m')
1396        class Foo(unittest.TestCase):
1397            def test_1(self): pass
1398            def test_2(self): pass
1399            def foo_bar(self): pass
1400        m.Foo = Foo
1401
1402        tests = [[Foo('test_1'), Foo('test_2')]]
1403
1404        loader = unittest.TestLoader()
1405        loader.suiteClass = list
1406        self.assertEqual(loader.loadTestsFromModule(m), tests)
1407
1408    # It is implicit in the documentation for TestLoader.suiteClass that
1409    # all TestLoader.loadTestsFrom* methods respect it. Let's make sure
1410    def test_suiteClass__loadTestsFromName(self):
1411        m = types.ModuleType('m')
1412        class Foo(unittest.TestCase):
1413            def test_1(self): pass
1414            def test_2(self): pass
1415            def foo_bar(self): pass
1416        m.Foo = Foo
1417
1418        tests = [Foo('test_1'), Foo('test_2')]
1419
1420        loader = unittest.TestLoader()
1421        loader.suiteClass = list
1422        self.assertEqual(loader.loadTestsFromName('Foo', m), tests)
1423
1424    # It is implicit in the documentation for TestLoader.suiteClass that
1425    # all TestLoader.loadTestsFrom* methods respect it. Let's make sure
1426    def test_suiteClass__loadTestsFromNames(self):
1427        m = types.ModuleType('m')
1428        class Foo(unittest.TestCase):
1429            def test_1(self): pass
1430            def test_2(self): pass
1431            def foo_bar(self): pass
1432        m.Foo = Foo
1433
1434        tests = [[Foo('test_1'), Foo('test_2')]]
1435
1436        loader = unittest.TestLoader()
1437        loader.suiteClass = list
1438        self.assertEqual(loader.loadTestsFromNames(['Foo'], m), tests)
1439
1440    # "The default value is the TestSuite class"
1441    def test_suiteClass__default_value(self):
1442        loader = unittest.TestLoader()
1443        self.assertIs(loader.suiteClass, unittest.TestSuite)
1444
1445
1446    def test_partial_functions(self):
1447        def noop(arg):
1448            pass
1449
1450        class Foo(unittest.TestCase):
1451            pass
1452
1453        setattr(Foo, 'test_partial', functools.partial(noop, None))
1454
1455        loader = unittest.TestLoader()
1456
1457        test_names = ['test_partial']
1458        self.assertEqual(loader.getTestCaseNames(Foo), test_names)
1459
1460
1461class TestObsoleteFunctions(unittest.TestCase):
1462    class MyTestSuite(unittest.TestSuite):
1463        pass
1464
1465    class MyTestCase(unittest.TestCase):
1466        def check_1(self): pass
1467        def check_2(self): pass
1468        def test(self): pass
1469
1470    @staticmethod
1471    def reverse_three_way_cmp(a, b):
1472        return unittest.util.three_way_cmp(b, a)
1473
1474    def test_getTestCaseNames(self):
1475        with self.assertWarns(DeprecationWarning) as w:
1476            tests = unittest.getTestCaseNames(self.MyTestCase,
1477                prefix='check', sortUsing=self.reverse_three_way_cmp,
1478                testNamePatterns=None)
1479        self.assertEqual(w.warnings[0].filename, __file__)
1480        self.assertEqual(tests, ['check_2', 'check_1'])
1481
1482    def test_makeSuite(self):
1483        with self.assertWarns(DeprecationWarning) as w:
1484            suite = unittest.makeSuite(self.MyTestCase,
1485                    prefix='check', sortUsing=self.reverse_three_way_cmp,
1486                    suiteClass=self.MyTestSuite)
1487        self.assertEqual(w.warnings[0].filename, __file__)
1488        self.assertIsInstance(suite, self.MyTestSuite)
1489        expected = self.MyTestSuite([self.MyTestCase('check_2'),
1490                                     self.MyTestCase('check_1')])
1491        self.assertEqual(suite, expected)
1492
1493    def test_findTestCases(self):
1494        m = types.ModuleType('m')
1495        m.testcase_1 = self.MyTestCase
1496
1497        with self.assertWarns(DeprecationWarning) as w:
1498            suite = unittest.findTestCases(m,
1499                prefix='check', sortUsing=self.reverse_three_way_cmp,
1500                suiteClass=self.MyTestSuite)
1501        self.assertEqual(w.warnings[0].filename, __file__)
1502        self.assertIsInstance(suite, self.MyTestSuite)
1503        expected = [self.MyTestSuite([self.MyTestCase('check_2'),
1504                                      self.MyTestCase('check_1')])]
1505        self.assertEqual(list(suite), expected)
1506
1507
1508if __name__ == "__main__":
1509    unittest.main()
1510