| 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 | |
|---|