JUnitConverter.php 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. <?php
  2. namespace Drupal\Core\Test;
  3. /**
  4. * Converts JUnit XML to Drupal's {simpletest} schema.
  5. *
  6. * This is mainly for converting PHPUnit test results.
  7. *
  8. * This class is @internal and not considered to be API.
  9. */
  10. class JUnitConverter {
  11. /**
  12. * Converts PHPUnit's JUnit XML output file to {simpletest} schema.
  13. *
  14. * @param int $test_id
  15. * The current test ID.
  16. * @param string $phpunit_xml_file
  17. * Path to the PHPUnit XML file.
  18. *
  19. * @return array[]
  20. * The results as array of rows in a format that can be inserted into the
  21. * {simpletest} table of the results database.
  22. *
  23. * @internal
  24. */
  25. public static function xmlToRows($test_id, $phpunit_xml_file) {
  26. $contents = @file_get_contents($phpunit_xml_file);
  27. if (!$contents) {
  28. return [];
  29. }
  30. return static::xmlElementToRows($test_id, new \SimpleXMLElement($contents));
  31. }
  32. /**
  33. * Parse test cases from XML to {simpletest} schema.
  34. *
  35. * @param int $test_id
  36. * The current test ID.
  37. * @param \SimpleXMLElement $element
  38. * The XML data from the JUnit file.
  39. *
  40. * @return array[]
  41. * The results as array of rows in a format that can be inserted into the
  42. * {simpletest} table of the results database.
  43. *
  44. * @internal
  45. */
  46. public static function xmlElementToRows($test_id, \SimpleXMLElement $element) {
  47. $records = [];
  48. $test_cases = static::findTestCases($element);
  49. foreach ($test_cases as $test_case) {
  50. $records[] = static::convertTestCaseToSimpletestRow($test_id, $test_case);
  51. }
  52. return $records;
  53. }
  54. /**
  55. * Finds all test cases recursively from a test suite list.
  56. *
  57. * @param \SimpleXMLElement $element
  58. * The PHPUnit xml to search for test cases.
  59. * @param \SimpleXMLElement $parent
  60. * (Optional) The parent of the current element. Defaults to NULL.
  61. *
  62. * @return array
  63. * A list of all test cases.
  64. *
  65. * @internal
  66. */
  67. public static function findTestCases(\SimpleXMLElement $element, \SimpleXMLElement $parent = NULL) {
  68. if (!isset($parent)) {
  69. $parent = $element;
  70. }
  71. if ($element->getName() === 'testcase' && (int) $parent->attributes()->tests > 0) {
  72. // Add the class attribute if the test case does not have one. This is the
  73. // case for tests using a data provider. The name of the parent testsuite
  74. // will be in the format class::method.
  75. if (!$element->attributes()->class) {
  76. $name = explode('::', $parent->attributes()->name, 2);
  77. $element->addAttribute('class', $name[0]);
  78. }
  79. return [$element];
  80. }
  81. $test_cases = [];
  82. foreach ($element as $child) {
  83. $file = (string) $parent->attributes()->file;
  84. if ($file && !$child->attributes()->file) {
  85. $child->addAttribute('file', $file);
  86. }
  87. $test_cases = array_merge($test_cases, static::findTestCases($child, $element));
  88. }
  89. return $test_cases;
  90. }
  91. /**
  92. * Converts a PHPUnit test case result to a {simpletest} result row.
  93. *
  94. * @param int $test_id
  95. * The current test ID.
  96. * @param \SimpleXMLElement $test_case
  97. * The PHPUnit test case represented as XML element.
  98. *
  99. * @return array
  100. * An array containing the {simpletest} result row.
  101. *
  102. * @internal
  103. */
  104. public static function convertTestCaseToSimpletestRow($test_id, \SimpleXMLElement $test_case) {
  105. $message = '';
  106. $pass = TRUE;
  107. if ($test_case->failure) {
  108. $lines = explode("\n", $test_case->failure);
  109. $message = $lines[2];
  110. $pass = FALSE;
  111. }
  112. if ($test_case->error) {
  113. $message = $test_case->error;
  114. $pass = FALSE;
  115. }
  116. $attributes = $test_case->attributes();
  117. $record = [
  118. 'test_id' => $test_id,
  119. 'test_class' => (string) $attributes->class,
  120. 'status' => $pass ? 'pass' : 'fail',
  121. 'message' => $message,
  122. 'message_group' => 'Other',
  123. 'function' => $attributes->class . '->' . $attributes->name . '()',
  124. 'line' => (int) $attributes->line ?: 0,
  125. 'file' => (string) $attributes->file,
  126. ];
  127. return $record;
  128. }
  129. }