diff --git a/.gitlab-ci/pipeline.yml b/.gitlab-ci/pipeline.yml
index 06f5c83acbca7524e7e4a948019431e405022de7..c311b1a03a634714ef411ea640801b97f3b4f377 100644
--- a/.gitlab-ci/pipeline.yml
+++ b/.gitlab-ci/pipeline.yml
@@ -104,7 +104,7 @@ variables:
   script:
     - sudo -u www-data -E -H composer run-script drupal-phpunit-upgrade-check
     # Need to pass this along directly.
-    - sudo -u www-data -E -H php ./core/scripts/run-tests.sh --debug-discovery --color --keep-results --types "$TESTSUITE" --concurrency "$CONCURRENCY" --repeat "1" --sqlite "./sites/default/files/tests.sqlite" --dburl $SIMPLETEST_DB --url $SIMPLETEST_BASE_URL --verbose --non-html --all --ci-parallel-node-index $CI_PARALLEL_NODE_INDEX --ci-parallel-node-total $CI_PARALLEL_NODE_TOTAL
+    - sudo -u www-data -E -H php ./core/scripts/run-tests.sh --color --keep-results --types "$TESTSUITE" --concurrency "$CONCURRENCY" --repeat "1" --sqlite "./sites/default/files/tests.sqlite" --dburl $SIMPLETEST_DB --url $SIMPLETEST_BASE_URL --verbose --non-html --all --ci-parallel-node-index $CI_PARALLEL_NODE_INDEX --ci-parallel-node-total $CI_PARALLEL_NODE_TOTAL
 
 .run-repeat-class-test: &run-repeat-class-test
   script:
@@ -234,7 +234,7 @@ variables:
   script:
     - sudo -u www-data -E -H composer run-script drupal-phpunit-upgrade-check
     # Run a small subset of tests to prove non W3C testing still works.
-    - sudo -u www-data -E -H php ./core/scripts/run-tests.sh --debug-discovery --color --keep-results --types "$TESTSUITE" --concurrency "$CONCURRENCY" --repeat "1" --sqlite "./sites/default/files/tests.sqlite" --dburl $SIMPLETEST_DB --url $SIMPLETEST_BASE_URL --verbose --non-html javascript
+    - sudo -u www-data -E -H php ./core/scripts/run-tests.sh --color --keep-results --types "$TESTSUITE" --concurrency "$CONCURRENCY" --repeat "1" --sqlite "./sites/default/files/tests.sqlite" --dburl $SIMPLETEST_DB --url $SIMPLETEST_BASE_URL --verbose --non-html javascript
 
   after_script:
     - sed -i "s#$CI_PROJECT_DIR/##" ./sites/default/files/simpletest/phpunit-*.xml || true
