Python Build Reasonableness
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

testr_command.py 5.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. # Copyright (c) 2013 Hewlett-Packard Development Company, L.P.
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
  12. # implied.
  13. # See the License for the specific language governing permissions and
  14. # limitations under the License.
  15. #
  16. # Copyright (c) 2013 Testrepository Contributors
  17. #
  18. # Licensed under either the Apache License, Version 2.0 or the BSD 3-clause
  19. # license at the users choice. A copy of both licenses are available in the
  20. # project source as Apache-2.0 and BSD. You may not use this file except in
  21. # compliance with one of these two licences.
  22. #
  23. # Unless required by applicable law or agreed to in writing, software
  24. # distributed under these licenses is distributed on an "AS IS" BASIS, WITHOUT
  25. # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  26. # license you chose for the specific language governing permissions and
  27. # limitations under that license.
  28. """setuptools/distutils command to run testr via setup.py
  29. PBR will hook in the Testr class to provide "setup.py test" when
  30. .testr.conf is present in the repository (see pbr/hooks/commands.py).
  31. If we are activated but testrepository is not installed, we provide a
  32. sensible error.
  33. You can pass --coverage which will also export PYTHON='coverage run
  34. --source <your package>' and automatically combine the coverage from
  35. each testr backend test runner after the run completes.
  36. """
  37. from distutils import cmd
  38. import distutils.errors
  39. import logging
  40. import os
  41. import sys
  42. import warnings
  43. logger = logging.getLogger(__name__)
  44. class TestrReal(cmd.Command):
  45. description = "DEPRECATED: Run unit tests using testr"
  46. user_options = [
  47. ('coverage', None, "Replace PYTHON with coverage and merge coverage "
  48. "from each testr worker."),
  49. ('testr-args=', 't', "Run 'testr' with these args"),
  50. ('omit=', 'o', "Files to omit from coverage calculations"),
  51. ('coverage-package-name=', None, "Use this name to select packages "
  52. "for coverage (one or more, "
  53. "comma-separated)"),
  54. ('slowest', None, "Show slowest test times after tests complete."),
  55. ('no-parallel', None, "Run testr serially"),
  56. ('log-level=', 'l', "Log level (default: info)"),
  57. ]
  58. boolean_options = ['coverage', 'slowest', 'no_parallel']
  59. def _run_testr(self, *args):
  60. logger.debug("_run_testr called with args = %r", args)
  61. return commands.run_argv([sys.argv[0]] + list(args),
  62. sys.stdin, sys.stdout, sys.stderr)
  63. def initialize_options(self):
  64. self.testr_args = None
  65. self.coverage = None
  66. self.omit = ""
  67. self.slowest = None
  68. self.coverage_package_name = None
  69. self.no_parallel = None
  70. self.log_level = 'info'
  71. def finalize_options(self):
  72. self.log_level = getattr(
  73. logging,
  74. self.log_level.upper(),
  75. logging.INFO)
  76. logging.basicConfig(level=self.log_level)
  77. logger.debug("finalize_options called")
  78. if self.testr_args is None:
  79. self.testr_args = []
  80. else:
  81. self.testr_args = self.testr_args.split()
  82. if self.omit:
  83. self.omit = "--omit=%s" % self.omit
  84. logger.debug("finalize_options: self.__dict__ = %r", self.__dict__)
  85. def run(self):
  86. """Set up testr repo, then run testr."""
  87. logger.debug("run called")
  88. warnings.warn('testr integration in pbr is deprecated. Please use '
  89. 'the \'testr\' setup command or call testr directly',
  90. DeprecationWarning)
  91. if not os.path.isdir(".testrepository"):
  92. self._run_testr("init")
  93. if self.coverage:
  94. self._coverage_before()
  95. if not self.no_parallel:
  96. testr_ret = self._run_testr("run", "--parallel", *self.testr_args)
  97. else:
  98. testr_ret = self._run_testr("run", *self.testr_args)
  99. if testr_ret:
  100. raise distutils.errors.DistutilsError(
  101. "testr failed (%d)" % testr_ret)
  102. if self.slowest:
  103. print("Slowest Tests")
  104. self._run_testr("slowest")
  105. if self.coverage:
  106. self._coverage_after()
  107. def _coverage_before(self):
  108. logger.debug("_coverage_before called")
  109. package = self.distribution.get_name()
  110. if package.startswith('python-'):
  111. package = package[7:]
  112. # Use this as coverage package name
  113. if self.coverage_package_name:
  114. package = self.coverage_package_name
  115. options = "--source %s --parallel-mode" % package
  116. os.environ['PYTHON'] = ("coverage run %s" % options)
  117. logger.debug("os.environ['PYTHON'] = %r", os.environ['PYTHON'])
  118. def _coverage_after(self):
  119. logger.debug("_coverage_after called")
  120. os.system("coverage combine")
  121. os.system("coverage html -d ./cover %s" % self.omit)
  122. os.system("coverage xml -o ./cover/coverage.xml %s" % self.omit)
  123. class TestrFake(cmd.Command):
  124. description = "Run unit tests using testr"
  125. user_options = []
  126. def initialize_options(self):
  127. pass
  128. def finalize_options(self):
  129. pass
  130. def run(self):
  131. print("Install testrepository to run 'testr' command properly.")
  132. try:
  133. from testrepository import commands
  134. have_testr = True
  135. Testr = TestrReal
  136. except ImportError:
  137. have_testr = False
  138. Testr = TestrFake