xmlunit.py 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. # -*- coding: utf-8 -*-
  2. """
  3. :codeauthor: Pedro Algarvio (pedro@algarvio.me)
  4. :copyright: Copyright 2014 by the SaltStack Team, see AUTHORS for more details.
  5. :license: Apache 2.0, see LICENSE for more details.
  6. tests.support.xmlunit
  7. ~~~~~~~~~~~~~~~~~~~
  8. XML Unit Tests
  9. """
  10. # pylint: disable=wrong-import-order,wrong-import-position
  11. # Import python libs
  12. from __future__ import absolute_import
  13. import io
  14. import logging
  15. import os
  16. from tests.support.runtests import RUNTIME_VARS
  17. log = logging.getLogger(__name__)
  18. try:
  19. import xmlrunner.runner
  20. import xmlrunner.result
  21. HAS_XMLRUNNER = True
  22. class _DuplicateWriter(io.TextIOBase):
  23. """
  24. Duplicate output from the first handle to the second handle
  25. The second handle is expected to be a StringIO and not to block.
  26. """
  27. def __init__(self, first, second):
  28. super(_DuplicateWriter, self).__init__()
  29. self._first = first
  30. self._second = second
  31. def flush(self):
  32. self._first.flush()
  33. self._second.flush()
  34. def writable(self):
  35. return True
  36. def writelines(self, lines):
  37. self._first.writelines(lines)
  38. self._second.writelines(lines)
  39. def write(self, b):
  40. if isinstance(self._first, io.TextIOBase):
  41. wrote = self._first.write(b)
  42. if wrote is not None:
  43. # expected to always succeed to write
  44. self._second.write(b[:wrote])
  45. return wrote
  46. else:
  47. # file-like object in Python2
  48. # It doesn't return wrote bytes.
  49. self._first.write(b)
  50. self._second.write(b)
  51. return len(b)
  52. def fileno(self):
  53. return self._first.fileno()
  54. xmlrunner.result._DuplicateWriter = _DuplicateWriter
  55. class _XMLTestResult(xmlrunner.result._XMLTestResult):
  56. def startTest(self, test):
  57. log.debug(">>>>> START >>>>> %s", test.id())
  58. # xmlrunner classes are NOT new-style classes
  59. xmlrunner.result._XMLTestResult.startTest(self, test)
  60. def stopTest(self, test):
  61. log.debug("<<<<< END <<<<<<< %s", test.id())
  62. # xmlrunner classes are NOT new-style classes
  63. return xmlrunner.result._XMLTestResult.stopTest(self, test)
  64. class XMLTestRunner(xmlrunner.runner.XMLTestRunner):
  65. def _make_result(self):
  66. return _XMLTestResult(
  67. self.stream, self.descriptions, self.verbosity, self.elapsed_times
  68. )
  69. def run(self, test):
  70. try:
  71. current_cwd = os.getcwd()
  72. if current_cwd != RUNTIME_VARS.CODE_DIR:
  73. log.critical(
  74. "CWD is not %s when running test %s",
  75. RUNTIME_VARS.CODE_DIR,
  76. test,
  77. )
  78. os.chdir(RUNTIME_VARS.CODE_DIR)
  79. except FileNotFoundError:
  80. log.critical("UNABLE TO GET CWD before running test: %s", test)
  81. os.chdir(RUNTIME_VARS.CODE_DIR)
  82. try:
  83. result = xmlrunner.runner.XMLTestRunner.run(self, test)
  84. except FileNotFoundError:
  85. log.critical(
  86. "FileNotFoundError was caught when running test: %s",
  87. test,
  88. exc_info=True,
  89. )
  90. raise
  91. self.stream.writeln("Finished generating XML reports")
  92. return result
  93. except ImportError:
  94. HAS_XMLRUNNER = False
  95. class XMLTestRunner(object):
  96. """
  97. This is a dumb class just so we don't break projects at import time
  98. """