diff --git a/core/.phpunit-next.xml b/core/.phpunit-next.xml
deleted file mode 100644
index 944ec9dfadd4c371956dd5827b2652e2f92e791b..0000000000000000000000000000000000000000
--- a/core/.phpunit-next.xml
+++ /dev/null
@@ -1,164 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-
-
-<!-- This is a near-copy of phpunit.xml.dist, used to test with upcoming
-     PHPUnit versions.
-
-     Current differences:
-     * for PHPUnit 11: removed duplicate directories from <testsuites>,
-       required in PHPUnit 10, but that cause duplication warnings in
-       PHPUnit 11.
--->
-
-
-<!-- For how to customize PHPUnit configuration, see core/tests/README.md. -->
-<!-- TODO set checkForUnintentionallyCoveredCode="true" once https://www.drupal.org/node/2626832 is resolved. -->
-<!-- PHPUnit expects functional tests to be run with either a privileged user
- or your current system user. See core/tests/README.md and
- https://www.drupal.org/node/2116263 for details.
--->
-<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         bootstrap="tests/bootstrap.php"
-         colors="true"
-         beStrictAboutTestsThatDoNotTestAnything="true"
-         beStrictAboutOutputDuringTests="true"
-         beStrictAboutChangesToGlobalState="true"
-         failOnRisky="true"
-         failOnWarning="true"
-         displayDetailsOnTestsThatTriggerErrors="true"
-         displayDetailsOnTestsThatTriggerWarnings="true"
-         displayDetailsOnTestsThatTriggerDeprecations="true"
-         cacheResult="false"
-         xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.5/phpunit.xsd"
-         cacheDirectory=".phpunit.cache">
-  <php>
-    <!-- Set error reporting to E_ALL. -->
-    <ini name="error_reporting" value="32767"/>
-    <!-- Do not limit the amount of memory tests take to run. -->
-    <ini name="memory_limit" value="-1"/>
-    <!-- Example SIMPLETEST_BASE_URL value: http://localhost -->
-    <env name="SIMPLETEST_BASE_URL" value=""/>
-    <!-- Example SIMPLETEST_DB value: mysql://username:password@localhost/database_name#table_prefix -->
-    <env name="SIMPLETEST_DB" value=""/>
-    <!-- By default, browser tests will output links that use the base URL set
-     in SIMPLETEST_BASE_URL. However, if your SIMPLETEST_BASE_URL is an internal
-     path (such as may be the case in a virtual or Docker-based environment),
-     you can set the base URL used in the browser test output links to something
-     reachable from your host machine here. This will allow you to follow them
-     directly and view the output. -->
-    <env name="BROWSERTEST_OUTPUT_BASE_URL" value=""/>
-    <!-- The environment variable SYMFONY_DEPRECATIONS_HELPER is used to configure
-      the behavior of the deprecation tests.
-      Drupal core's testing framework is setting this variable to its defaults.
-      Projects with their own requirements need to manage this variable
-      explicitly.
-    -->
-    <!-- To disable deprecation testing completely uncomment the next line. -->
-    <!-- <env name="SYMFONY_DEPRECATIONS_HELPER" value="disabled"/> -->
-    <!-- Deprecation errors can be selectively ignored by specifying a file of
-      regular expression patterns for exclusion.
-      Uncomment the line below to specify a custom deprecations ignore file.
-      NOTE: it may be required to specify the full path to the file to run tests
-      correctly.
-    -->
-    <!-- <env name="SYMFONY_DEPRECATIONS_HELPER" value="ignoreFile=.deprecation-ignore.txt"/> -->
-    <!-- Example for changing the driver class for mink tests MINK_DRIVER_CLASS value: 'Drupal\FunctionalJavascriptTests\DrupalSelenium2Driver' -->
-    <env name="MINK_DRIVER_CLASS" value=""/>
-    <!-- Example for changing the driver args to mink tests MINK_DRIVER_ARGS value: '["http://127.0.0.1:8510"]' -->
-    <env name="MINK_DRIVER_ARGS" value=""/>
-    <!-- Example for changing the driver args to webdriver tests MINK_DRIVER_ARGS_WEBDRIVER value: '["chrome", { "goog:chromeOptions": { "w3c": false } }, "http://localhost:4444/wd/hub"]' For using the Firefox browser, replace "chrome" with "firefox" -->
-    <env name="MINK_DRIVER_ARGS_WEBDRIVER" value=""/>
-  </php>
-  <extensions>
-    <!-- Functional tests HTML output logging. -->
-    <bootstrap class="Drupal\TestTools\Extension\HtmlLogging\HtmlOutputLogger">
-      <!-- The directory where the browser output will be stored. If a relative
-        path is specified, it will be relative to the current working directory
-        of the process running the PHPUnit CLI. In CI environments, this can be
-        overridden by the value set for the "BROWSERTEST_OUTPUT_DIRECTORY"
-        environment variable.
-      -->
-      <parameter name="outputDirectory" value="sites/simpletest/browser_output"/>
-      <!-- By default browser tests print the individual links in the test run
-        report. To avoid overcrowding the output in CI environments, you can
-        set the "verbose" parameter or the "BROWSERTEST_OUTPUT_VERBOSE"
-        environment variable to "false". In GitLabCI, the output is saved
-        anyway as an artifact that can be browsed or downloaded from Gitlab.
-      -->
-      <parameter name="verbose" value="true"/>
-    </bootstrap>
-    <!-- Debug dump() printer. -->
-    <bootstrap class="Drupal\TestTools\Extension\Dump\DebugDump">
-      <parameter name="colors" value="true"/>
-      <parameter name="printCaller" value="true"/>
-    </bootstrap>
-  </extensions>
-  <testsuites>
-    <testsuite name="unit-component">
-      <directory>tests/Drupal/Tests/Component</directory>
-    </testsuite>
-    <testsuite name="unit">
-      <directory>tests/Drupal/Tests</directory>
-      <exclude>tests/Drupal/Tests/Component</exclude>
-      <directory>modules/**/tests/src/Unit</directory>
-      <directory>profiles/**/tests/src/Unit</directory>
-      <directory>themes/**/tests/src/Unit</directory>
-      <directory>../modules/**/tests/src/Unit</directory>
-      <directory>../profiles/**/tests/src/Unit</directory>
-      <directory>../themes/**/tests/src/Unit</directory>
-    </testsuite>
-    <testsuite name="kernel">
-      <directory>tests/Drupal/KernelTests</directory>
-      <directory>modules/**/tests/src/Kernel</directory>
-      <directory>recipes/*/tests/src/Kernel</directory>
-      <directory>profiles/**/tests/src/Kernel</directory>
-      <directory>themes/**/tests/src/Kernel</directory>
-      <directory>../modules/**/tests/src/Kernel</directory>
-      <directory>../profiles/**/tests/src/Kernel</directory>
-      <directory>../themes/**/tests/src/Kernel</directory>
-    </testsuite>
-    <testsuite name="functional">
-      <directory>tests/Drupal/FunctionalTests</directory>
-      <directory>modules/**/tests/src/Functional</directory>
-      <directory>profiles/**/tests/src/Functional</directory>
-      <directory>recipes/*/tests/src/Functional</directory>
-      <directory>themes/**/tests/src/Functional</directory>
-      <directory>../modules/**/tests/src/Functional</directory>
-      <directory>../profiles/**/tests/src/Functional</directory>
-      <directory>../themes/**/tests/src/Functional</directory>
-    </testsuite>
-    <testsuite name="functional-javascript">
-      <directory>tests/Drupal/FunctionalJavascriptTests</directory>
-      <directory>modules/**/tests/src/FunctionalJavascript</directory>
-      <directory>recipes/*/tests/src/FunctionalJavascript</directory>
-      <directory>profiles/**/tests/src/FunctionalJavascript</directory>
-      <directory>themes/**/tests/src/FunctionalJavascript</directory>
-      <directory>../modules/**/tests/src/FunctionalJavascript</directory>
-      <directory>../profiles/**/tests/src/FunctionalJavascript</directory>
-      <directory>../themes/**/tests/src/FunctionalJavascript</directory>
-    </testsuite>
-    <testsuite name="build">
-      <directory>tests/Drupal/BuildTests</directory>
-      <directory>modules/**/tests/src/Build</directory>
-    </testsuite>
-  </testsuites>
-  <!-- Settings for coverage reports. -->
-  <source ignoreSuppressionOfDeprecations="true">
-    <include>
-      <directory>./includes</directory>
-      <directory>./lib</directory>
-      <directory>./modules</directory>
-      <directory>../modules</directory>
-      <directory>../sites</directory>
-    </include>
-    <exclude>
-      <directory>./lib/Drupal/Component</directory>
-      <directory>./modules/*/src/Tests</directory>
-      <directory>./modules/*/tests</directory>
-      <directory>../modules/*/src/Tests</directory>
-      <directory>../modules/*/tests</directory>
-      <directory>../modules/*/*/src/Tests</directory>
-      <directory>../modules/*/*/tests</directory>
-    </exclude>
-  </source>
-</phpunit>
diff --git a/core/lib/Drupal/Core/Test/PhpUnitTestDiscovery.php b/core/lib/Drupal/Core/Test/PhpUnitTestDiscovery.php
deleted file mode 100644
index d9737028821c66d7dceda0d9ea8f61df41350947..0000000000000000000000000000000000000000
--- a/core/lib/Drupal/Core/Test/PhpUnitTestDiscovery.php
+++ /dev/null
@@ -1,346 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-namespace Drupal\Core\Test;
-
-use Drupal\Core\Test\Exception\MissingGroupException;
-use Drupal\TestTools\PhpUnitCompatibility\RunnerVersion;
-use PHPUnit\Framework\DataProviderTestSuite;
-use PHPUnit\Framework\Test;
-use PHPUnit\Framework\TestCase;
-use PHPUnit\Framework\TestSuite;
-use PHPUnit\TextUI\Configuration\Builder;
-use PHPUnit\TextUI\Configuration\TestSuiteBuilder;
-
-/**
- * Discovers available tests using the PHPUnit API.
- *
- * @internal
- */
-class PhpUnitTestDiscovery {
-
-  /**
-   * The map of legacy test suite identifiers to phpunit.xml ones.
-   *
-   * @var array<string,string>
-   */
-  private array $map = [
-    'PHPUnit-FunctionalJavascript' => 'functional-javascript',
-    'PHPUnit-Functional' => 'functional',
-    'PHPUnit-Kernel' => 'kernel',
-    'PHPUnit-Unit' => 'unit',
-    'PHPUnit-Unit-Component' => 'unit-component',
-    'PHPUnit-Build' => 'build',
-  ];
-
-  /**
-   * The reverse map of legacy test suite identifiers to phpunit.xml ones.
-   *
-   * @var array<string,string>
-   */
-  private array $reverseMap;
-
-  /**
-   * The warnings generated during the discovery.
-   *
-   * @var list<string>
-   */
-  private array $warnings = [];
-
-  public function __construct(
-    private string $configurationFilePath,
-  ) {
-    $this->reverseMap = array_flip($this->map);
-  }
-
-  /**
-   * Discovers available tests.
-   *
-   * @param string|null $extension
-   *   (optional) The name of an extension to limit discovery to; e.g., 'node'.
-   * @param list<string> $testSuites
-   *   (optional) An array of PHPUnit test suites to filter the discovery for.
-   * @param string|null $directory
-   *   (optional) Limit discovered tests to a specific directory.
-   *
-   * @return array<string<array<class-string, array{name: class-string, description: string, group: string|int, groups: list<string|int>, type: string, file: string, tests_count: positive-int}>>>
-   *   An array of test groups keyed by the group name. Each test group is an
-   *   array of test class information arrays as returned by
-   *   ::getTestClassInfo(), keyed by test class. If a test class belongs to
-   *   multiple groups, it will appear under all group keys it belongs to.
-   */
-  public function getTestClasses(?string $extension = NULL, array $testSuites = [], ?string $directory = NULL): array {
-    $this->warnings = [];
-
-    $args = ['--configuration', $this->configurationFilePath];
-
-    if (!empty($testSuites)) {
-      // Convert $testSuites from Drupal's legacy syntax to the syntax used in
-      // phpunit.xml, that is necessary to PHPUnit to be able to apply the
-      // test suite filter. For example, 'PHPUnit-Unit' to 'unit'.
-      $tmp = [];
-      foreach ($testSuites as $i) {
-        if (!is_string($i)) {
-          throw new \InvalidArgumentException("Test suite must be a string");
-        }
-        if (str_contains($i, ' ')) {
-          throw new \InvalidArgumentException("Test suite name '{$i}' is invalid");
-        }
-        $tmp[] = $this->map[$i] ?? $i;
-      }
-      $args[] = '--testsuite=' . implode(',', $tmp);
-    }
-
-    if ($directory !== NULL) {
-      $args[] = $directory;
-    }
-
-    $phpUnitConfiguration = (new Builder())->build($args);
-
-    // TestSuiteBuilder calls the test data providers during the discovery.
-    // Data providers may be changing the Drupal service container, which leads
-    // to potential issues. We save the current container before running the
-    // discovery, and in case a change is detected, reset it and raise
-    // warnings so that developers can tune their data provider code.
-    if (\Drupal::hasContainer()) {
-      $container = \Drupal::getContainer();
-      $containerObjectId = spl_object_id($container);
-    }
-    $phpUnitTestSuite = (new TestSuiteBuilder())->build($phpUnitConfiguration);
-    if (isset($containerObjectId) && $containerObjectId !== spl_object_id(\Drupal::getContainer())) {
-      $this->warnings[] = '*** The service container was changed during the test discovery ***';
-      $this->warnings[] = 'Probably a test data provider method called \\Drupal::setContainer.';
-      $this->warnings[] = 'Ensure that all the data providers restore the original container before returning data.';
-      assert(isset($container));
-      \Drupal::setContainer($container);
-    }
-
-    $list = $directory === NULL ?
-      $this->getTestList($phpUnitTestSuite, $extension) :
-      $this->getTestListLimitedToDirectory($phpUnitTestSuite, $extension, $testSuites);
-
-    // Sort the groups and tests within the groups by name.
-    uksort($list, 'strnatcasecmp');
-    foreach ($list as &$tests) {
-      uksort($tests, 'strnatcasecmp');
-    }
-
-    return $list;
-  }
-
-  /**
-   * Discovers all class files in all available extensions.
-   *
-   * @param string|null $extension
-   *   (optional) The name of an extension to limit discovery to; e.g., 'node'.
-   * @param string|null $directory
-   *   (optional) Limit discovered tests to a specific directory.
-   *
-   * @return array
-   *   A classmap containing all discovered class files; i.e., a map of
-   *   fully-qualified classnames to path names.
-   */
-  public function findAllClassFiles(?string $extension = NULL, ?string $directory = NULL): array {
-    $testClasses = $this->getTestClasses($extension, [], $directory);
-    $classMap = [];
-    foreach ($testClasses as $group) {
-      foreach ($group as $className => $info) {
-        $classMap[$className] = $info['file'];
-      }
-    }
-    return $classMap;
-  }
-
-  /**
-   * Returns the warnings generated during the discovery.
-   *
-   * @return list<string>
-   *   The warnings.
-   */
-  public function getWarnings(): array {
-    return $this->warnings;
-  }
-
-  /**
-   * Returns a list of tests from a TestSuite object.
-   *
-   * @param \PHPUnit\Framework\TestSuite $phpUnitTestSuite
-   *   The TestSuite object returned by PHPUnit test discovery.
-   * @param string|null $extension
-   *   The name of an extension to limit discovery to; e.g., 'node'.
-   *
-   * @return array<string<array<class-string, array{name: class-string, description: string, group: string|int, groups: list<string|int>, type: string, file: string, tests_count: positive-int}>>>
-   *   An array of test groups keyed by the group name. Each test group is an
-   *   array of test class information arrays as returned by
-   *   ::getTestClassInfo(), keyed by test class. If a test class belongs to
-   *   multiple groups, it will appear under all group keys it belongs to.
-   */
-  private function getTestList(TestSuite $phpUnitTestSuite, ?string $extension): array {
-    $list = [];
-    foreach ($phpUnitTestSuite->tests() as $testSuite) {
-      foreach ($testSuite->tests() as $testClass) {
-        if ($extension !== NULL && !str_starts_with($testClass->name(), "Drupal\\Tests\\{$extension}\\")) {
-          continue;
-        }
-
-        $item = $this->getTestClassInfo(
-          $testClass,
-          $this->reverseMap[$testSuite->name()] ?? $testSuite->name(),
-        );
-
-        foreach ($item['groups'] as $group) {
-          $list[$group][$item['name']] = $item;
-        }
-      }
-    }
-    return $list;
-  }
-
-  /**
-   * Returns a list of tests from a TestSuite object limited to a directory.
-   *
-   * @param \PHPUnit\Framework\TestSuite $phpUnitTestSuite
-   *   The TestSuite object returned by PHPUnit test discovery.
-   * @param string|null $extension
-   *   The name of an extension to limit discovery to; e.g., 'node'.
-   * @param list<string> $testSuites
-   *   An array of PHPUnit test suites to filter the discovery for.
-   *
-   * @return array<string<array<class-string, array{name: class-string, description: string, group: string|int, groups: list<string|int>, type: string, file: string, tests_count: positive-int}>>>
-   *   An array of test groups keyed by the group name. Each test group is an
-   *   array of test class information arrays as returned by
-   *   ::getTestClassInfo(), keyed by test class. If a test class belongs to
-   *   multiple groups, it will appear under all group keys it belongs to.
-   */
-  private function getTestListLimitedToDirectory(TestSuite $phpUnitTestSuite, ?string $extension, array $testSuites): array {
-    $list = [];
-
-    // In this case, PHPUnit found a single test class to run tests for.
-    if ($phpUnitTestSuite->isForTestClass()) {
-      if ($extension !== NULL && !str_starts_with($phpUnitTestSuite->name(), "Drupal\\Tests\\{$extension}\\")) {
-        return [];
-      }
-
-      // Take the test suite name from the class namespace.
-      $testSuite = 'PHPUnit-' . TestDiscovery::getPhpunitTestSuite($phpUnitTestSuite->name());
-      if (!empty($testSuites) && !in_array($testSuite, $testSuites, TRUE)) {
-        return [];
-      }
-
-      $item = $this->getTestClassInfo($phpUnitTestSuite, $testSuite);
-
-      foreach ($item['groups'] as $group) {
-        $list[$group][$item['name']] = $item;
-      }
-      return $list;
-    }
-
-    // Multiple test classes were found.
-    $list = [];
-    foreach ($phpUnitTestSuite->tests() as $testClass) {
-      if ($extension !== NULL && !str_starts_with($testClass->name(), "Drupal\\Tests\\{$extension}\\")) {
-        continue;
-      }
-
-      // Take the test suite name from the class namespace.
-      $testSuite = 'PHPUnit-' . TestDiscovery::getPhpunitTestSuite($testClass->name());
-      if (!empty($testSuites) && !in_array($testSuite, $testSuites, TRUE)) {
-        continue;
-      }
-
-      $item = $this->getTestClassInfo($testClass, $testSuite);
-
-      foreach ($item['groups'] as $group) {
-        $list[$group][$item['name']] = $item;
-      }
-    }
-    return $list;
-
-  }
-
-  /**
-   * Returns the test class information.
-   *
-   * @param \PHPUnit\Framework\Test $testClass
-   *   The test class.
-   * @param string $testSuite
-   *   The test suite of this test class.
-   *
-   * @return array{name: class-string, description: string, group: string|int, groups: list<string|int>, type: string, file: string, tests_count: positive-int}
-   *   The test class information.
-   */
-  private function getTestClassInfo(Test $testClass, string $testSuite): array {
-    $reflection = new \ReflectionClass($testClass->name());
-
-    // Let PHPUnit API return the groups, as it will deal transparently with
-    // annotations or attributes, but skip groups generated by PHPUnit
-    // internally and starting with a double underscore prefix.
-    if (RunnerVersion::getMajor() < 11) {
-      $groups = array_filter($testClass->groups(), function (string $value): bool {
-        return !str_starts_with($value, '__phpunit');
-      });
-    }
-    else {
-      // In PHPUnit 11+, we need to coalesce the groups from individual tests
-      // as they may not be available from the test class level (when tests are
-      // backed by data providers).
-      $tmp = [];
-      foreach ($testClass as $test) {
-        if ($test instanceof DataProviderTestSuite) {
-          foreach ($test as $testWithData) {
-            $tmp = array_merge($tmp, $testWithData->groups());
-          }
-        }
-        else {
-          $tmp = array_merge($tmp, $test->groups());
-        }
-      }
-      $groups = array_filter(array_unique($tmp), function (string $value): bool {
-        return !str_starts_with($value, '__phpunit');
-      });
-    }
-    if (empty($groups)) {
-      throw new MissingGroupException(sprintf('Missing group metadata in test class %s', $testClass->name()));
-    }
-
-    // Let PHPUnit API return the class coverage information.
-    $test = $testClass;
-    while (!$test instanceof TestCase) {
-      $test = $test->tests()[0];
-    }
-    if (($metadata = $test->valueObjectForEvents()->metadata()->isCoversClass()) && $metadata->isNotEmpty()) {
-      $description = sprintf('Tests %s.', $metadata->asArray()[0]->className());
-    }
-    elseif (($metadata = $test->valueObjectForEvents()->metadata()->isCoversDefaultClass()) && $metadata->isNotEmpty()) {
-      $description = sprintf('Tests %s.', $metadata->asArray()[0]->className());
-    }
-    else {
-      $description = TestDiscovery::parseTestClassSummary($reflection->getDocComment());
-    }
-
-    // Find the test cases count.
-    $count = 0;
-    foreach ($testClass->tests() as $testCase) {
-      if ($testCase instanceof TestCase) {
-        // If it's a straight test method, counts 1.
-        $count++;
-      }
-      else {
-        // It's a data provider test suite, count 1 per data set provided.
-        $count += count($testCase->tests());
-      }
-    }
-
-    return [
-      'name' => $testClass->name(),
-      'group' => $groups[0],
-      'groups' => $groups,
-      'type' => $testSuite,
-      'description' => $description,
-      'file' => $reflection->getFileName(),
-      'tests_count' => $count,
-    ];
-  }
-
-}
diff --git a/core/lib/Drupal/Core/Test/RunTests/TestFileParser.php b/core/lib/Drupal/Core/Test/RunTests/TestFileParser.php
index 8ab5260aa660eefec6f7b9bae2b0ad7bcab3993d..12aa757e57ee9db3b355418b182e927a1efbfafc 100644
--- a/core/lib/Drupal/Core/Test/RunTests/TestFileParser.php
+++ b/core/lib/Drupal/Core/Test/RunTests/TestFileParser.php
@@ -4,16 +4,9 @@
 
 use PHPUnit\Framework\TestCase;
 
