commands.py 6.2 KB

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