diff --git a/core/lib/Drupal/Core/Test/JUnitHelper.php b/core/lib/Drupal/Core/Test/JUnitHelper.php
new file mode 100644
index 0000000000..11d1a1ad00
--- /dev/null
+++ b/core/lib/Drupal/Core/Test/JUnitHelper.php
@@ -0,0 +1,131 @@
+<?php
+
+namespace Drupal\Core\Test;
+
+/**
+ * Convert PHPUnit 6+ JUnit reports to a form usable by run-tests.sh.
+ */
+class JUnitHelper {
+
+  /**
+   * The test ID.
+   *
+   * @var string
+   */
+  protected $testId;
+
+  /**
+   * Full path of the JUnit XML file to process.
+   *
+   * @var string
+   */
+  protected $jUnitFile;
+
+  /**
+   *
+   * @param string $test_id
+   *   The test ID for this test.
+   * @param string $junit_file
+   *   Full path to the JUnit XML file.
+   */
+  public function __construct($test_id, $junit_file) {
+    $this->testId = $test_id;
+    $this->jUnitFile = $junit_file;
+  }
+
+  /**
+   * Get the JUnit XML information transformed into the {simpletest} schema.
+   *
+   * @return string[]
+   */
+  public function getRecords() {
+    $records = [];
+    if (($log_file_contents = @file_get_contents($this->jUnitFile)) !== FALSE) {
+      foreach ($this->findTestcases(new \SimpleXMLElement($log_file_contents)) as $testcase) {
+        $records[] = $this->testCaseToRow($testcase);
+      }
+    }
+    return $records;
+  }
+
+  /**
+   * Get all the testcase records within the JUnit XML document.
+   *
+   * @param \SimpleXMLElement $junit
+   *   The JUnit XML to search for test cases.
+   *
+   * @return \SimpleXMLElement[]
+   *   All the testcase elements of the JUnit DOM, or empty array if there are
+   *   none.
+   */
+  protected function findTestcases(\SimpleXMLElement $junit) {
+    return $junit->xpath('.//testcase');
+  }
+
+  /**
+   * Determine a status string for the given testcase.
+   *
+   * JUnit from PHPUnit < 6 will not have a skipped child element, so we can't
+   * determine it from this record. It's still safe to check for the skipped
+   * child element, however, which gives us forward compatiblity for PHPUnit 6+.
+   *
+   * @param \SimpleXMLElement $testcase
+   *
+   * @return string
+   *   The status value to insert into the {simpletest} record. Allowed values:
+   *   'pass', 'fail', 'skipped'.
+   */
+  protected function getStatus(\SimpleXMLElement $testcase) {
+    $status = 'pass';
+    if ($testcase->failure || $testcase->error) {
+      $status = 'fail';
+    }
+    elseif ($testcase->skipped){
+      $status = 'skipped';
+    }
+    return $status;
+  }
+
+  /**
+   * Convert a single JUnit DOM testcase into a {simpletest} database row.
+   *
+   * @param \SimpleXMLElement $testcase
+   *   DOM representation of an individual JUnit testcase.
+   *
+   * @return mixed[]
+   *   A record suitable to insert into the {simpletest} database.
+   */
+  protected function testCaseToRow(\SimpleXMLElement $testcase) {
+    $status = $this->getStatus($testcase);
+
+    // Empty message for 'pass' status.
+    $message = '';
+    if ($status == 'fail') {
+      if ($testcase->failure) {
+        $message = (string) $testcase->failure[0];
+      }
+      elseif ($testcase->error) {
+        $message = (string) $testcase->error[0];
+      }
+    }
+    elseif ($status == 'skipped') {
+      $message = 'Skipped or incomplete';
+    }
+
+    $attributes = $testcase->attributes();
+
+    $record = [
+      'test_id' => $this->testId,
+      'test_class' => (string) $attributes->class,
+      'status' => $status,
+      'message' => $message,
+      // @todo: Check on the proper values for this.
+      'message_group' => 'Other',
+      'function' => $attributes->class . '->' . $attributes->name . '()',
+      'line' => (int) $attributes->line[0] ?: 0,
+      'file' => (string) $attributes->file[0],
+    ];
+    return $record;
+  }
+
+}
diff --git a/core/modules/simpletest/css/simpletest.module.css b/core/modules/simpletest/css/simpletest.module.css
index 9235b4958c..7fd087da69 100644
--- a/core/modules/simpletest/css/simpletest.module.css
+++ b/core/modules/simpletest/css/simpletest.module.css
@@ -60,6 +60,13 @@ tr.simpletest-fail.odd {
 tr.simpletest-fail.even {
   background-color: #ffacac;
 }
+tr.simpletest-skipped,
+tr.simpletest-skipped.odd {
+  background-color: #ffc9c9;
+}
+tr.simpletest-skipped.even {
+  background-color: #ffacac;
+}
 tr.simpletest-exception,
 tr.simpletest-exception.odd {
   background-color: #f4ea71;
diff --git a/core/modules/simpletest/simpletest.module b/core/modules/simpletest/simpletest.module
index dd05ddc1ca..c9d5497f68 100644
--- a/core/modules/simpletest/simpletest.module
+++ b/core/modules/simpletest/simpletest.module
@@ -15,6 +15,7 @@
 use Drupal\Tests\Listeners\SimpletestUiPrinter;
 use PHPUnit\Framework\TestCase;
 use Symfony\Component\Process\PhpExecutableFinder;
+use Drupal\Core\Test\JUnitHelper;
 use Drupal\Core\Test\TestStatus;
 
 /**
@@ -46,7 +47,7 @@ function simpletest_help($route_name, RouteMatchInterface $route_match) {
 function simpletest_theme() {
   return [
     'simpletest_result_summary' => [
-      'variables' => ['label' => NULL, 'items' => [], 'pass' => 0, 'fail' => 0, 'exception' => 0, 'debug' => 0],
+      'variables' => ['label' => NULL, 'items' => [], 'pass' => 0, 'fail' => 0, 'skipped' => 0, 'exception' => 0, 'debug' => 0],
     ],
   ];
 }
@@ -94,6 +95,7 @@ function _simpletest_build_summary_line($summary) {
   $translation = \Drupal::translation();
   $items['pass'] = $translation->formatPlural($summary['pass'], '1 pass', '@count passes');
   $items['fail'] = $translation->formatPlural($summary['fail'], '1 fail', '@count fails');
+  $items['skipped'] = $translation->formatPlural($summary['skipped'], '1 skipped', '@count skipped');
   $items['exception'] = $translation->formatPlural($summary['exception'], '1 exception', '@count exceptions');
   if ($summary['debug']) {
     $items['debug'] = $translation->formatPlural($summary['debug'], '1 debug message', '@count debug messages');
@@ -188,7 +190,8 @@ function simpletest_run_phpunit_tests($test_id, array $unescaped_test_classnames
 
   $rows = [];
   if ($status == TestStatus::PASS) {
-    $rows = simpletest_phpunit_xml_to_rows($test_id, $phpunit_file);
+    $junit = new JUnitHelper($test_id, $phpunit_file);
+    $rows = $junit->getRecords();
   }
   else {
     $rows[] = [
@@ -241,6 +244,7 @@ function simpletest_summarize_phpunit_result($results) {
       $summaries[$result['test_class']] = [
         '#pass' => 0,
         '#fail' => 0,
+        '#skipped' => 0,
         '#exception' => 0,
         '#debug' => 0,
       ];
@@ -255,6 +259,10 @@ function simpletest_summarize_phpunit_result($results) {
         $summaries[$result['test_class']]['#fail']++;
         break;
 
+      case 'skipped':
+        $summaries[$result['test_class']]['#skipped']++;
+        break;
+
       case 'exception':
         $summaries[$result['test_class']]['#exception']++;
         break;
@@ -409,7 +417,7 @@ function _simpletest_batch_operation($test_list_init, $test_id, &$context) {
     // First iteration: initialize working values.
     $test_list = $test_list_init;
     $context['sandbox']['max'] = count($test_list);
-    $test_results = ['#pass' => 0, '#fail' => 0, '#exception' => 0, '#debug' => 0];
+    $test_results = ['#pass' => 0, '#fail' => 0, '#skipped' => 0, '#exception' => 0, '#debug' => 0];
   }
   else {
     // Nth iteration: get the current values where we last stored them.
@@ -774,18 +782,15 @@ function simpletest_mail_alter(&$message) {
  *   The results as array of rows in a format that can be inserted into
  *   {simpletest}. If the phpunit_xml_file does not have any contents then the
  *   function will return NULL.
+ *
+ * @deprecated in Drupal 8.6.x for removal before Drupal 9.0.0. Use
+ *   \Drupal\Core\Test\JUnitHelper to convert JUnit to simpletest database rows.
  */
 function simpletest_phpunit_xml_to_rows($test_id, $phpunit_xml_file) {
-  $contents = @file_get_contents($phpunit_xml_file);
-  if (!$contents) {
-    return;
-  }
-  $records = [];
-  $testcases = simpletest_phpunit_find_testcases(new SimpleXMLElement($contents));
-  foreach ($testcases as $testcase) {
-    $records[] = simpletest_phpunit_testcase_to_row($test_id, $testcase);
-  }
-  return $records;
+  $junit = new JUnitHelper($test_id, $phpunit_xml_file);
+  $records = $junit->getRecords();
+  @trigger_error(__FUNCTION__ . ' is deprecated in Drupal 8.6.x. Use \Drupal\Core\Test\JUnitHelper to convert JUnit to simpletest database rows.', E_USER_DEPRECATED);
+  return $records ?: NULL;
 }
 
 /**
@@ -794,38 +799,18 @@ function simpletest_phpunit_xml_to_rows($test_id, $phpunit_xml_file) {
  * @param \SimpleXMLElement $element
  *   The PHPUnit xml to search for test cases.
  * @param \SimpleXMLElement $parent
- *   (Optional) The parent of the current element. Defaults to NULL.
+ *   (Optional) The parent of the current element. Defaults to NULL. Unused.
  *
  * @return array
  *   A list of all test cases.
+ *
+ * @deprecated in Drupal 8.6.x for removal before Drupal 9.0.0. Use
+ *   \Drupal\Core\Test\JUnitHelper to convert JUnit to simpletest database rows.
  */
 function simpletest_phpunit_find_testcases(\SimpleXMLElement $element, \SimpleXMLElement $parent = NULL) {
-  $testcases = [];
-
-  if (!isset($parent)) {
-    $parent = $element;
-  }
-
-  if ($element->getName() === 'testcase' && (int) $parent->attributes()->tests > 0) {
-    // Add the class attribute if the testcase does not have one. This is the
-    // case for tests using a data provider. The name of the parent testsuite
-    // will be in the format class::method.
-    if (!$element->attributes()->class) {
-      $name = explode('::', $parent->attributes()->name, 2);
-      $element->addAttribute('class', $name[0]);
-    }
-    $testcases[] = $element;
-  }
-  else {
-    foreach ($element as $child) {
-      $file = (string) $parent->attributes()->file;
-      if ($file && !$child->attributes()->file) {
-        $child->addAttribute('file', $file);
-      }
-      $testcases = array_merge($testcases, simpletest_phpunit_find_testcases($child, $element));
-    }
-  }
-  return $testcases;
+  $testcases = $element->xpath('//testcase');
+  @trigger_error(__FUNCTION__ . ' is deprecated in Drupal 8.6.x. Use \Drupal\Core\Test\JUnitHelper to convert JUnit to simpletest database rows.', E_USER_DEPRECATED);
+  return $testcases ?: [];
 }
 
 /**
@@ -838,6 +823,9 @@ function simpletest_phpunit_find_testcases(\SimpleXMLElement $element, \SimpleXM
  *
  * @return array
  *   An array containing the {simpletest} result row.
+ *
+ * @deprecated in Drupal 8.6.x for removal before Drupal 9.0.0. Use
+ *   \Drupal\Core\Test\JUnitHelper to convert JUnit to simpletest database rows.
  */
 function simpletest_phpunit_testcase_to_row($test_id, \SimpleXMLElement $testcase) {
   $message = '';
@@ -865,5 +853,6 @@ function simpletest_phpunit_testcase_to_row($test_id, \SimpleXMLElement $testcas
     'line' => $attributes->line ?: 0,
     'file' => $attributes->file,
   ];
+  @trigger_error(__FUNCTION__ . ' is deprecated in Drupal 8.6.x. Use \Drupal\Core\Test\JUnitHelper to convert JUnit to simpletest database rows.', E_USER_DEPRECATED);
   return $record;
 }
diff --git a/core/modules/simpletest/src/Form/SimpletestResultsForm.php b/core/modules/simpletest/src/Form/SimpletestResultsForm.php
index 55a9ca4e87..98ff612a06 100644
--- a/core/modules/simpletest/src/Form/SimpletestResultsForm.php
+++ b/core/modules/simpletest/src/Form/SimpletestResultsForm.php
@@ -92,6 +92,7 @@ protected static function buildStatusImageMap() {
     return [
       'pass' => $image_pass,
       'fail' => $image_fail,
+      'skipped' => $image_debug,
       'exception' => $image_exception,
       'debug' => $image_debug,
     ];
@@ -263,6 +264,7 @@ public static function addResultForm(array &$form, array $results) {
     $filter = [
       'pass' => [],
       'fail' => [],
+      'skipped' => [],
     ];
 
     // Summary result widget.
@@ -277,6 +279,7 @@ public static function addResultForm(array &$form, array $results) {
       '#theme' => 'simpletest_result_summary',
       '#pass' => 0,
       '#fail' => 0,
+      '#skipped' => 0,
       '#exception' => 0,
       '#debug' => 0,
     ];
@@ -333,7 +336,8 @@ public static function addResultForm(array &$form, array $results) {
 
       // Set summary information.
       $group_summary['#ok'] = $group_summary['#fail'] + $group_summary['#exception'] == 0;
-      $form['result']['results'][$group]['#open'] = !$group_summary['#ok'];
+      // Set the group to be revealed if there were fails, errors, or skipped.
+      $form['result']['results'][$group]['#open'] = !$group_summary['#ok'] || $group_summary['#skipped'];
 
       // Store test group (class) as for use in filter.
       $filter[$group_summary['#ok'] ? 'pass' : 'fail'][] = $group;
diff --git a/core/modules/simpletest/src/TestBase.php b/core/modules/simpletest/src/TestBase.php
index 260d1a34af..4f7dfe0bf6 100644
--- a/core/modules/simpletest/src/TestBase.php
+++ b/core/modules/simpletest/src/TestBase.php
@@ -58,6 +58,7 @@
   public $results = [
     '#pass' => 0,
     '#fail' => 0,
+    '#skipped' => 0,
     '#exception' => 0,
     '#debug' => 0,
   ];
@@ -287,7 +288,7 @@ protected function storeAssertion(array $assertion) {
    * Internal helper: stores the assert.
    *
    * @param $status
-   *   Can be 'pass', 'fail', 'exception', 'debug'.
+   *   Can be 'pass', 'fail', 'skipped', 'exception', 'debug'.
    *   TRUE is a synonym for 'pass', FALSE for 'fail'.
    * @param string|\Drupal\Component\Render\MarkupInterface $message
    *   (optional) A message to display with the assertion. Do not translate
diff --git a/core/modules/simpletest/src/Tests/SimpleTestBrowserTest.php b/core/modules/simpletest/src/Tests/SimpleTestBrowserTest.php
index bb9da9411a..cffc401737 100644
--- a/core/modules/simpletest/src/Tests/SimpleTestBrowserTest.php
+++ b/core/modules/simpletest/src/Tests/SimpleTestBrowserTest.php
@@ -141,7 +141,7 @@ public function testTestingThroughUI() {
         "tests[$test]" => TRUE,
       ];
       $this->drupalPostForm(NULL, $edit, t('Run tests'));
-      $this->assertText('0 fails, 0 exceptions');
+      $this->assertText('0 fails, 0 skipped, 0 exceptions');
     }
   }
 
diff --git a/core/modules/simpletest/src/Tests/SimpleTestTest.php b/core/modules/simpletest/src/Tests/SimpleTestTest.php
index 42759c255a..d201da6e6f 100644
--- a/core/modules/simpletest/src/Tests/SimpleTestTest.php
+++ b/core/modules/simpletest/src/Tests/SimpleTestTest.php
@@ -265,7 +265,7 @@ public function confirmStubTestResults() {
 
     $this->assertAssertion("Debug: 'Foo'", 'Debug', 'Fail', 'SimpleTestTest.php', 'Drupal\simpletest\Tests\SimpleTestTest->stubTest()');
 
-    $this->assertEqual('16 passes, 3 fails, 2 exceptions, 3 debug messages', $this->childTestResults['summary']);
+    $this->assertEqual('16 passes, 3 fails, 0 skipped, 2 exceptions, 3 debug messages', $this->childTestResults['summary']);
 
     $this->testIds[] = $test_id = $this->getTestIdFromResults();
     $this->assertTrue($test_id, 'Found test ID in results.');
diff --git a/core/modules/simpletest/tests/src/Unit/PhpUnitErrorTest.php b/core/modules/simpletest/tests/src/Unit/PhpUnitErrorTest.php
deleted file mode 100644
index 25211fc404..0000000000
--- a/core/modules/simpletest/tests/src/Unit/PhpUnitErrorTest.php
+++ /dev/null
@@ -1,40 +0,0 @@
-<?php
-
-namespace Drupal\Tests\simpletest\Unit;
-
-use Drupal\Tests\UnitTestCase;
-
-/**
- * Tests PHPUnit errors are getting converted to Simpletest errors.
- *
- * @group simpletest
- */
-class PhpUnitErrorTest extends UnitTestCase {
-
-  /**
-   * Test errors reported.
-   *
-   * @covers ::simpletest_phpunit_xml_to_rows
-   */
-  public function testPhpUnitXmlParsing() {
-    require_once __DIR__ . '/../../../simpletest.module';
-
-    $phpunit_error_xml = __DIR__ . '/../../fixtures/phpunit_error.xml';
-
-    $res = simpletest_phpunit_xml_to_rows(1, $phpunit_error_xml);
-    $this->assertEquals(count($res), 4, 'All testcases got extracted');
-    $this->assertNotEquals($res[0]['status'], 'pass');
-    $this->assertEquals($res[0]['status'], 'fail');
-
-    // Test nested testsuites, which appear when you use @dataProvider.
-    for ($i = 0; $i < 3; $i++) {
-      $this->assertNotEquals($res[$i + 1]['status'], 'pass');
-      $this->assertEquals($res[$i + 1]['status'], 'fail');
-    }
-
-    // Make sure simpletest_phpunit_xml_to_rows() does not balk if the test
-    // didn't run.
-    simpletest_phpunit_xml_to_rows(1, 'foobar');
-  }
-
-}
diff --git a/core/modules/simpletest/tests/src/Unit/SimpletestJUnitDeprecationTest.php b/core/modules/simpletest/tests/src/Unit/SimpletestJUnitDeprecationTest.php
new file mode 100644
index 0000000000..7f260ea795
--- /dev/null
+++ b/core/modules/simpletest/tests/src/Unit/SimpletestJUnitDeprecationTest.php
@@ -0,0 +1,54 @@
+<?php
+
+namespace Drupal\Tests\simpletest\Unit;
+
+use Drupal\Tests\UnitTestCase;
+
+/**
+ * @group simpletest
+ * @group legacy
+ */
+class SimpletestJUnitDeprecationTest extends UnitTestCase {
+
+  protected function setUp() {
+    parent::setUp();
+    require_once __DIR__ . '/../../../simpletest.module';
+  }
+
+  /**
+   * @covers ::simpletest_phpunit_xml_to_rows
+   * @expectedDeprecation simpletest_phpunit_xml_to_rows is deprecated in Drupal 8.6.x. Use \Drupal\Core\Test\JUnitHelper to convert JUnit to simpletest database rows.
+   */
+  public function testXmlToRows() {
+    $phpunit_error_xml = __DIR__ . '/../../../../../tests/fixtures/phpunit_error.xml';
+
+    $results = simpletest_phpunit_xml_to_rows(1, $phpunit_error_xml);
+    $this->assertCount(4, $results);
+  }
+
+  /**
+   * @covers ::simpletest_phpunit_find_testcases
+   * @expectedDeprecation simpletest_phpunit_find_testcases is deprecated in Drupal 8.6.x. Use \Drupal\Core\Test\JUnitHelper to convert JUnit to simpletest database rows.
+   */
+  public function testFindTestcases() {
+    // Note that testcase elements usually don't have tests attributes, but we
+    // can fool the function into parsing this testcase just to trigger the
+    // deprecation error.
+    $junit = new \SimpleXMLElement('<testcase name="name" class="Drupal\Foo\BarTest" tests="1"/>');
+
+    $result = simpletest_phpunit_find_testcases($junit);
+    $this->assertNotEmpty($result);
+  }
+
+  /**
+   * @covers ::simpletest_phpunit_testcase_to_row
+   * @expectedDeprecation simpletest_phpunit_testcase_to_row is deprecated in Drupal 8.6.x. Use \Drupal\Core\Test\JUnitHelper to convert JUnit to simpletest database rows.
+   */
+  public function testTestcaseToRow() {
+    $junit = new \SimpleXMLElement('<testcase class="Drupal\Foo\BarTest"/>');
+
+    $result = simpletest_phpunit_testcase_to_row('id', $junit);
+    $this->assertNotEmpty($result);
+  }
+
+}
diff --git a/core/scripts/run-tests.sh b/core/scripts/run-tests.sh
index 6a8eaca824..942959214d 100644
--- a/core/scripts/run-tests.sh
+++ b/core/scripts/run-tests.sh
@@ -759,7 +759,7 @@ function simpletest_script_execute_batch($test_classes) {
           // Ensure that an error line is displayed for the class.
           simpletest_script_reporter_display_summary(
             $child['class'],
-            ['#pass' => 0, '#fail' => 1, '#exception' => 0, '#debug' => 0]
+            ['#pass' => 0, '#fail' => 1, '#skipped' => 0, '#exception' => 0, '#debug' => 0]
           );
           if ($args['die-on-fail']) {
             list($db_prefix) = simpletest_last_test_get($child['test_id']);
@@ -1221,10 +1221,11 @@ function simpletest_script_reporter_display_summary($class, $results) {
   // Output all test results vertically aligned.
   // Cut off the class name after 60 chars, and pad each group with 3 digits
   // by default (more than 999 assertions are rare).
-  $output = vsprintf('%-60.60s %10s %9s %14s %12s', [
+  $output = vsprintf('%-60.60s %10s %9s %22s %14s %12s', [
     $class,
     $results['#pass'] . ' passes',
     !$results['#fail'] ? '' : $results['#fail'] . ' fails',
+    !$results['#skipped'] ? '' : $results['#skipped'] . ' skipped/incomplete',
     !$results['#exception'] ? '' : $results['#exception'] . ' exceptions',
     !$results['#debug'] ? '' : $results['#debug'] . ' messages',
   ]);
diff --git a/core/tests/Drupal/Tests/Core/Test/JUnitHelperTest.php b/core/tests/Drupal/Tests/Core/Test/JUnitHelperTest.php
new file mode 100644
index 0000000000..20822a9596
--- /dev/null
+++ b/core/tests/Drupal/Tests/Core/Test/JUnitHelperTest.php
@@ -0,0 +1,87 @@
+<?php
+
+namespace Drupal\Tests\Core\Test;
+
+use Drupal\Core\Test\JUnitHelper;
+use Drupal\Tests\UnitTestCase;
+
+/**
+ * @coversDefaultClass \Drupal\Core\Test\JUnitHelper
+ *
+ * @group Test
+ * @group JUnit
+ * @group simpletest
+ */
+class JUnitHelperTest extends UnitTestCase {
+
+  public function testEmptyState() {
+    $junit = new JUnitHelper('id', 'empty-file');
+    $this->assertEmpty($junit->getRecords());
+  }
+
+  /**
+   * @coversNothing
+   */
+  public function testError() {
+    $file = realpath(__DIR__ . '/../../../../fixtures/phpunit_error.xml');
+    $this->assertFileExists($file);
+    $junit = new JUnitHelper('id', realpath($file));
+    $records = $junit->getRecords();
+
+    $this->assertEquals(count($records), 4, 'All testcases got extracted');
+    $this->assertNotEquals($records[0]['status'], 'pass');
+    $this->assertEquals($records[0]['status'], 'fail');
+
+    // Test nested testsuites, which appear when you use @dataProvider.
+    for ($i = 0; $i < 3; $i++) {
+      $this->assertNotEquals($records[$i + 1]['status'], 'pass');
+      $this->assertEquals($records[$i + 1]['status'], 'fail');
+    }
+  }
+
+  /**
+   * @coversNothing
+   */
+  public function testSkipped() {
+    $file = realpath(__DIR__ . '/../../../../fixtures/phpunit_skipped.xml');
+    $this->assertFileExists($file);
+
+    $junit = new JUnitHelper('id', realpath($file));
+    $records = $junit->getRecords();
+
+    $this->assertCount(18, $records);
+    // Only item 0 should be skipped.
+    $this->assertEquals('skipped', $records[0]['status']);
+    foreach (range(1, 17) as $index) {
+      $this->assertEquals('pass', $records[$index]['status']);
+    }
+  }
+
+  public function provideGetStatus() {
+    return [
+      'pass' => ['pass', '<testcase name="name"/>'],
+      'fail-for-fail' => ['fail', '<testcase name="name"><failure type="PHPUnit_Framework_ExpectationFailedException">Message</failure></testcase>'],
+      'error-for-fail' => ['fail', '<testcase name="name"><error type="PHPUnit_Framework_Error_Notice">Message</error></testcase>'],
+      'skipped' => ['skipped', '<testcase name="name"><skipped/></testcase>'],
+    ];
+  }
+
+  /**
+   * @dataProvider provideGetStatus
+   * @covers ::getStatus
+   */
+  public function testGetStatus($expected, $xml) {
+    $junit = $this->getMockBuilder(JUnitHelper::class)
+      ->disableOriginalConstructor()
+      ->getMock();
+
+    $ref_get_status = new \ReflectionMethod($junit, 'getStatus');
+    $ref_get_status->setAccessible(TRUE);
+
+    $this->assertEquals(
+      $expected,
+      $ref_get_status->invokeArgs($junit, [new \SimpleXMLElement($xml)])
+    );
+  }
+
+}
diff --git a/core/modules/simpletest/tests/fixtures/phpunit_error.xml b/core/tests/fixtures/phpunit_error.xml
similarity index 100%
rename from core/modules/simpletest/tests/fixtures/phpunit_error.xml
rename to core/tests/fixtures/phpunit_error.xml
diff --git a/core/tests/fixtures/phpunit_skipped.xml b/core/tests/fixtures/phpunit_skipped.xml
new file mode 100644
index 0000000000..58c4122111
--- /dev/null
+++ b/core/tests/fixtures/phpunit_skipped.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<testsuites>
+  <testsuite name="" tests="18" assertions="61" errors="0" failures="0" skipped="1" time="0.029664">
+    <testsuite name="unit" tests="18" assertions="61" errors="0" failures="0" skipped="1" time="0.029664">
+      <testsuite name="unit" tests="18" assertions="61" errors="0" failures="0" skipped="1" time="0.029664">
+        <testsuite name="Drupal\Tests\Core\Access\AccessManagerTest" file="/Users/paul/projects/drupal/core/tests/Drupal/Tests/Core/Access/AccessManagerTest.php" tests="18" assertions="61" errors="0" failures="0" skipped="1" time="0.029664">
+          <testcase name="testSetChecks" class="Drupal\Tests\Core\Access\AccessManagerTest" classname="Drupal.Tests.Core.Access.AccessManagerTest" file="/Users/paul/projects/drupal/core/tests/Drupal/Tests/Core/Access/AccessManagerTest.php" line="138" assertions="0" time="0.004875">
+            <skipped/>
+          </testcase>
+          <testcase name="testSetChecksWithDynamicAccessChecker" class="Drupal\Tests\Core\Access\AccessManagerTest" classname="Drupal.Tests.Core.Access.AccessManagerTest" file="/Users/paul/projects/drupal/core/tests/Drupal/Tests/Core/Access/AccessManagerTest.php" line="159" assertions="3" time="0.002332"/>
+          <testcase name="testCheck" class="Drupal\Tests\Core\Access\AccessManagerTest" classname="Drupal.Tests.Core.Access.AccessManagerTest" file="/Users/paul/projects/drupal/core/tests/Drupal/Tests/Core/Access/AccessManagerTest.php" line="189" assertions="24" time="0.002953"/>
+          <testcase name="testCheckWithNullAccount" class="Drupal\Tests\Core\Access\AccessManagerTest" classname="Drupal.Tests.Core.Access.AccessManagerTest" file="/Users/paul/projects/drupal/core/tests/Drupal/Tests/Core/Access/AccessManagerTest.php" line="231" assertions="1" time="0.001155"/>
+          <testsuite name="Drupal\Tests\Core\Access\AccessManagerTest::testCheckConjunctions" tests="6" assertions="12" errors="0" failures="0" skipped="0" time="0.007527">
+            <testcase name="testCheckConjunctions with data set #0" class="Drupal\Tests\Core\Access\AccessManagerTest" classname="Drupal.Tests.Core.Access.AccessManagerTest" file="/Users/paul/projects/drupal/core/tests/Drupal/Tests/Core/Access/AccessManagerTest.php" line="305" assertions="2" time="0.001340"/>
+            <testcase name="testCheckConjunctions with data set #1" class="Drupal\Tests\Core\Access\AccessManagerTest" classname="Drupal.Tests.Core.Access.AccessManagerTest" file="/Users/paul/projects/drupal/core/tests/Drupal/Tests/Core/Access/AccessManagerTest.php" line="305" assertions="2" time="0.001225"/>
+            <testcase name="testCheckConjunctions with data set #2" class="Drupal\Tests\Core\Access\AccessManagerTest" classname="Drupal.Tests.Core.Access.AccessManagerTest" file="/Users/paul/projects/drupal/core/tests/Drupal/Tests/Core/Access/AccessManagerTest.php" line="305" assertions="2" time="0.001213"/>
+            <testcase name="testCheckConjunctions with data set #3" class="Drupal\Tests\Core\Access\AccessManagerTest" classname="Drupal.Tests.Core.Access.AccessManagerTest" file="/Users/paul/projects/drupal/core/tests/Drupal/Tests/Core/Access/AccessManagerTest.php" line="305" assertions="2" time="0.001237"/>
+            <testcase name="testCheckConjunctions with data set #4" class="Drupal\Tests\Core\Access\AccessManagerTest" classname="Drupal.Tests.Core.Access.AccessManagerTest" file="/Users/paul/projects/drupal/core/tests/Drupal/Tests/Core/Access/AccessManagerTest.php" line="305" assertions="2" time="0.001203"/>
+            <testcase name="testCheckConjunctions with data set #5" class="Drupal\Tests\Core\Access\AccessManagerTest" classname="Drupal.Tests.Core.Access.AccessManagerTest" file="/Users/paul/projects/drupal/core/tests/Drupal/Tests/Core/Access/AccessManagerTest.php" line="305" assertions="2" time="0.001309"/>
+          </testsuite>
+          <testcase name="testCheckNamedRoute" class="Drupal\Tests\Core\Access\AccessManagerTest" classname="Drupal.Tests.Core.Access.AccessManagerTest" file="/Users/paul/projects/drupal/core/tests/Drupal/Tests/Core/Access/AccessManagerTest.php" line="333" assertions="5" time="0.001741"/>
+          <testcase name="testCheckNamedRouteWithUpcastedValues" class="Drupal\Tests\Core\Access\AccessManagerTest" classname="Drupal.Tests.Core.Access.AccessManagerTest" file="/Users/paul/projects/drupal/core/tests/Drupal/Tests/Core/Access/AccessManagerTest.php" line="368" assertions="5" time="0.001681"/>
+          <testcase name="testCheckNamedRouteWithDefaultValue" class="Drupal\Tests\Core\Access\AccessManagerTest" classname="Drupal.Tests.Core.Access.AccessManagerTest" file="/Users/paul/projects/drupal/core/tests/Drupal/Tests/Core/Access/AccessManagerTest.php" line="417" assertions="5" time="0.001703"/>
+          <testcase name="testCheckNamedRouteWithNonExistingRoute" class="Drupal\Tests\Core\Access\AccessManagerTest" classname="Drupal.Tests.Core.Access.AccessManagerTest" file="/Users/paul/projects/drupal/core/tests/Drupal/Tests/Core/Access/AccessManagerTest.php" line="464" assertions="2" time="0.001036"/>
+          <testsuite name="Drupal\Tests\Core\Access\AccessManagerTest::testCheckException" tests="4" assertions="4" errors="0" failures="0" skipped="0" time="0.004661">
+            <testcase name="testCheckException with data set #0" class="Drupal\Tests\Core\Access\AccessManagerTest" classname="Drupal.Tests.Core.Access.AccessManagerTest" file="/Users/paul/projects/drupal/core/tests/Drupal/Tests/Core/Access/AccessManagerTest.php" line="480" assertions="1" time="0.001333"/>
+            <testcase name="testCheckException with data set #1" class="Drupal\Tests\Core\Access\AccessManagerTest" classname="Drupal.Tests.Core.Access.AccessManagerTest" file="/Users/paul/projects/drupal/core/tests/Drupal/Tests/Core/Access/AccessManagerTest.php" line="480" assertions="1" time="0.001112"/>
+            <testcase name="testCheckException with data set #2" class="Drupal\Tests\Core\Access\AccessManagerTest" classname="Drupal.Tests.Core.Access.AccessManagerTest" file="/Users/paul/projects/drupal/core/tests/Drupal/Tests/Core/Access/AccessManagerTest.php" line="480" assertions="1" time="0.001106"/>
+            <testcase name="testCheckException with data set #3" class="Drupal\Tests\Core\Access\AccessManagerTest" classname="Drupal.Tests.Core.Access.AccessManagerTest" file="/Users/paul/projects/drupal/core/tests/Drupal/Tests/Core/Access/AccessManagerTest.php" line="480" assertions="1" time="0.001110"/>
+          </testsuite>
+        </testsuite>
+      </testsuite>
+    </testsuite>
+  </testsuite>
+</testsuites>