-@trigger_error('Drupal\Core\Test\RunTests\TestFileParser is deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. There is no replacement. See https://www.drupal.org/node/3447698', E_USER_DEPRECATED);
-
 /**
  * Parses class names from PHP files without loading them.
  *
- * @deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. There is no
- *   replacement.
- *
- * @see https://www.drupal.org/node/3447698
- *
  * @internal
  */
 class TestFileParser {
diff --git a/core/lib/Drupal/Core/Test/TestDiscovery.php b/core/lib/Drupal/Core/Test/TestDiscovery.php
index 468256779b311ecc50937b1d5ef44733a3e2258c..1347d0c583f4501152b8196f269e39c14845deb1 100644
--- a/core/lib/Drupal/Core/Test/TestDiscovery.php
+++ b/core/lib/Drupal/Core/Test/TestDiscovery.php
@@ -7,7 +7,6 @@
 use Drupal\Component\Utility\NestedArray;
 use Drupal\Core\Extension\ExtensionDiscovery;
 use Drupal\Core\Test\Exception\MissingGroupException;
-use PHPUnit\Framework\Attributes\Group;
 
 /**
  * Discovers available tests.
@@ -27,11 +26,6 @@ class TestDiscovery {
    * Statically cached list of test classes.
    *
    * @var array
-   *
-   * @deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. There is
-   *   no replacement.
-   *
-   * @see https://www.drupal.org/node/3447698
    */
   protected $testClasses;
 
@@ -155,14 +149,8 @@ public function registerTestNamespaces() {
    *
    * @todo Remove singular grouping; retain list of groups in 'group' key.
    * @see https://www.drupal.org/node/2296615
-   *
-   * @deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. Use
-   *   PhpUnitTestDiscovery::getTestClasses() instead.
-   *
-   * @see https://www.drupal.org/node/3447698
    */
   public function getTestClasses($extension = NULL, array $types = [], ?string $directory = NULL) {
-    @trigger_error(__METHOD__ . '() is deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. Use PhpUnitTestDiscovery::getTestClasses() instead. See https://www.drupal.org/node/3447698', E_USER_DEPRECATED);
     if (!isset($extension) && empty($types)) {
       if (!empty($this->testClasses)) {
         return $this->testClasses;
@@ -187,15 +175,6 @@ public function getTestClasses($extension = NULL, array $types = [], ?string $di
       catch (MissingGroupException $e) {
         // If the class name ends in Test and is not a migrate table dump.
         if (str_ends_with($classname, 'Test') && !str_contains($classname, 'migrate_drupal\Tests\Table')) {
-          $reflection = new \ReflectionClass($classname);
-          $groupAttributes = $reflection->getAttributes(Group::class, \ReflectionAttribute::IS_INSTANCEOF);
-          if (!empty($groupAttributes)) {
-            $group = '##no-group-annotations';
-            $info['group'] = $group;
-            $info['groups'] = [$group];
-            $list[$group][$classname] = $info;
-            continue;
-          }
           throw $e;
         }
         // If the class is @group annotation just skip it. Most likely it is an
@@ -237,14 +216,8 @@ public function getTestClasses($extension = NULL, array $types = [], ?string $di
    * @return array
    *   A classmap containing all discovered class files; i.e., a map of
    *   fully-qualified classnames to path names.
-   *
-   * @deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. Use
-   *   PhpUnitTestDiscovery::findAllClassFiles() instead.
-   *
-   * @see https://www.drupal.org/node/3447698
    */
   public function findAllClassFiles($extension = NULL, ?string $directory = NULL) {
-    @trigger_error(__METHOD__ . '() is deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. Use PhpUnitTestDiscovery::findAllClassFiles() instead. See https://www.drupal.org/node/3447698', E_USER_DEPRECATED);
     $classmap = [];
     $namespaces = $this->registerTestNamespaces();
     if (isset($extension)) {
@@ -283,14 +256,8 @@ public function findAllClassFiles($extension = NULL, ?string $directory = NULL)
    *
    * @todo Limit to '*Test.php' files (~10% less files to reflect/introspect).
    * @see https://www.drupal.org/node/2296635
-   *
-   * @deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. There is
-   *   no replacement.
-   *
-   * @see https://www.drupal.org/node/3447698
    */
   public static function scanDirectory($namespace_prefix, $path) {
-    @trigger_error(__METHOD__ . '() is deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. There is no replacement. See https://www.drupal.org/node/3447698', E_USER_DEPRECATED);
     if (!str_ends_with($namespace_prefix, '\\')) {
       throw new \InvalidArgumentException("Namespace prefix for $path must contain a trailing namespace separator.");
     }
@@ -345,14 +312,8 @@ public static function scanDirectory($namespace_prefix, $path) {
    *
    * @throws \Drupal\Core\Test\Exception\MissingGroupException
    *   If the class does not have a @group annotation.
-   *
-   * @deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. There is
-   *   no replacement.
-   *
-   * @see https://www.drupal.org/node/3447698
    */
   public static function getTestInfo($classname, $doc_comment = NULL) {
-    @trigger_error(__METHOD__ . '() is deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. There is no replacement. See https://www.drupal.org/node/3447698', E_USER_DEPRECATED);
     if ($doc_comment === NULL) {
       $reflection = new \ReflectionClass($classname);
       $doc_comment = $reflection->getDocComment();
@@ -389,7 +350,7 @@ public static function getTestInfo($classname, $doc_comment = NULL) {
     $info['type'] = 'PHPUnit-' . static::getPhpunitTestSuite($classname);
 
     if (!empty($annotations['coversDefaultClass'])) {
-      $info['description'] = 'Tests ' . ltrim($annotations['coversDefaultClass']) . '.';
+      $info['description'] = 'Tests ' . $annotations['coversDefaultClass'] . '.';
     }
     else {
       $info['description'] = static::parseTestClassSummary($doc_comment);
diff --git a/core/modules/language/tests/src/Kernel/Migrate/d7/MigrateLanguageNegotiationSettingsTest.php b/core/modules/language/tests/src/Kernel/Migrate/d7/MigrateLanguageNegotiationSettingsTest.php
index fe5ff0ca0627f2c655dc3e7825ea9f8364982067..54fdf4b0d21d14b51e4375dd14b935341e2b5b13 100644
--- a/core/modules/language/tests/src/Kernel/Migrate/d7/MigrateLanguageNegotiationSettingsTest.php
+++ b/core/modules/language/tests/src/Kernel/Migrate/d7/MigrateLanguageNegotiationSettingsTest.php
@@ -10,7 +10,6 @@
 /**
  * Tests the migration of language negotiation.
  *
- * @group #slow
  * @group migrate_drupal_7
  */
 class MigrateLanguageNegotiationSettingsTest extends MigrateDrupal7TestBase {
diff --git a/core/modules/link/tests/src/Functional/LinkFieldUITest.php b/core/modules/link/tests/src/Functional/LinkFieldUITest.php
index 5c78abc23910b006d510cccdd435a772ae85f886..694fb6b3677462b6d7941725a13a95fd7b0d5641 100644
--- a/core/modules/link/tests/src/Functional/LinkFieldUITest.php
+++ b/core/modules/link/tests/src/Functional/LinkFieldUITest.php
@@ -15,7 +15,6 @@
  * Tests link field UI functionality.
  *
  * @group link
- * @group #slow
  */
 class LinkFieldUITest extends BrowserTestBase {
 
diff --git a/core/modules/package_manager/tests/src/Kernel/SupportedReleaseValidatorTest.php b/core/modules/package_manager/tests/src/Kernel/SupportedReleaseValidatorTest.php
index 2e9a0977fa36d168b89e5c5e625c076b49f2698d..90348cdfdd3cf5e5c131f8ef343df202565a9215 100644
--- a/core/modules/package_manager/tests/src/Kernel/SupportedReleaseValidatorTest.php
+++ b/core/modules/package_manager/tests/src/Kernel/SupportedReleaseValidatorTest.php
@@ -13,6 +13,7 @@
  * @coversDefaultClass \Drupal\package_manager\Validator\SupportedReleaseValidator
  * @group #slow
  * @group package_manager
+ * @group #slow
  * @internal
  */
 class SupportedReleaseValidatorTest extends PackageManagerKernelTestBase {
diff --git a/core/modules/path/tests/src/Kernel/Migrate/d6/MigrateUrlAliasTest.php b/core/modules/path/tests/src/Kernel/Migrate/d6/MigrateUrlAliasTest.php
index be5d811fe5434465b1cf64559fac4237a304854a..d5cc9759ab182f22442624a75beda5c642de91db 100644
--- a/core/modules/path/tests/src/Kernel/Migrate/d6/MigrateUrlAliasTest.php
+++ b/core/modules/path/tests/src/Kernel/Migrate/d6/MigrateUrlAliasTest.php
@@ -13,7 +13,6 @@
 /**
  * URL alias migration.
  *
- * @group #slow
  * @group migrate_drupal_6
  */
 class MigrateUrlAliasTest extends MigrateDrupal6TestBase {
diff --git a/core/modules/system/tests/src/Kernel/DateFormatAccessControlHandlerTest.php b/core/modules/system/tests/src/Kernel/DateFormatAccessControlHandlerTest.php
index 82d866e985e4142ab967b195f4d918b60cc06838..6c8c42da59e89e7eafa40fa45422dfeb7e4878e4 100644
--- a/core/modules/system/tests/src/Kernel/DateFormatAccessControlHandlerTest.php
+++ b/core/modules/system/tests/src/Kernel/DateFormatAccessControlHandlerTest.php
@@ -77,8 +77,6 @@ public function testAccess($permissions, $which_entity, $view_label_access_resul
    *   An array of test cases.
    */
   public static function providerTestAccess(): array {
-    $originalContainer = \Drupal::hasContainer() ? \Drupal::getContainer() : NULL;
-
     $c = new ContainerBuilder();
     $cache_contexts_manager = (new Prophet())->prophesize(CacheContextsManager::class);
     $cache_contexts_manager->assertValidTokens()->willReturn(TRUE);
@@ -86,7 +84,7 @@ public static function providerTestAccess(): array {
     $c->set('cache_contexts_manager', $cache_contexts_manager);
     \Drupal::setContainer($c);
 
-    $data = [
+    return [
       'No permission + unlocked' => [
         [],
         'unlocked',
@@ -124,13 +122,6 @@ public static function providerTestAccess(): array {
         AccessResult::allowed()->addCacheContexts(['user.permissions']),
       ],
     ];
-
-    // Restore the original container if needed.
-    if ($originalContainer) {
-      \Drupal::setContainer($originalContainer);
-    }
-
-    return $data;
   }
 
 }
diff --git a/core/modules/taxonomy/tests/src/Kernel/Migrate/d6/MigrateTermNodeTest.php b/core/modules/taxonomy/tests/src/Kernel/Migrate/d6/MigrateTermNodeTest.php
index 511778daf2003528511ecedd76cb45a6cc58b5d9..1d9654dd50508a179598ee8fa37d17dbdec5e02a 100644
--- a/core/modules/taxonomy/tests/src/Kernel/Migrate/d6/MigrateTermNodeTest.php
+++ b/core/modules/taxonomy/tests/src/Kernel/Migrate/d6/MigrateTermNodeTest.php
@@ -10,7 +10,6 @@
 /**
  * Upgrade taxonomy term node associations.
  *
- * @group #slow
  * @group migrate_drupal_6
  */
 class MigrateTermNodeTest extends MigrateDrupal6TestBase {
diff --git a/core/modules/workflows/tests/src/Kernel/WorkflowAccessControlHandlerTest.php b/core/modules/workflows/tests/src/Kernel/WorkflowAccessControlHandlerTest.php
index 180edc868f60e982735006b8796b67f31049d735..e46fbcf417bf92dcac70243a0a8eb4056917c52a 100644
--- a/core/modules/workflows/tests/src/Kernel/WorkflowAccessControlHandlerTest.php
+++ b/core/modules/workflows/tests/src/Kernel/WorkflowAccessControlHandlerTest.php
@@ -124,8 +124,6 @@ public function testCheckAccess($user, $operation, $result, $states_to_create =
    *   An array of test data.
    */
   public static function checkAccessProvider() {
-    $originalContainer = \Drupal::hasContainer() ? \Drupal::getContainer() : NULL;
-
     $container = new ContainerBuilder();
     $cache_contexts_manager = (new Prophet())->prophesize(CacheContextsManager::class);
     $cache_contexts_manager->assertValidTokens()->willReturn(TRUE);
@@ -133,7 +131,7 @@ public static function checkAccessProvider() {
     $container->set('cache_contexts_manager', $cache_contexts_manager);
     \Drupal::setContainer($container);
 
-    $data = [
+    return [
       'Admin view' => [
         'adminUser',
         'view',
@@ -277,13 +275,6 @@ public static function checkAccessProvider() {
         AccessResult::allowed()->addCacheContexts(['user.permissions']),
       ],
     ];
-
-    // Restore the original container if needed.
-    if ($originalContainer) {
-      \Drupal::setContainer($originalContainer);
-    }
-
-    return $data;
   }
 
 }
diff --git a/core/scripts/run-tests.sh b/core/scripts/run-tests.sh
index 96f16eed9c712ce15cfd00f62fc794974b4fe8a1..4545a00cc3ac1b512ea5b12b141531513a31def9 100755
--- a/core/scripts/run-tests.sh
+++ b/core/scripts/run-tests.sh
@@ -17,13 +17,14 @@
 use Drupal\Core\Composer\Composer;
 use Drupal\Core\Database\Database;
 use Drupal\Core\Test\EnvironmentCleaner;
-use Drupal\Core\Test\PhpUnitTestDiscovery;
 use Drupal\Core\Test\PhpUnitTestRunner;
 use Drupal\Core\Test\SimpletestTestRunResultsStorage;
+use Drupal\Core\Test\RunTests\TestFileParser;
 use Drupal\Core\Test\TestDatabase;
 use Drupal\Core\Test\TestRun;
 use Drupal\Core\Test\TestRunnerKernel;
 use Drupal\Core\Test\TestRunResultsStorageInterface;
+use Drupal\Core\Test\TestDiscovery;
 use Drupal\BuildTests\Framework\BuildTestBase;
 use Drupal\FunctionalJavascriptTests\WebDriverTestBase;
 use Drupal\KernelTests\KernelTestBase;
@@ -48,10 +49,6 @@
 const SIMPLETEST_SCRIPT_COLOR_YELLOW = 33;
 // A refreshing cyan.
 const SIMPLETEST_SCRIPT_COLOR_CYAN = 36;
-// A fainting gray.
-const SIMPLETEST_SCRIPT_COLOR_GRAY = 90;
-// A notable white.
-const SIMPLETEST_SCRIPT_COLOR_BRIGHT_WHITE = "1;97";
 
 // Restricting the chunk of queries prevents memory exhaustion.
 const SIMPLETEST_SCRIPT_SQLITE_VARIABLE_LIMIT = 350;
@@ -89,12 +86,12 @@
   // Display all available tests organized by one @group annotation.
   echo "\nAvailable test groups & classes\n";
   echo "-------------------------------\n\n";
-  $test_discovery = new PhpUnitTestDiscovery(\Drupal::root() . \DIRECTORY_SEPARATOR . 'core');
+  $test_discovery = new TestDiscovery(
+    \Drupal::root(),
+    \Drupal::service('class_loader')
+  );
   try {
     $groups = $test_discovery->getTestClasses($args['module']);
-    foreach ($test_discovery->getWarnings() as $warning) {
-      simpletest_script_print($warning . "\n", SIMPLETEST_SCRIPT_COLOR_EXCEPTION);
-    }
   }
   catch (Exception $e) {
     error_log((string) $e);
@@ -122,8 +119,11 @@
 // @see https://www.drupal.org/node/2569585
 if ($args['list-files'] || $args['list-files-json']) {
   // List all files which could be run as tests.
-  $test_discovery = new PhpUnitTestDiscovery(\Drupal::root() . \DIRECTORY_SEPARATOR . 'core');
-  // PhpUnitTestDiscovery::findAllClassFiles() gives us a classmap similar to a
+  $test_discovery = new TestDiscovery(
+    \Drupal::root(),
+    \Drupal::service('class_loader')
+  );
+  // TestDiscovery::findAllClassFiles() gives us a classmap similar to a
   // Composer 'classmap' array.
   $test_classes = $test_discovery->findAllClassFiles();
   // JSON output is the easiest.
@@ -177,15 +177,6 @@
   exit(SIMPLETEST_SCRIPT_EXIT_FAILURE);
 }
 
-echo "\n";
-echo "Drupal test run\n\n";
-echo sprintf("Drupal Version:  %s\n", \Drupal::VERSION);
-echo sprintf("PHP Version:     %s\n", \PHP_VERSION);
-echo sprintf("PHP Binary:      %s\n", $php ?? getenv('_'));
-echo sprintf("PHPUnit Version: %s\n", Version::id());
-echo "-------------------------------\n";
-echo "\n";
-
 $test_list = simpletest_script_get_test_list();
 
 // Try to allocate unlimited time to run the tests.
@@ -364,11 +355,6 @@ function simpletest_script_help(): void {
 
               The index of the job in the job set.
 
-  --debug-discovery
-
-              If provided, dumps detailed information on the tests selected
-              for execution, before the execution starts.
-
   <test1>[,<test2>[,<test3> ...]]
 
               One or more tests to be run. By default, these are interpreted
@@ -441,7 +427,6 @@ function simpletest_script_parse_args() {
     'non-html' => FALSE,
     'ci-parallel-node-index' => 1,
     'ci-parallel-node-total' => 1,
-    'debug-discovery' => FALSE,
   ];
 
   // Override with set values.
@@ -934,15 +919,17 @@ function simpletest_script_command(TestRun $test_run, string $test_class): array
 function simpletest_script_get_test_list() {
   global $args;
 
-  $test_discovery = new PhpUnitTestDiscovery(\Drupal::root() . \DIRECTORY_SEPARATOR . 'core');
+  $test_discovery = new TestDiscovery(
+    \Drupal::root(),
+    \Drupal::service('class_loader')
+  );
+  $types_processed = empty($args['types']);
   $test_list = [];
   $slow_tests = [];
   if ($args['all'] || $args['module'] || $args['directory']) {
     try {
       $groups = $test_discovery->getTestClasses($args['module'], $args['types'], $args['directory']);
-      foreach ($test_discovery->getWarnings() as $warning) {
-        simpletest_script_print($warning . "\n", SIMPLETEST_SCRIPT_COLOR_EXCEPTION);
-      }
+      $types_processed = TRUE;
     }
     catch (Exception $e) {
       echo (string) $e;
@@ -951,34 +938,30 @@ function simpletest_script_get_test_list() {
     // Ensure that tests marked explicitly as @group #slow are run at the
     // beginning of each job.
     if (key($groups) === '#slow') {
-      $slow_tests = array_shift($groups);
+      $slow_tests = array_keys(array_shift($groups));
     }
     $not_slow_tests = [];
     foreach ($groups as $group => $tests) {
-      $not_slow_tests = array_merge($not_slow_tests, $tests);
+      $not_slow_tests = array_merge($not_slow_tests, array_keys($tests));
     }
     // Filter slow tests out of the not slow tests and ensure a unique list
     // since tests may appear in more than one group.
-    $not_slow_tests = array_diff_key($not_slow_tests, $slow_tests);
+    $not_slow_tests = array_unique(array_diff($not_slow_tests, $slow_tests));
 
     // If the tests are not being run in parallel, then ensure slow tests run
     // all together first.
     if ((int) $args['ci-parallel-node-total'] <= 1 ) {
       sort_tests_by_type_and_methods($slow_tests);
       sort_tests_by_type_and_methods($not_slow_tests);
-      $all_tests_list = array_merge($slow_tests, $not_slow_tests);
-      assign_tests_sequence($all_tests_list);
-      dump_tests_sequence($all_tests_list, $args);
-      $test_list = array_keys($all_tests_list);
+      $test_list = array_merge($slow_tests, $not_slow_tests);
     }
     else {
-      // Sort all tests by the number of test cases on the test class.
-      // This is used in combination with @group #slow to start the slowest
-      // tests first and distribute tests between test runners.
+      // Sort all tests by the number of public methods on the test class.
+      // This is a proxy for the approximate time taken to run the test,
+      // which is used in combination with @group #slow to start the slowest tests
+      // first and distribute tests between test runners.
       sort_tests_by_public_method_count($slow_tests);
       sort_tests_by_public_method_count($not_slow_tests);
-      $all_tests_list = array_merge($slow_tests, $not_slow_tests);
-      assign_tests_sequence($all_tests_list);
 
       // Now set up a bin per test runner.
       $bin_count = (int) $args['ci-parallel-node-total'];
@@ -992,8 +975,6 @@ function simpletest_script_get_test_list() {
       $binned_other_tests = place_tests_into_bins($not_slow_tests, $bin_count);
       $other_tests_for_job = $binned_other_tests[$args['ci-parallel-node-index'] - 1];
       $test_list = array_merge($slow_tests_for_job, $other_tests_for_job);
-      dump_bin_tests_sequence($args['ci-parallel-node-index'], $all_tests_list, $test_list, $args);
-      $test_list = array_keys($test_list);
     }
   }
   else {
@@ -1007,9 +988,6 @@ function simpletest_script_get_test_list() {
         else {
           try {
             $groups = $test_discovery->getTestClasses(NULL, $args['types']);
-            foreach ($test_discovery->getWarnings() as $warning) {
-              simpletest_script_print($warning . "\n", SIMPLETEST_SCRIPT_COLOR_EXCEPTION);
-            }
           }
           catch (Exception $e) {
             echo (string) $e;
@@ -1027,24 +1005,19 @@ function simpletest_script_get_test_list() {
     }
     elseif ($args['file']) {
       // Extract test case class names from specified files.
+      $parser = new TestFileParser();
       foreach ($args['test_names'] as $file) {
-        if (!file_exists($file) || is_dir($file)) {
+        if (!file_exists($file)) {
           simpletest_script_print_error('File not found: ' . $file);
           exit(SIMPLETEST_SCRIPT_EXIT_FAILURE);
         }
-        $fileTests = current($test_discovery->getTestClasses(NULL, [], $file));
-        $test_list = array_merge($test_list, $fileTests);
+        $test_list = array_merge($test_list, $parser->getTestListFromFile($file));
       }
-      assign_tests_sequence($test_list);
-      dump_tests_sequence($test_list, $args);
-      $test_list = array_keys($test_list);
     }
     else {
       try {
         $groups = $test_discovery->getTestClasses(NULL, $args['types']);
-        foreach ($test_discovery->getWarnings() as $warning) {
-          simpletest_script_print($warning . "\n", SIMPLETEST_SCRIPT_COLOR_EXCEPTION);
-        }
+        $types_processed = TRUE;
       }
       catch (Exception $e) {
         echo (string) $e;
@@ -1061,15 +1034,22 @@ function simpletest_script_get_test_list() {
       }
       // Merge the tests from the groups together.
       foreach ($args['test_names'] as $group_name) {
-        $test_list = array_merge($test_list, $groups[$group_name]);
+        $test_list = array_merge($test_list, array_keys($groups[$group_name]));
       }
-      assign_tests_sequence($test_list);
-      dump_tests_sequence($test_list, $args);
       // Ensure our list of tests contains only one entry for each test.
-      $test_list = array_keys($test_list);
+      $test_list = array_unique($test_list);
     }
   }
 
+  // If the test list creation does not automatically limit by test type then
+  // we need to do so here.
+  if (!$types_processed) {
+    $test_list = array_filter($test_list, function ($test_class) use ($args) {
+      $test_info = TestDiscovery::getTestInfo($test_class);
+      return in_array($test_info['type'], $args['types'], TRUE);
+    });
+  }
+
   if (empty($test_list)) {
     simpletest_script_print_error('No valid tests were specified.');
     exit(SIMPLETEST_SCRIPT_EXIT_FAILURE);
@@ -1082,11 +1062,11 @@ function simpletest_script_get_test_list() {
  * Sort tests by test type and number of public methods.
  */
 function sort_tests_by_type_and_methods(array &$tests): void {
-  uasort($tests, function ($a, $b) {
-    if (get_test_type_weight($a['name']) === get_test_type_weight($b['name'])) {
-      return $b['tests_count'] <=> $a['tests_count'];
+  usort($tests, function ($a, $b) {
+    if (get_test_type_weight($a) === get_test_type_weight($b)) {
+      return get_test_class_method_count($b) <=> get_test_class_method_count($a);
     }
-    return get_test_type_weight($b['name']) <=> get_test_type_weight($a['name']);
+    return get_test_type_weight($b) <=> get_test_type_weight($a);
   });
 }
 
@@ -1103,8 +1083,8 @@ function sort_tests_by_type_and_methods(array &$tests): void {
  *   An array of test class names.
  */
 function sort_tests_by_public_method_count(array &$tests): void {
-  uasort($tests, function ($a, $b) {
-    return $b['tests_count'] <=> $a['tests_count'];
+  usort($tests, function ($a, $b) {
+    return get_test_class_method_count($b) <=> get_test_class_method_count($a);
   });
 }
 
@@ -1125,46 +1105,28 @@ function get_test_type_weight(string $class): int {
 }
 
 /**
- * Assigns the test sequence.
+ * Get an approximate test method count for a test class.
  *
- * @param array $tests
- *   The array of test class info.
- */
-function assign_tests_sequence(array &$tests): void {
-  $i = 0;
-  foreach ($tests as &$testInfo) {
-    $testInfo['sequence'] = ++$i;
-  }
-}
-
-/**
- * Dumps the list of tests in order of execution after sorting.
- *
- * @param array $tests
- *   The array of test class info.
- * @param array $args
- *   The command line arguments.
+ * @param string $class
+ *   The test class name.
  */
-function dump_tests_sequence(array $tests, array $args): void {
-  if ($args['debug-discovery'] === FALSE) {
-    return;
-  }
-  echo "Test execution sequence\n";
-  echo "-----------------------\n\n";
-  echo " Seq Slow? Group            Cnt Class\n";
-  echo "-----------------------------------------\n";
-  $i = 0;
-  foreach ($tests as $testInfo) {
-    echo sprintf(
-      "%4d %5s %15s %4d %s\n",
-      $testInfo['sequence'],
-      in_array('#slow', $testInfo['groups']) ? '#slow' : '',
-      trim_with_ellipsis($testInfo['group'], 15, \STR_PAD_RIGHT),
-      $testInfo['tests_count'],
-      trim_with_ellipsis($testInfo['name'], 60, \STR_PAD_LEFT),
-    );
+function get_test_class_method_count(string $class): int {
+  $reflection = new \ReflectionClass($class);
+  $count = 0;
+  foreach ($reflection->getMethods(\ReflectionMethod::IS_PUBLIC) as $method) {
+    // If a method uses a dataProvider, increase the count by 20 since data
+    // providers result in a single method running multiple times.
+    $comments = $method->getDocComment();
+    preg_match_all('#@(.*?)\n#s', $comments, $annotations);
+    foreach ($annotations[1] as $annotation) {
+      if (str_starts_with($annotation, 'dataProvider')) {
+        $count = $count + 20;
+        continue;
+      }
+    }
+    $count++;
   }
-  echo "-----------------------------------------\n\n";
+  return $count;
 }
 
 /**
@@ -1187,50 +1149,12 @@ function place_tests_into_bins(array $tests, int $bin_count) {
   // Create a bin corresponding to each parallel test job.
   $bins = array_fill(0, $bin_count, []);
   // Go through each test and add them to one bin at a time.
-  $i = 0;
   foreach ($tests as $key => $test) {
-    $bins[($i++ % $bin_count)][$key] = $test;
+    $bins[($key % $bin_count)][] = $test;
   }
   return $bins;
 }
 
-/**
- * Dumps the list of tests in order of execution for a bin.
- *
- * @param int $bin
- *   The bin.
- * @param array $allTests
- *   The list of all test classes discovered.
- * @param array $tests
- *   The list of test class to run for this bin.
- * @param array $args
- *   The command line arguments.
- */
-function dump_bin_tests_sequence(int $bin, array $allTests, array $tests, array $args): void {
-  if ($args['debug-discovery'] === FALSE) {
-    return;
-  }
-  echo "Test execution sequence. ";
-  echo "Tests marked *** will be executed in this PARALLEL BIN #{$bin}.\n";
-  echo "-------------------------------------------------------------------------------------\n\n";
-  echo "Bin  Seq Slow? Group            Cnt Class\n";
-  echo "--------------------------------------------\n";
-  foreach ($allTests as $testInfo) {
-    $inBin = isset($tests[$testInfo['name']]);
-    $message = sprintf(
-      "%s %4d %5s %15s %4d %s\n",
-      $inBin ? "***" : "   ",
-      $testInfo['sequence'],
-      in_array('#slow', $testInfo['groups']) ? '#slow' : '',
-      trim_with_ellipsis($testInfo['group'], 15, \STR_PAD_RIGHT),
-      $testInfo['tests_count'],
-      trim_with_ellipsis($testInfo['name'], 60, \STR_PAD_LEFT),
-    );
-    simpletest_script_print($message, $inBin ? SIMPLETEST_SCRIPT_COLOR_BRIGHT_WHITE : SIMPLETEST_SCRIPT_COLOR_GRAY);
-  }
-  echo "-------------------------------------------------\n\n";
-}
-
 /**
  * Initialize the reporter.
  */
@@ -1246,6 +1170,12 @@ function simpletest_script_reporter_init(): void {
     'debug' => 'Log',
   ];
 
+  echo "\n";
+  echo "Drupal test run\n";
+  echo "Using PHP Binary: $php\n";
+  echo "---------------\n";
+  echo "\n";
+
   // Tell the user about what tests are to be run.
   if ($args['all']) {
     echo "All tests will run.\n\n";
@@ -1448,7 +1378,7 @@ function simpletest_script_reporter_display_results(TestRunResultsStorageInterfa
 function simpletest_script_format_result($result): void {
   global $args, $results_map, $color;
 
-  $summary = sprintf("%-9.9s %9.3fs %s\n", $results_map[$result->status], $result->time, trim_with_ellipsis($result->function, 80, STR_PAD_LEFT));
+  $summary = sprintf("%-9.9s %9.3fs %-80.80s\n", $results_map[$result->status], $result->time, trim_with_ellipsis($result->function, 80, STR_PAD_LEFT));
 
   simpletest_script_print($summary, simpletest_script_color_code($result->status));
 
@@ -1610,12 +1540,12 @@ function simpletest_script_load_messages_by_test_id(TestRunResultsStorageInterfa
  */
 function trim_with_ellipsis(string $input, int $length, int $side): string {
   if (strlen($input) < $length) {
-      return str_pad($input, $length, ' ', \STR_PAD_RIGHT);
+      return str_pad($input, $length, ' ', STR_PAD_RIGHT);
   }
   elseif (strlen($input) > $length) {
       return match($side) {
-        \STR_PAD_RIGHT => substr($input, 0, $length - 1) . '…',
-        default => '…' . substr($input, -$length + 1),
+        STR_PAD_RIGHT => substr($input, 0, $length - 3) . '...',
+        default => '...' . substr($input, -$length + 3),
       };
   }
   return $input;
diff --git a/core/tests/Drupal/KernelTests/Core/Test/PhpUnitApiFindAllClassFilesTest.php b/core/tests/Drupal/KernelTests/Core/Test/PhpUnitApiFindAllClassFilesTest.php
deleted file mode 100644
index feb6addef2a32c7405d76755ca9511a8d1bd50a8..0000000000000000000000000000000000000000
--- a/core/tests/Drupal/KernelTests/Core/Test/PhpUnitApiFindAllClassFilesTest.php
+++ /dev/null
@@ -1,72 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-namespace Drupal\KernelTests\Core\Test;
-
-use Drupal\Core\Test\PhpUnitTestDiscovery;
-use Drupal\Core\Test\TestDiscovery;
-use Drupal\KernelTests\KernelTestBase;
-use Drupal\TestTools\PhpUnitCompatibility\RunnerVersion;
-use PHPUnit\Framework\Attributes\CoversClass;
-use PHPUnit\Framework\Attributes\DataProvider;
-use PHPUnit\Framework\Attributes\Group;
-use PHPUnit\Framework\Attributes\IgnoreDeprecations;
-
-/**
- * Tests ::findAllClassFiles() between TestDiscovery and PhpUnitTestDiscovery.
- *
- * PhpUnitTestDiscovery uses PHPUnit API to build the list of test classes,
- * while TestDiscovery uses Drupal legacy code.
- */
-#[CoversClass(PhpUnitTestDiscovery::class)]
-#[Group('TestSuites')]
-#[Group('Test')]
-#[Group('#slow')]
-class PhpUnitApiFindAllClassFilesTest extends KernelTestBase {
-
-  /**
-   * Checks that Drupal legacy and PHPUnit API based discoveries are equal.
-   */
-  #[DataProvider('argumentsProvider')]
-  #[IgnoreDeprecations]
-  public function testEquality(?string $extension = NULL, ?string $directory = NULL): void {
-    $testDiscovery = new TestDiscovery(
-      $this->container->getParameter('app.root'),
-      $this->container->get('class_loader')
-    );
-    $internalList = $testDiscovery->findAllClassFiles($extension, $directory);
-
-    // Location of PHPUnit configuration file.
-    $configurationFilePath = $this->container->getParameter('app.root') . \DIRECTORY_SEPARATOR . 'core';
-    // @todo once PHPUnit 10 is no longer used, remove the condition.
-    // @see https://www.drupal.org/project/drupal/issues/3497116
-    if (RunnerVersion::getMajor() >= 11) {
-      $configurationFilePath .= \DIRECTORY_SEPARATOR . '.phpunit-next.xml';
-    }
-
-    $phpUnitTestDiscovery = new PhpUnitTestDiscovery($configurationFilePath);
-
-    $phpUnitList = $phpUnitTestDiscovery->findAllClassFiles($extension, $directory);
-
-    // Downgrade results to make them comparable, working around bugs and
-    // additions.
-    // 1. TestDiscovery discovers non-test classes that PHPUnit does not.
-    $internalList = array_intersect_key($internalList, $phpUnitList);
-
-    $this->assertEquals($internalList, $phpUnitList);
-  }
-
-  /**
-   * Provides test data to ::testEquality.
-   */
-  public static function argumentsProvider(): \Generator {
-    yield 'All tests' => [];
-    yield 'Extension: system' => ['extension' => 'system'];
-    yield 'Extension: system, directory' => [
-      'extension' => 'system',
-      'directory' => 'core/modules/system/tests/src',
-    ];
-  }
-
-}
diff --git a/core/tests/Drupal/KernelTests/Core/Test/PhpUnitApiGetTestClassesTest.php b/core/tests/Drupal/KernelTests/Core/Test/PhpUnitApiGetTestClassesTest.php
deleted file mode 100644
index 32d21e3e6c394f71cbb192a87193bd4e22634eb7..0000000000000000000000000000000000000000
--- a/core/tests/Drupal/KernelTests/Core/Test/PhpUnitApiGetTestClassesTest.php
+++ /dev/null
@@ -1,109 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-namespace Drupal\KernelTests\Core\Test;
-
-use Drupal\Core\Test\PhpUnitTestDiscovery;
-use Drupal\Core\Test\TestDiscovery;
-use Drupal\KernelTests\KernelTestBase;
-use Drupal\TestTools\PhpUnitCompatibility\RunnerVersion;
-use PHPUnit\Framework\Attributes\CoversClass;
-use PHPUnit\Framework\Attributes\DataProvider;
-use PHPUnit\Framework\Attributes\Group;
-use PHPUnit\Framework\Attributes\IgnoreDeprecations;
-
-/**
- * Tests ::getTestClasses() between TestDiscovery and PhpPUnitTestDiscovery.
- *
- * PhpPUnitTestDiscovery uses PHPUnit API to build the list of test classes,
- * while TestDiscovery uses Drupal legacy code.
- */
-#[CoversClass(PhpUnitTestDiscovery::class)]
-#[Group('TestSuites')]
-#[Group('Test')]
-#[Group('#slow')]
-class PhpUnitApiGetTestClassesTest extends KernelTestBase {
-
-  /**
-   * Checks that Drupal legacy and PHPUnit API based discoveries are equal.
-   */
-  #[DataProvider('argumentsProvider')]
-  #[IgnoreDeprecations]
-  public function testEquality(array $suites, ?string $extension = NULL, ?string $directory = NULL): void {
-    $testDiscovery = new TestDiscovery(
-      $this->container->getParameter('app.root'),
-      $this->container->get('class_loader')
-    );
-    $internalList = $testDiscovery->getTestClasses($extension, $suites, $directory);
-
-    // Location of PHPUnit configuration file.
-    $configurationFilePath = $this->container->getParameter('app.root') . \DIRECTORY_SEPARATOR . 'core';
-    // @todo once PHPUnit 10 is no longer used, remove the condition.
-    // @see https://www.drupal.org/project/drupal/issues/3497116
-    if (RunnerVersion::getMajor() >= 11) {
-      $configurationFilePath .= \DIRECTORY_SEPARATOR . '.phpunit-next.xml';
-    }
-
-    $phpUnitTestDiscovery = new PhpUnitTestDiscovery($configurationFilePath);
-
-    $phpUnitList = $phpUnitTestDiscovery->getTestClasses($extension, $suites, $directory);
-
-    // Downgrade results to make them comparable, working around bugs and
-    // additions.
-    // 1. Remove TestDiscovery empty groups.
-    $internalList = array_filter($internalList);
-    // 2. Remove TestDiscovery '##no-group-annotations' group.
-    unset($internalList['##no-group-annotations']);
-    // 3. Remove 'file' and 'tests_count' keys from PHPUnit results.
-    foreach ($phpUnitList as &$group) {
-      foreach ($group as &$testClass) {
-        unset($testClass['file']);
-        unset($testClass['tests_count']);
-      }
-    }
-    // 4. Remove from PHPUnit results groups not found by TestDiscovery.
-    $phpUnitList = array_intersect_key($phpUnitList, $internalList);
-    // 5. Remove from PHPUnit groups classes not found by TestDiscovery.
-    foreach ($phpUnitList as $groupName => &$group) {
-      $group = array_intersect_key($group, $internalList[$groupName]);
-    }
-    // 6. Remove from PHPUnit test classes groups not found by TestDiscovery.
-    foreach ($phpUnitList as $groupName => &$group) {
-      foreach ($group as $testClassName => &$testClass) {
-        $testClass['groups'] = array_intersect_key($testClass['groups'], $internalList[$groupName][$testClassName]['groups']);
-      }
-    }
-
-    $this->assertEquals($internalList, $phpUnitList);
-  }
-
-  /**
-   * Provides test data to ::testEquality.
-   */
-  public static function argumentsProvider(): \Generator {
-    yield 'All tests' => ['suites' => []];
-    yield 'Testsuite: functional-javascript' => ['suites' => ['PHPUnit-FunctionalJavascript']];
-    yield 'Testsuite: functional' => ['suites' => ['PHPUnit-Functional']];
-    yield 'Testsuite: kernel' => ['suites' => ['PHPUnit-Kernel']];
-    yield 'Testsuite: unit' => ['suites' => ['PHPUnit-Unit']];
-    yield 'Testsuite: unit-component' => ['suites' => ['PHPUnit-Unit-Component']];
-    yield 'Testsuite: build' => ['suites' => ['PHPUnit-Build']];
-    yield 'Extension: system' => ['suites' => [], 'extension' => 'system'];
-    yield 'Extension: system, testsuite: unit' => [
-      'suites' => ['PHPUnit-Unit'],
-      'extension' => 'system',
-    ];
-    yield 'Extension: system, directory' => [
-      'suites' => [],
-      'extension' => 'system',
-      'directory' => 'core/modules/system/tests/src',
-    ];
-    yield 'Extension: system, testsuite: unit, directory' => [
-      'suites' => ['PHPUnit-Unit'],
-      'extension' => 'system',
-      'directory' => 'core/modules/system/tests/src',
-    ];
-  }
-
-}
diff --git a/core/tests/Drupal/KernelTests/Core/Test/PhpUnitTestDiscoveryTest.php b/core/tests/Drupal/KernelTests/Core/Test/PhpUnitTestDiscoveryTest.php
index d8534458049cedba4cbd3e8c5d8df0fdaa7e3ac4..705981f750798d4f69597613d37abed3c139be71 100644
--- a/core/tests/Drupal/KernelTests/Core/Test/PhpUnitTestDiscoveryTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Test/PhpUnitTestDiscoveryTest.php
@@ -7,8 +7,6 @@
 use Drupal\Core\Test\TestDiscovery;
 use Drupal\KernelTests\KernelTestBase;
 use Drupal\TestTools\PhpUnitCompatibility\RunnerVersion;
-use PHPUnit\Framework\Attributes\Group;
-use PHPUnit\Framework\Attributes\IgnoreDeprecations;
 use PHPUnit\TextUI\Configuration\Builder;
 use PHPUnit\TextUI\Configuration\TestSuiteBuilder;
 use Symfony\Component\Process\Process;
@@ -24,10 +22,11 @@
  * list thus generated, with the list generated by
  * \Drupal\Core\Test\TestDiscovery, which is used by run-tests.sh, to ensure
  * both methods will run the same tests,
+ *
+ * @group TestSuites
+ * @group Test
+ * @group #slow
  */
-#[Group('TestSuites')]
-#[Group('Test')]
-#[Group('#slow')]
 class PhpUnitTestDiscoveryTest extends KernelTestBase {
 
   private const TEST_LIST_MISMATCH_MESSAGE =
@@ -62,7 +61,6 @@ public function tearDown(): void {
   /**
    * Tests equality of test discovery between run-tests.sh and PHPUnit CLI.
    */
-  #[IgnoreDeprecations]
   public function testPhpUnitTestDiscoveryEqualsInternal(): void {
     // Drupal's test discovery, used by run-tests.sh.
     $testDiscovery = new TestDiscovery(
@@ -78,19 +76,11 @@ public function testPhpUnitTestDiscoveryEqualsInternal(): void {
     $internalList = array_unique($internalList);
     asort($internalList);
 
-    // Location of PHPUnit configuration file.
-    $configurationFilePath = $this->root . \DIRECTORY_SEPARATOR . 'core';
-    // @todo once PHPUnit 10 is no longer used, remove the condition.
-    // @see https://www.drupal.org/project/drupal/issues/3497116
-    if (RunnerVersion::getMajor() >= 11) {
-      $configurationFilePath .= \DIRECTORY_SEPARATOR . '.phpunit-next.xml';
-    }
-
     // PHPUnit's test discovery - via CLI execution.
     $process = new Process([
       'vendor/bin/phpunit',
       '--configuration',
-      $configurationFilePath,
+      'core',
       '--list-tests-xml',
       $this->xmlOutputFile,
     ], $this->root);
@@ -123,8 +113,14 @@ public function testPhpUnitTestDiscoveryEqualsInternal(): void {
     // Check against Drupal's discovery.
     $this->assertEquals(implode("\n", $phpUnitClientList), implode("\n", $internalList), self::TEST_LIST_MISMATCH_MESSAGE);
 
+    // @todo once PHPUnit 10 is no longer used re-enable the rest of the test.
+    // @see https://www.drupal.org/project/drupal/issues/3497116
+    if (RunnerVersion::getMajor() >= 11) {
+      $this->markTestIncomplete('On PHPUnit 11+ the test triggers warnings due to phpunit.xml setup. Re-enable in https://www.drupal.org/project/drupal/issues/3497116.');
+    }
+
     // PHPUnit's test discovery - via API.
-    $phpUnitConfiguration = (new Builder())->build(['--configuration', $configurationFilePath]);
+    $phpUnitConfiguration = (new Builder())->build(['--configuration', 'core']);
     $phpUnitTestSuite = (new TestSuiteBuilder())->build($phpUnitConfiguration);
     $phpUnitApiList = [];
     foreach ($phpUnitTestSuite->tests() as $testSuite) {
diff --git a/core/tests/Drupal/Tests/Core/Menu/LocalActionManagerTest.php b/core/tests/Drupal/Tests/Core/Menu/LocalActionManagerTest.php
index d0759a4bf082378a85181ebb08314f7321d17408..08fa2eceaf54dba0ad591a160e386804c51e394e 100644
--- a/core/tests/Drupal/Tests/Core/Menu/LocalActionManagerTest.php
+++ b/core/tests/Drupal/Tests/Core/Menu/LocalActionManagerTest.php
@@ -203,8 +203,6 @@ public function testGetActionsForRoute($route_appears, array $plugin_definitions
   }
 
   public static function getActionsForRouteProvider() {
-    $originalContainer = \Drupal::hasContainer() ? \Drupal::getContainer() : NULL;
-
     $cache_contexts_manager = (new Prophet())->prophesize(CacheContextsManager::class);
     $cache_contexts_manager->assertValidTokens(Argument::any())
       ->willReturn(TRUE);
@@ -386,11 +384,6 @@ public static function getActionsForRouteProvider() {
       ],
     ];
 
-    // Restore the original container if needed.
-    if ($originalContainer) {
-      \Drupal::setContainer($originalContainer);
-    }
-
     return $data;
   }
 
diff --git a/core/tests/Drupal/Tests/Core/Test/RunTests/TestFileParserTest.php b/core/tests/Drupal/Tests/Core/Test/RunTests/TestFileParserTest.php
index 9138d54523d65b7d553066555495a1e0f4c1ad56..957b2f61f97bdcd14d66ab485678f7e2e295a476 100644
--- a/core/tests/Drupal/Tests/Core/Test/RunTests/TestFileParserTest.php
+++ b/core/tests/Drupal/Tests/Core/Test/RunTests/TestFileParserTest.php
@@ -6,18 +6,12 @@
 
 use Drupal\Core\Test\RunTests\TestFileParser;
 use Drupal\Tests\UnitTestCase;
-use PHPUnit\Framework\Attributes\CoversClass;
-use PHPUnit\Framework\Attributes\DataProvider;
-use PHPUnit\Framework\Attributes\Group;
-use PHPUnit\Framework\Attributes\IgnoreDeprecations;
 
 /**
- * Tests for the deprecated TestFileParser class.
+ * @coversDefaultClass \Drupal\Core\Test\RunTests\TestFileParser
+ * @group Test
+ * @group RunTests
  */
-#[CoversClass(TestFileParser::class)]
-#[Group('Test')]
-#[Group('RunTest')]
-#[IgnoreDeprecations]
 class TestFileParserTest extends UnitTestCase {
 
   public static function provideTestFileContents() {
@@ -72,9 +66,9 @@ class AnotherClass {}
   }
 
   /**
-   * @legacy-covers ::parseContents
+   * @covers ::parseContents
+   * @dataProvider provideTestFileContents
    */
-  #[DataProvider('provideTestFileContents')]
   public function testParseContents($expected, $contents): void {
     $parser = new TestFileParser();
 
@@ -84,7 +78,7 @@ public function testParseContents($expected, $contents): void {
   }
 
   /**
-   * @legacy-covers ::getTestListFromFile
+   * @covers ::getTestListFromFile
    */
   public function testGetTestListFromFile(): void {
     $parser = new TestFileParser();
diff --git a/core/tests/Drupal/Tests/Core/Test/TestDiscoveryTest.php b/core/tests/Drupal/Tests/Core/Test/TestDiscoveryTest.php
index 0fb55e6c7f8af07510284dcbe38d1b6b43b9b5c2..bfbb4ca2e40da205f47ff5dfc89020211375bf45 100644
--- a/core/tests/Drupal/Tests/Core/Test/TestDiscoveryTest.php
+++ b/core/tests/Drupal/Tests/Core/Test/TestDiscoveryTest.php
@@ -13,23 +13,17 @@
 use Drupal\Core\Test\TestDiscovery;
 use Drupal\Tests\UnitTestCase;
 use org\bovigo\vfs\vfsStream;
-use PHPUnit\Framework\Attributes\CoversClass;
-use PHPUnit\Framework\Attributes\DataProvider;
-use PHPUnit\Framework\Attributes\Group;
-use PHPUnit\Framework\Attributes\IgnoreDeprecations;
 
 /**
- * Unit tests for TestDiscovery.
+ * @coversDefaultClass \Drupal\Core\Test\TestDiscovery
+ * @group Test
  */
-#[CoversClass(TestDiscovery::class)]
-#[Group('Test')]
-#[IgnoreDeprecations]
 class TestDiscoveryTest extends UnitTestCase {
 
   /**
-   * @legacy-covers ::getTestInfo
+   * @covers ::getTestInfo
+   * @dataProvider infoParserProvider
    */
-  #[DataProvider('infoParserProvider')]
   public function testTestInfoParser($expected, $classname, $doc_comment = NULL): void {
     $info = TestDiscovery::getTestInfo($classname, $doc_comment);
     $this->assertEquals($expected, $info);
@@ -40,14 +34,14 @@ public static function infoParserProvider() {
     $tests[] = [
       // Expected result.
       [
-        'name' => TestDatabaseTest::class,
+        'name' => static::class,
         'group' => 'Test',
-        'groups' => ['Test', 'simpletest', 'Template'],
-        'description' => 'Tests \Drupal\Core\Test\TestDatabase.',
+        'groups' => ['Test'],
+        'description' => 'Tests \Drupal\Core\Test\TestDiscovery.',
         'type' => 'PHPUnit-Unit',
       ],
       // Classname.
-      TestDatabaseTest::class,
+      static::class,
     ];
 
     // A core unit test.
@@ -223,7 +217,7 @@ public static function infoParserProvider() {
   }
 
   /**
-   * @legacy-covers ::getTestInfo
+   * @covers ::getTestInfo
    */
   public function testTestInfoParserMissingGroup(): void {
     $classname = 'Drupal\KernelTests\field\BulkDeleteTest';
@@ -238,7 +232,7 @@ public function testTestInfoParserMissingGroup(): void {
   }
 
   /**
-   * @legacy-covers ::getTestInfo
+   * @covers ::getTestInfo
    */
   public function testTestInfoParserMissingSummary(): void {
     $classname = 'Drupal\KernelTests\field\BulkDeleteTest';
@@ -317,7 +311,7 @@ class FunctionalExampleTest {}
   }
 
   /**
-   * @legacy-covers ::getTestClasses
+   * @covers ::getTestClasses
    */
   public function testGetTestClasses(): void {
     $this->setupVfsWithTestClasses();
@@ -386,7 +380,7 @@ protected function getTestDiscoveryMock($app_root, $extensions) {
   }
 
   /**
-   * @legacy-covers ::getTestClasses
+   * @covers ::getTestClasses
    */
   public function testGetTestClassesWithSelectedTypes(): void {
     $this->setupVfsWithTestClasses();
@@ -431,7 +425,7 @@ public function testGetTestClassesWithSelectedTypes(): void {
   }
 
   /**
-   * @legacy-covers ::getTestClasses
+   * @covers ::getTestClasses
    */
   public function testGetTestsInProfiles(): void {
     $this->setupVfsWithTestClasses();
@@ -460,9 +454,9 @@ public function testGetTestsInProfiles(): void {
   }
 
   /**
-   * @legacy-covers ::getPhpunitTestSuite
+   * @covers ::getPhpunitTestSuite
+   * @dataProvider providerTestGetPhpunitTestSuite
    */
-  #[DataProvider('providerTestGetPhpunitTestSuite')]
   public function testGetPhpunitTestSuite($classname, $expected): void {
     $this->assertEquals($expected, TestDiscovery::getPhpunitTestSuite($classname));
   }
@@ -488,7 +482,7 @@ public static function providerTestGetPhpunitTestSuite() {
   /**
    * Ensure that classes are not reflected when the docblock is empty.
    *
-   * @legacy-covers ::getTestInfo
+   * @covers ::getTestInfo
    */
   public function testGetTestInfoEmptyDocblock(): void {
     // If getTestInfo() performed reflection, it won't be able to find the
@@ -503,7 +497,7 @@ public function testGetTestInfoEmptyDocblock(): void {
   /**
    * Ensure TestDiscovery::scanDirectory() ignores certain abstract file types.
    *
-   * @legacy-covers ::scanDirectory
+   * @covers ::scanDirectory
    */
   public function testScanDirectoryNoAbstract(): void {
     $this->setupVfsWithTestClasses();