[3] | 1 | """ |
---|
| 2 | nosetests setuptools command |
---|
| 3 | ---------------------------- |
---|
| 4 | |
---|
| 5 | The easiest way to run tests with nose is to use the `nosetests` setuptools |
---|
| 6 | command:: |
---|
| 7 | |
---|
| 8 | python setup.py nosetests |
---|
| 9 | |
---|
| 10 | This command has one *major* benefit over the standard `test` command: *all |
---|
| 11 | nose plugins are supported*. |
---|
| 12 | |
---|
| 13 | To configure the `nosetests` command, add a [nosetests] section to your |
---|
| 14 | setup.cfg. The [nosetests] section can contain any command line arguments that |
---|
| 15 | nosetests supports. The differences between issuing an option on the command |
---|
| 16 | line and adding it to setup.cfg are: |
---|
| 17 | |
---|
| 18 | * In setup.cfg, the -- prefix must be excluded |
---|
| 19 | * In setup.cfg, command line flags that take no arguments must be given an |
---|
| 20 | argument flag (1, T or TRUE for active, 0, F or FALSE for inactive) |
---|
| 21 | |
---|
| 22 | Here's an example [nosetests] setup.cfg section:: |
---|
| 23 | |
---|
| 24 | [nosetests] |
---|
| 25 | verbosity=1 |
---|
| 26 | detailed-errors=1 |
---|
| 27 | with-coverage=1 |
---|
| 28 | cover-package=nose |
---|
| 29 | debug=nose.loader |
---|
| 30 | pdb=1 |
---|
| 31 | pdb-failures=1 |
---|
| 32 | |
---|
| 33 | If you commonly run nosetests with a large number of options, using |
---|
| 34 | the nosetests setuptools command and configuring with setup.cfg can |
---|
| 35 | make running your tests much less tedious. (Note that the same options |
---|
| 36 | and format supported in setup.cfg are supported in all other config |
---|
| 37 | files, and the nosetests script will also load config files.) |
---|
| 38 | |
---|
| 39 | Another reason to run tests with the command is that the command will |
---|
| 40 | install packages listed in your `tests_require`, as well as doing a |
---|
| 41 | complete build of your package before running tests. For packages with |
---|
| 42 | dependencies or that build C extensions, using the setuptools command |
---|
| 43 | can be more convenient than building by hand and running the nosetests |
---|
| 44 | script. |
---|
| 45 | |
---|
| 46 | Bootstrapping |
---|
| 47 | ------------- |
---|
| 48 | |
---|
| 49 | If you are distributing your project and want users to be able to run tests |
---|
| 50 | without having to install nose themselves, add nose to the setup_requires |
---|
| 51 | section of your setup():: |
---|
| 52 | |
---|
| 53 | setup( |
---|
| 54 | # ... |
---|
| 55 | setup_requires=['nose>=0.11'] |
---|
| 56 | ) |
---|
| 57 | |
---|
| 58 | This will direct setuptools to download and activate nose during the setup |
---|
| 59 | process, making the ``nosetests`` command available. |
---|
| 60 | |
---|
| 61 | """ |
---|
| 62 | try: |
---|
| 63 | from setuptools import Command |
---|
| 64 | except ImportError: |
---|
| 65 | Command = nosetests = None |
---|
| 66 | else: |
---|
| 67 | from nose.config import Config, option_blacklist, user_config_files, \ |
---|
| 68 | flag, _bool |
---|
| 69 | from nose.core import TestProgram |
---|
| 70 | from nose.plugins import DefaultPluginManager |
---|
| 71 | |
---|
| 72 | |
---|
| 73 | def get_user_options(parser): |
---|
| 74 | """convert a optparse option list into a distutils option tuple list""" |
---|
| 75 | opt_list = [] |
---|
| 76 | for opt in parser.option_list: |
---|
| 77 | if opt._long_opts[0][2:] in option_blacklist: |
---|
| 78 | continue |
---|
| 79 | long_name = opt._long_opts[0][2:] |
---|
| 80 | if opt.action not in ('store_true', 'store_false'): |
---|
| 81 | long_name = long_name + "=" |
---|
| 82 | short_name = None |
---|
| 83 | if opt._short_opts: |
---|
| 84 | short_name = opt._short_opts[0][1:] |
---|
| 85 | opt_list.append((long_name, short_name, opt.help or "")) |
---|
| 86 | return opt_list |
---|
| 87 | |
---|
| 88 | |
---|
| 89 | class nosetests(Command): |
---|
| 90 | description = "Run unit tests using nosetests" |
---|
| 91 | __config = Config(files=user_config_files(), |
---|
| 92 | plugins=DefaultPluginManager()) |
---|
| 93 | __parser = __config.getParser() |
---|
| 94 | user_options = get_user_options(__parser) |
---|
| 95 | |
---|
| 96 | def initialize_options(self): |
---|
| 97 | """create the member variables, but change hyphens to |
---|
| 98 | underscores |
---|
| 99 | """ |
---|
| 100 | |
---|
| 101 | self.option_to_cmds = {} |
---|
| 102 | for opt in self.__parser.option_list: |
---|
| 103 | cmd_name = opt._long_opts[0][2:] |
---|
| 104 | option_name = cmd_name.replace('-', '_') |
---|
| 105 | self.option_to_cmds[option_name] = cmd_name |
---|
| 106 | setattr(self, option_name, None) |
---|
| 107 | self.attr = None |
---|
| 108 | |
---|
| 109 | def finalize_options(self): |
---|
| 110 | """nothing to do here""" |
---|
| 111 | pass |
---|
| 112 | |
---|
| 113 | def run(self): |
---|
| 114 | """ensure tests are capable of being run, then |
---|
| 115 | run nose.main with a reconstructed argument list""" |
---|
| 116 | self.run_command('egg_info') |
---|
| 117 | |
---|
| 118 | # Build extensions in-place |
---|
| 119 | self.reinitialize_command('build_ext', inplace=1) |
---|
| 120 | self.run_command('build_ext') |
---|
| 121 | |
---|
| 122 | if self.distribution.install_requires: |
---|
| 123 | self.distribution.fetch_build_eggs( |
---|
| 124 | self.distribution.install_requires) |
---|
| 125 | if self.distribution.tests_require: |
---|
| 126 | self.distribution.fetch_build_eggs( |
---|
| 127 | self.distribution.tests_require) |
---|
| 128 | |
---|
| 129 | argv = ['nosetests'] |
---|
| 130 | for (option_name, cmd_name) in self.option_to_cmds.items(): |
---|
| 131 | if option_name in option_blacklist: |
---|
| 132 | continue |
---|
| 133 | value = getattr(self, option_name) |
---|
| 134 | if value is not None: |
---|
| 135 | argv.extend( |
---|
| 136 | self.cfgToArg(option_name.replace('_', '-'), value)) |
---|
| 137 | TestProgram(argv=argv, config=self.__config) |
---|
| 138 | |
---|
| 139 | def cfgToArg(self, optname, value): |
---|
| 140 | argv = [] |
---|
| 141 | if flag(value): |
---|
| 142 | if _bool(value): |
---|
| 143 | argv.append('--' + optname) |
---|
| 144 | else: |
---|
| 145 | argv.extend(['--' + optname, value]) |
---|
| 146 | return argv |
---|