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