Imported Upstream version 1.1.2
[platform/upstream/python-nose.git] / doc / doc_tests / test_selector_plugin / selector_plugin.rst
1 Using a Custom Selector
2 -----------------------
3
4 By default, nose uses a `nose.selector.Selector` instance to decide
5 what is and is not a test. The default selector is fairly simple: for
6 the most part, if an object's name matches the ``testMatch`` regular
7 expression defined in the active `nose.config.Config` instance, the
8 object is selected as a test. 
9
10 This behavior is fine for new projects, but may be undesireable for
11 older projects with a different test naming scheme. Fortunately, you
12 can easily override this behavior by providing a custom selector using
13 a plugin.
14
15     >>> import os
16     >>> support = os.path.join(os.path.dirname(__file__), 'support')
17
18 In this example, the project to be tested consists of a module and
19 package and associated tests, laid out like this::
20
21     >>> from nose.util import ls_tree
22     >>> print ls_tree(support)
23     |-- mymodule.py
24     |-- mypackage
25     |   |-- __init__.py
26     |   |-- strings.py
27     |   `-- math
28     |       |-- __init__.py
29     |       `-- basic.py
30     `-- tests
31         |-- testlib.py
32         |-- math
33         |   `-- basic.py
34         |-- mymodule
35         |   `-- my_function.py
36         `-- strings
37             `-- cat.py
38
39 Because the test modules do not include ``test`` in their names,
40 nose's default selector is unable to discover this project's tests.
41
42 .. Note ::
43
44    The run() function in :mod:`nose.plugins.plugintest` reformats test result
45    output to remove timings, which will vary from run to run, and
46    redirects the output to stdout.
47
48     >>> from nose.plugins.plugintest import run_buffered as run
49
50 ..
51
52     >>> argv = [__file__, '-v', support]
53     >>> run(argv=argv)
54     ----------------------------------------------------------------------
55     Ran 0 tests in ...s
56     <BLANKLINE>
57     OK
58
59 The tests for the example project follow a few basic conventions:
60
61 * The are all located under the tests/ directory.
62 * Test modules are organized into groups under directories named for
63   the module or package they test.
64 * testlib is *not* a test module, but it must be importable by the
65   test modules.
66 * Test modules contain unitest.TestCase classes that are tests, and
67   may contain other functions or classes that are NOT tests, no matter
68   how they are named.
69
70 We can codify those conventions in a selector class.
71
72     >>> from nose.selector import Selector
73     >>> import unittest
74     >>> class MySelector(Selector):
75     ...     def wantDirectory(self, dirname):
76     ...         # we want the tests directory and all directories
77     ...         # beneath it, and no others
78     ...         parts = dirname.split(os.path.sep)
79     ...         return 'tests' in parts
80     ...     def wantFile(self, filename):
81     ...         # we want python modules under tests/, except testlib
82     ...         parts = filename.split(os.path.sep)
83     ...         base, ext = os.path.splitext(parts[-1])
84     ...         return 'tests' in parts and ext == '.py' and base != 'testlib'
85     ...     def wantModule(self, module):
86     ...         # wantDirectory and wantFile above will ensure that
87     ...         # we never see an unwanted module
88     ...         return True
89     ...     def wantFunction(self, function):
90     ...         # never collect functions
91     ...         return False
92     ...     def wantClass(self, cls):
93     ...         # only collect TestCase subclasses
94     ...         return issubclass(cls, unittest.TestCase)
95
96 To use our selector class, we need a plugin that can inject it into
97 the test loader.
98
99     >>> from nose.plugins import Plugin
100     >>> class UseMySelector(Plugin):
101     ...     enabled = True
102     ...     def configure(self, options, conf):
103     ...         pass # always on
104     ...     def prepareTestLoader(self, loader):
105     ...         loader.selector = MySelector(loader.config)
106
107 Now we can execute a test run using the custom selector, and the
108 project's tests will be collected.
109
110     >>> run(argv=argv, plugins=[UseMySelector()])
111     test_add (basic.TestBasicMath) ... ok
112     test_sub (basic.TestBasicMath) ... ok
113     test_tuple_groups (my_function.MyFunction) ... ok
114     test_cat (cat.StringsCat) ... ok
115     <BLANKLINE>
116     ----------------------------------------------------------------------
117     Ran 4 tests in ...s
118     <BLANKLINE>
119     OK