1 | """ |
---|
2 | This plugin bypasses the actual execution of tests, and instead just collects |
---|
3 | test names. Fixtures are also bypassed, so running nosetests with the |
---|
4 | collection plugin enabled should be very quick. |
---|
5 | |
---|
6 | This plugin is useful in combination with the testid plugin (``--with-id``). |
---|
7 | Run both together to get an indexed list of all tests, which will enable you to |
---|
8 | run individual tests by index number. |
---|
9 | |
---|
10 | This plugin is also useful for counting tests in a test suite, and making |
---|
11 | people watching your demo think all of your tests pass. |
---|
12 | """ |
---|
13 | from nose.plugins.base import Plugin |
---|
14 | from nose.case import Test |
---|
15 | import logging |
---|
16 | import unittest |
---|
17 | |
---|
18 | log = logging.getLogger(__name__) |
---|
19 | |
---|
20 | |
---|
21 | class CollectOnly(Plugin): |
---|
22 | """ |
---|
23 | Collect and output test names only, don't run any tests. |
---|
24 | """ |
---|
25 | name = "collect-only" |
---|
26 | enableOpt = 'collect_only' |
---|
27 | |
---|
28 | def options(self, parser, env): |
---|
29 | """Register commandline options. |
---|
30 | """ |
---|
31 | parser.add_option('--collect-only', |
---|
32 | action='store_true', |
---|
33 | dest=self.enableOpt, |
---|
34 | default=env.get('NOSE_COLLECT_ONLY'), |
---|
35 | help="Enable collect-only: %s [COLLECT_ONLY]" % |
---|
36 | (self.help())) |
---|
37 | |
---|
38 | def prepareTestLoader(self, loader): |
---|
39 | """Install collect-only suite class in TestLoader. |
---|
40 | """ |
---|
41 | # Disable context awareness |
---|
42 | log.debug("Preparing test loader") |
---|
43 | loader.suiteClass = TestSuiteFactory(self.conf) |
---|
44 | |
---|
45 | def prepareTestCase(self, test): |
---|
46 | """Replace actual test with dummy that always passes. |
---|
47 | """ |
---|
48 | # Return something that always passes |
---|
49 | log.debug("Preparing test case %s", test) |
---|
50 | if not isinstance(test, Test): |
---|
51 | return |
---|
52 | def run(result): |
---|
53 | # We need to make these plugin calls because there won't be |
---|
54 | # a result proxy, due to using a stripped-down test suite |
---|
55 | self.conf.plugins.startTest(test) |
---|
56 | result.startTest(test) |
---|
57 | self.conf.plugins.addSuccess(test) |
---|
58 | result.addSuccess(test) |
---|
59 | self.conf.plugins.stopTest(test) |
---|
60 | result.stopTest(test) |
---|
61 | return run |
---|
62 | |
---|
63 | |
---|
64 | class TestSuiteFactory: |
---|
65 | """ |
---|
66 | Factory for producing configured test suites. |
---|
67 | """ |
---|
68 | def __init__(self, conf): |
---|
69 | self.conf = conf |
---|
70 | |
---|
71 | def __call__(self, tests=(), **kw): |
---|
72 | return TestSuite(tests, conf=self.conf) |
---|
73 | |
---|
74 | |
---|
75 | class TestSuite(unittest.TestSuite): |
---|
76 | """ |
---|
77 | Basic test suite that bypasses most proxy and plugin calls, but does |
---|
78 | wrap tests in a nose.case.Test so prepareTestCase will be called. |
---|
79 | """ |
---|
80 | def __init__(self, tests=(), conf=None): |
---|
81 | self.conf = conf |
---|
82 | # Exec lazy suites: makes discovery depth-first |
---|
83 | if callable(tests): |
---|
84 | tests = tests() |
---|
85 | log.debug("TestSuite(%r)", tests) |
---|
86 | unittest.TestSuite.__init__(self, tests) |
---|
87 | |
---|
88 | def addTest(self, test): |
---|
89 | log.debug("Add test %s", test) |
---|
90 | if isinstance(test, unittest.TestSuite): |
---|
91 | self._tests.append(test) |
---|
92 | else: |
---|
93 | self._tests.append(Test(test, config=self.conf)) |
---|
94 | |
---|