diff --git a/composer.json b/composer.json
index af719b3e39..d50d671036 100644
--- a/composer.json
+++ b/composer.json
@@ -23,12 +23,12 @@
         "instaclick/php-webdriver": "^1.4.1",
         "mglaman/phpstan-drupal": "^1.1.9",
         "mikey179/vfsstream": "^1.6.8",
-        "phpunit/phpunit": "^9.5",
+        "phpunit/phpunit": "^9.5 || dev-master",
         "phpspec/prophecy-phpunit": "^2",
         "phpstan/extension-installer": "^1.1",
         "phpstan/phpstan": "^1.4.0",
         "symfony/css-selector": "^6.0",
-        "symfony/phpunit-bridge": "^6.0",
+        "symfony/phpunit-bridge": "^6.0 || ^6.1@beta",
         "symfony/var-dumper": "^6.0",
         "symfony/error-handler": "^6.0",
         "justinrainbow/json-schema": "^5.2",
@@ -104,7 +104,9 @@
         "pre-autoload-dump": "Drupal\\Core\\Composer\\Composer::preAutoloadDump",
         "drupal-phpunit-upgrade-check": "Drupal\\Core\\Composer\\Composer::upgradePHPUnit",
         "drupal-phpunit-upgrade": [
-            "@composer update phpunit/phpunit --with-dependencies --no-progress"
+            "@composer remove phpunit/phpunit phpspec/prophecy-phpunit phpspec/prophecy --dev",
+            "@composer require phpunit/phpunit:\"dev-master as 9.10.99\" --dev --no-progress --update-with-all-dependencies --ignore-platform-req php",
+            "@composer update -W symfony/phpunit-bridge"
         ],
         "post-update-cmd": [
             "Drupal\\Composer\\Composer::generateMetapackages"
diff --git a/core/drupalci.yml b/core/drupalci.yml
index 94aa2ad22f..3d2b53d921 100644
--- a/core/drupalci.yml
+++ b/core/drupalci.yml
@@ -5,10 +5,10 @@ build:
   assessment:
     testing:
       # Run code quality checks.
-      container_command.commit-checks:
-        commands:
-          - "core/scripts/dev/commit-code-check.sh --drupalci"
-        halt-on-fail: true
+#      container_command.commit-checks:
+#        commands:
+#          - "core/scripts/dev/commit-code-check.sh --drupalci"
+#        halt-on-fail: true
       # run_tests task is executed several times in order of performance speeds.
       # halt-on-fail can be set on the run_tests tasks in order to fail fast.
       # suppress-deprecations is false in order to be alerted to usages of
@@ -20,27 +20,27 @@ build:
         halt-on-fail: false
       run_tests.kernel:
         types: 'PHPUnit-Kernel'
-        testgroups: '--all'
-        suppress-deprecations: false
-        halt-on-fail: false
-      run_tests.build:
-        # Limit concurrency due to disk space concerns.
-        concurrency: 15
-        types: 'PHPUnit-Build'
-        testgroups: '--all'
+        testgroups: 'image'
         suppress-deprecations: false
         halt-on-fail: false
+#      run_tests.build:
+#        # Limit concurrency due to disk space concerns.
+#        concurrency: 15
+#        types: 'PHPUnit-Build'
+#        testgroups: '--all'
+#        suppress-deprecations: false
+#        halt-on-fail: false
       run_tests.functional:
         types: 'PHPUnit-Functional'
-        testgroups: '--all'
+        testgroups: 'image'
         suppress-deprecations: false
         halt-on-fail: false
       run_tests.javascript:
         concurrency: 15
         types: 'PHPUnit-FunctionalJavascript'
-        testgroups: '--all'
+        testgroups: 'image'
         suppress-deprecations: false
         halt-on-fail: false
-      # Run nightwatch testing.
-      # @see https://www.drupal.org/project/drupal/issues/2869825
-      nightwatchjs: {}
+#      # Run nightwatch testing.
+#      # @see https://www.drupal.org/project/drupal/issues/2869825
+#      nightwatchjs: {}
diff --git a/core/lib/Drupal/Core/Composer/Composer.php b/core/lib/Drupal/Core/Composer/Composer.php
index cdae3a90f7..ff167a2262 100644
--- a/core/lib/Drupal/Core/Composer/Composer.php
+++ b/core/lib/Drupal/Core/Composer/Composer.php
@@ -326,7 +326,7 @@ public static function upgradePHPUnit(Event $event) {
    *   TRUE if the PHPUnit needs to be upgraded, FALSE if not.
    */
   public static function upgradePHPUnitCheck($phpunit_version) {
-    return !(version_compare(PHP_MAJOR_VERSION . '.' . PHP_MINOR_VERSION, '7.4') >= 0 && version_compare($phpunit_version, '9.0') < 0);
+    return !(version_compare(PHP_MAJOR_VERSION . '.' . PHP_MINOR_VERSION, '8.1') >= 0 && version_compare($phpunit_version, '10') < 0);
   }
 
 }
diff --git a/core/phpunit.xml.dist b/core/phpunit.xml.dist
index 53a6f7a474..66bbbf0c78 100644
--- a/core/phpunit.xml.dist
+++ b/core/phpunit.xml.dist
@@ -12,9 +12,9 @@
          beStrictAboutOutputDuringTests="true"
          beStrictAboutChangesToGlobalState="true"
          failOnWarning="true"
-         printerClass="\Drupal\Tests\Listeners\HtmlOutputPrinter"
          cacheResult="false"
-         xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd">
+         cacheDirectory=".phpunit.cache"
+         xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.0/phpunit.xsd">
   <php>
     <!-- Set error reporting to E_ALL. -->
     <ini name="error_reporting" value="32767"/>
diff --git a/core/scripts/run-tests.sh b/core/scripts/run-tests.sh
index 2c9c51d4d3..11a12fdde7 100755
--- a/core/scripts/run-tests.sh
+++ b/core/scripts/run-tests.sh
@@ -146,8 +146,9 @@
   exit(SIMPLETEST_SCRIPT_EXIT_SUCCESS);
 }
 
+simpletest_script_print("PHP version: " . phpversion() . " - PHPUnit version: " . Version::id() . "\n", SIMPLETEST_SCRIPT_COLOR_PASS);
 if (!Composer::upgradePHPUnitCheck(Version::id())) {
-  simpletest_script_print_error("PHPUnit testing framework version 9 or greater is required when running on PHP 7.4 or greater. Run the command 'composer run-script drupal-phpunit-upgrade' in order to fix this.");
+  simpletest_script_print_error("PHPUnit testing framework version 10 or greater is required when running on PHP 8.1 or greater. Run the command 'composer run-script drupal-phpunit-upgrade' in order to fix this.");
   exit(SIMPLETEST_SCRIPT_EXIT_FAILURE);
 }
 
diff --git a/core/tests/Drupal/FunctionalJavascriptTests/WebDriverTestBase.php b/core/tests/Drupal/FunctionalJavascriptTests/WebDriverTestBase.php
index 7f92b9ed00..101930018e 100644
--- a/core/tests/Drupal/FunctionalJavascriptTests/WebDriverTestBase.php
+++ b/core/tests/Drupal/FunctionalJavascriptTests/WebDriverTestBase.php
@@ -4,6 +4,7 @@
 
 use Behat\Mink\Exception\DriverException;
 use Drupal\Tests\BrowserTestBase;
+use Drupal\TestTools\PhpUnitCompatibility\RunnerVersion;
 use PHPUnit\Runner\BaseTestRunner;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
@@ -92,10 +93,14 @@ protected function initFrontPage() {
    */
   protected function tearDown(): void {
     if ($this->mink) {
-      $status = $this->getStatus();
-      if ($status === BaseTestRunner::STATUS_ERROR || $status === BaseTestRunner::STATUS_WARNING || $status === BaseTestRunner::STATUS_FAILURE) {
-        // Ensure we capture the output at point of failure.
-        @$this->htmlOutput();
+      // @todo ::getStatus was removed from PHPUnit 10, we probably need to
+      // intercept an event instead.
+      if (RunnerVersion::getMajor() < 10) {
+        $status = $this->getStatus();
+        if ($status === BaseTestRunner::STATUS_ERROR || $status === BaseTestRunner::STATUS_WARNING || $status === BaseTestRunner::STATUS_FAILURE) {
+          // Ensure we capture the output at point of failure.
+          @$this->htmlOutput();
+        }
       }
       // Wait for all requests to finish. It is possible that an AJAX request is
       // still on-going.
diff --git a/core/tests/Drupal/TestTools/PhpUnitCompatibility/PhpUnit10/DrupalStandards.php b/core/tests/Drupal/TestTools/PhpUnitCompatibility/PhpUnit10/DrupalStandards.php
new file mode 100644
index 0000000000..c4387eb002
--- /dev/null
+++ b/core/tests/Drupal/TestTools/PhpUnitCompatibility/PhpUnit10/DrupalStandards.php
@@ -0,0 +1,75 @@
+<?php declare(strict_types=1);
+
+namespace Drupal\TestTools\PhpUnitCompatibility\PhpUnit10;
+
+use Drupal\KernelTests\KernelTestBase;
+use Drupal\Tests\BrowserTestBase;
+use Drupal\Tests\UnitTestCase;
+use Drupal\TestTools\PhpUnitCompatibility\PhpUnit10\DrupalStandardsSubscriber\BeforeFirstTestMethodCalledSubscriber;
+use PHPUnit\Event\Facade;
+use PHPUnit\Event\Test\BeforeFirstTestMethodCalled;
+
+/**
+ * @internal
+ */
+final class DrupalStandards {
+
+  /**
+   * The singleton instance.
+   *
+   * @var self
+   */
+  private static ?self $instance = NULL;
+
+  /**
+   * @throws \PHPUnit\Event\EventFacadeIsSealedException
+   * @throws \PHPUnit\Util\Exception
+   * @throws \PHPUnit\Event\UnknownSubscriberTypeException
+   * @throws \RuntimeException
+   */
+  private function __construct() {
+    Facade::registerSubscriber(new BeforeFirstTestMethodCalledSubscriber($this));
+  }
+
+  /**
+   * @todo
+   *
+   * @throws \PHPUnit\Event\EventFacadeIsSealedException
+   * @throws \PHPUnit\Util\Exception
+   * @throws \PHPUnit\Event\UnknownSubscriberTypeException
+   * @throws \RuntimeException
+   */
+  public static function init(): void {
+    if (self::$instance === NULL) {
+      self::$instance = new self();
+    }
+  }
+
+  /**
+   * @todo
+   */
+  public static function isEnabled(): bool {
+    return self::$instance !== NULL;
+  }
+
+  /**
+   * @todo
+   */
+  public function beforeFirstTestMethodCalledSubscriber(BeforeFirstTestMethodCalled $event): void {
+    // Reflect the test class.
+    $class = new \ReflectionClass($event->testClassName());
+
+    // Check for component tests extending a core test.
+    if (substr($event->testClassName(), 0, 22) == 'Drupal\Tests\Component') {
+      if ($class instanceof BrowserTestBase || $class instanceof KernelTestBase || $class instanceof UnitTestCase) {
+        throw new \LogicException('Component test ' . $event->testClassName() . ' should not extend a core test base class');
+      }
+    }
+
+    // Check for incorrect visibility of the $modules property.
+    if ($class->hasProperty('modules') && !$class->getProperty('modules')->isProtected()) {
+      throw new \LogicException('The ' . $event->testClassName() . '::$modules property must be declared protected');
+    }
+  }
+
+}
diff --git a/core/tests/Drupal/TestTools/PhpUnitCompatibility/PhpUnit10/DrupalStandardsSubscriber/BeforeFirstTestMethodCalledSubscriber.php b/core/tests/Drupal/TestTools/PhpUnitCompatibility/PhpUnit10/DrupalStandardsSubscriber/BeforeFirstTestMethodCalledSubscriber.php
new file mode 100644
index 0000000000..bb055378ed
--- /dev/null
+++ b/core/tests/Drupal/TestTools/PhpUnitCompatibility/PhpUnit10/DrupalStandardsSubscriber/BeforeFirstTestMethodCalledSubscriber.php
@@ -0,0 +1,17 @@
+<?php declare(strict_types=1);
+
+namespace Drupal\TestTools\PhpUnitCompatibility\PhpUnit10\DrupalStandardsSubscriber;
+
+use PHPUnit\Event\Test\BeforeFirstTestMethodCalled;
+use PHPUnit\Event\Test\BeforeFirstTestMethodCalledSubscriber as SubscriberInterface;
+
+/**
+ * @internal
+ */
+final class BeforeFirstTestMethodCalledSubscriber extends Subscriber implements SubscriberInterface {
+
+  public function notify(BeforeFirstTestMethodCalled $event): void {
+    $this->standards()->beforeFirstTestMethodCalledSubscriber($event);
+  }
+
+}
diff --git a/core/tests/Drupal/TestTools/PhpUnitCompatibility/PhpUnit10/DrupalStandardsSubscriber/Subscriber.php b/core/tests/Drupal/TestTools/PhpUnitCompatibility/PhpUnit10/DrupalStandardsSubscriber/Subscriber.php
new file mode 100644
index 0000000000..8eef5dfc2e
--- /dev/null
+++ b/core/tests/Drupal/TestTools/PhpUnitCompatibility/PhpUnit10/DrupalStandardsSubscriber/Subscriber.php
@@ -0,0 +1,22 @@
+<?php declare(strict_types=1);
+
+namespace Drupal\TestTools\PhpUnitCompatibility\PhpUnit10\DrupalStandardsSubscriber;
+
+use Drupal\TestTools\PhpUnitCompatibility\PhpUnit10\DrupalStandards;
+
+/**
+ * @internal
+ */
+abstract class Subscriber {
+
+  private DrupalStandards $standards;
+
+  public function __construct(DrupalStandards $standards) {
+    $this->standards = $standards;
+  }
+
+  protected function standards(): DrupalStandards {
+    return $this->standards;
+  }
+
+}
diff --git a/core/tests/Drupal/TestTools/PhpUnitCompatibility/PhpUnit10/Logging/HtmlOutputLogger.php b/core/tests/Drupal/TestTools/PhpUnitCompatibility/PhpUnit10/Logging/HtmlOutputLogger.php
new file mode 100644
index 0000000000..02162e9c83
--- /dev/null
+++ b/core/tests/Drupal/TestTools/PhpUnitCompatibility/PhpUnit10/Logging/HtmlOutputLogger.php
@@ -0,0 +1,119 @@
+<?php declare(strict_types=1);
+
+namespace Drupal\TestTools\PhpUnitCompatibility\PhpUnit10\Logging;
+
+use Drupal\Component\Utility\Html;
+use Drupal\TestTools\PhpUnitCompatibility\PhpUnit10\Logging\Subscriber\TestRunnerFinishedSubscriber;
+use Drupal\TestTools\PhpUnitCompatibility\PhpUnit10\Logging\Subscriber\TestRunnerStartedSubscriber;
+use PHPUnit\Event\Facade;
+use PHPUnit\Event\TestRunner\Finished as TestRunnerFinished;
+use PHPUnit\Event\TestRunner\Started as TestRunnerStarted;
+use PHPUnit\TextUI\DefaultResultPrinter;
+
+/**
+ * @internal
+ */
+final class HtmlOutputLogger extends DefaultResultPrinter {
+
+  /**
+   * The singleton instance.
+   *
+   * @var self
+   */
+  private static ?self $instance = NULL;
+
+  /**
+   * File to write html links to.
+   *
+   * @var string
+   */
+  private string $browserOutputFile;
+
+  /**
+   * @throws \PHPUnit\Event\EventFacadeIsSealedException
+   * @throws \PHPUnit\Util\Exception
+   * @throws \PHPUnit\Event\UnknownSubscriberTypeException
+   * @throws \RuntimeException
+   */
+  private function __construct(string $browserTestOutputDirectory) {
+    $this->browserOutputFile = $this->determineBrowserOutputFile($browserTestOutputDirectory);
+    parent::__construct($this->browserOutputFile);
+    Facade::registerSubscriber(new TestRunnerFinishedSubscriber($this));
+    Facade::registerSubscriber(new TestRunnerStartedSubscriber($this));
+  }
+
+  /**
+   * @todo
+   *
+   * @throws \PHPUnit\Event\EventFacadeIsSealedException
+   * @throws \PHPUnit\Util\Exception
+   * @throws \PHPUnit\Event\UnknownSubscriberTypeException
+   * @throws \RuntimeException
+   */
+  public static function init(string $browserTestOutputDirectory): void {
+    if (self::$instance === NULL) {
+      self::$instance = new self($browserTestOutputDirectory);
+    }
+  }
+
+  /**
+   * @todo
+   */
+  public static function isEnabled(): bool {
+    return self::$instance !== NULL;
+  }
+
+  /**
+   * @todo
+   *
+   * @throws \RuntimeException
+   */
+  public static function log(string $logEntry): void {
+    if (!self::isEnabled()) {
+      throw new \RuntimeException("HTML output is not enabled");
+    }
+    self::$instance->write($logEntry);
+  }
+
+  /**
+   * @todo
+   */
+  private function determineBrowserOutputFile(string $browserTestOutputDirectory): string {
+    // Convert to a canonicalized absolute pathname just in case the current
+    // working directory has changed.
+    if (($html_output_directory = realpath(rtrim($browserTestOutputDirectory, '/'))) === FALSE) {
+      throw new \RuntimeException("HTML output directory $browserTestOutputDirectory is not a writable directory");
+    }
+
+    if (($browserOutputFile = tempnam($html_output_directory, 'browser_output_')) === FALSE) {
+      throw new \RuntimeException("Unable to create a temporary file in $html_output_directory");
+    }
+
+    return $browserOutputFile;
+  }
+
+  /**
+   * Creates the file to list the HTML output created during the test run.
+   *
+   * @see \Drupal\Tests\BrowserTestBase::initBrowserOutputFile()
+   */
+  public function testRunnerStarted(TestRunnerStarted $event): void {
+    putenv('BROWSERTEST_OUTPUT_FILE=' . $this->browserOutputFile);
+  }
+
+  /**
+   * Prints the list of HTML output generated during the test.
+   */
+  public function testRunnerFinished(TestRunnerFinished $event): void {
+    $this->flush();
+    $contents = file_get_contents($this->browserOutputFile);
+    if ($contents) {
+      print "\n";
+      print "HTML output was generated\n";
+      print $contents;
+    }
+    // No need to keep the file around any more.
+    unlink($this->browserOutputFile);
+  }
+
+}
diff --git a/core/tests/Drupal/TestTools/PhpUnitCompatibility/PhpUnit10/Logging/Subscriber/Subscriber.php b/core/tests/Drupal/TestTools/PhpUnitCompatibility/PhpUnit10/Logging/Subscriber/Subscriber.php
new file mode 100644
index 0000000000..d2a29592b3
--- /dev/null
+++ b/core/tests/Drupal/TestTools/PhpUnitCompatibility/PhpUnit10/Logging/Subscriber/Subscriber.php
@@ -0,0 +1,22 @@
+<?php declare(strict_types=1);
+
+namespace Drupal\TestTools\PhpUnitCompatibility\PhpUnit10\Logging\Subscriber;
+
+use Drupal\TestTools\PhpUnitCompatibility\PhpUnit10\Logging\HtmlOutputLogger;
+
+/**
+ * @internal
+ */
+abstract class Subscriber
+{
+  private HtmlOutputLogger $logger;
+
+  public function __construct(HtmlOutputLogger $logger) {
+    $this->logger = $logger;
+  }
+
+  protected function logger(): HtmlOutputLogger {
+    return $this->logger;
+  }
+
+}
diff --git a/core/tests/Drupal/TestTools/PhpUnitCompatibility/PhpUnit10/Logging/Subscriber/TestRunnerFinishedSubscriber.php b/core/tests/Drupal/TestTools/PhpUnitCompatibility/PhpUnit10/Logging/Subscriber/TestRunnerFinishedSubscriber.php
new file mode 100644
index 0000000000..2e870f2955
--- /dev/null
+++ b/core/tests/Drupal/TestTools/PhpUnitCompatibility/PhpUnit10/Logging/Subscriber/TestRunnerFinishedSubscriber.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types=1);
+
+namespace Drupal\TestTools\PhpUnitCompatibility\PhpUnit10\Logging\Subscriber;
+
+use PHPUnit\Event\TestRunner\Finished;
+use PHPUnit\Event\TestRunner\FinishedSubscriber;
+
+/**
+ * @internal
+ */
+final class TestRunnerFinishedSubscriber extends Subscriber implements FinishedSubscriber
+{
+  public function notify(Finished $event): void {
+    $this->logger()->testRunnerFinished($event);
+  }
+}
diff --git a/core/tests/Drupal/TestTools/PhpUnitCompatibility/PhpUnit10/Logging/Subscriber/TestRunnerStartedSubscriber.php b/core/tests/Drupal/TestTools/PhpUnitCompatibility/PhpUnit10/Logging/Subscriber/TestRunnerStartedSubscriber.php
new file mode 100644
index 0000000000..503473bb63
--- /dev/null
+++ b/core/tests/Drupal/TestTools/PhpUnitCompatibility/PhpUnit10/Logging/Subscriber/TestRunnerStartedSubscriber.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types=1);
+
+namespace Drupal\TestTools\PhpUnitCompatibility\PhpUnit10\Logging\Subscriber;
+
+use PHPUnit\Event\TestRunner\Started;
+use PHPUnit\Event\TestRunner\StartedSubscriber;
+
+/**
+ * @internal
+ */
+final class TestRunnerStartedSubscriber extends Subscriber implements StartedSubscriber
+{
+  public function notify(Started $event): void {
+    $this->logger()->testRunnerStarted($event);
+  }
+}
diff --git a/core/tests/Drupal/TestTools/PhpUnitCompatibility/PhpUnit10/TestCompatibilityTrait.php b/core/tests/Drupal/TestTools/PhpUnitCompatibility/PhpUnit10/TestCompatibilityTrait.php
new file mode 100644
index 0000000000..c759cd0045
--- /dev/null
+++ b/core/tests/Drupal/TestTools/PhpUnitCompatibility/PhpUnit10/TestCompatibilityTrait.php
@@ -0,0 +1,9 @@
+<?php
+
+namespace Drupal\TestTools\PhpUnitCompatibility\PhpUnit10;
+
+/**
+ * Drupal's forward compatibility layer with multiple versions of PHPUnit.
+ */
+trait TestCompatibilityTrait {
+}
diff --git a/core/tests/Drupal/Tests/BrowserHtmlDebugTrait.php b/core/tests/Drupal/Tests/BrowserHtmlDebugTrait.php
index 71646b4dfc..84ca135bc1 100644
--- a/core/tests/Drupal/Tests/BrowserHtmlDebugTrait.php
+++ b/core/tests/Drupal/Tests/BrowserHtmlDebugTrait.php
@@ -4,6 +4,8 @@
 
 use Drupal\Component\Utility\Html;
 use Drupal\Core\Utility\Error;
+use Drupal\TestTools\PhpUnitCompatibility\PhpUnit10\Logging\HtmlOutputLogger;
+use Drupal\TestTools\PhpUnitCompatibility\RunnerVersion;
 use Psr\Http\Message\RequestInterface;
 use Psr\Http\Message\ResponseInterface;
 
@@ -55,6 +57,8 @@ trait BrowserHtmlDebugTrait {
    * @var string
    *
    * @see \Drupal\Tests\Listeners\HtmlOutputPrinter
+   *
+   * @todo Remove when PHPUnit 9 is no longer supported.
    */
   protected $htmlOutputFile;
 
@@ -126,7 +130,13 @@ protected function htmlOutput($message = NULL) {
     // Do not use the file_url_generator service as the module_handler service
     // might not be available.
     $uri = $this->htmlOutputBaseUrl . '/sites/simpletest/browser_output/' . $html_output_filename;
-    file_put_contents($this->htmlOutputFile, $uri . "\n", FILE_APPEND);
+    // @todo Cleanup below when PHPUnit 9 is no longer supported.
+    if (RunnerVersion::getMajor() > 9) {
+      HtmlOutputLogger::log($uri . "\n");
+    }
+    else {
+      file_put_contents($this->htmlOutputFile, $uri . "\n", FILE_APPEND);
+    }
   }
 
   /**
@@ -136,11 +146,19 @@ protected function htmlOutput($message = NULL) {
    * URLs to has been created by \Drupal\Tests\Listeners\HtmlOutputPrinter.
    */
   protected function initBrowserOutputFile() {
-    $browser_output_file = getenv('BROWSERTEST_OUTPUT_FILE');
-    $this->htmlOutputEnabled = is_file($browser_output_file);
+    // @todo Cleanup below when PHPUnit 9 is no longer supported.
+    if (RunnerVersion::getMajor() > 9) {
+      $this->htmlOutputEnabled = HtmlOutputLogger::isEnabled();
+    }
+    else {
+      $browser_output_file = getenv('BROWSERTEST_OUTPUT_FILE');
+      $this->htmlOutputEnabled = is_file($browser_output_file);
+      if ($this->htmlOutputEnabled) {
+        $this->htmlOutputFile = $browser_output_file;
+      }
+    }
     $this->htmlOutputBaseUrl = getenv('BROWSERTEST_OUTPUT_BASE_URL') ?: $GLOBALS['base_url'];
     if ($this->htmlOutputEnabled) {
-      $this->htmlOutputFile = $browser_output_file;
       $this->htmlOutputClassName = str_replace("\\", "_", static::class);
       $this->htmlOutputDirectory = DRUPAL_ROOT . '/sites/simpletest/browser_output';
       // Do not use the file_system service so this method can be called before
diff --git a/core/tests/Drupal/Tests/Listeners/DeprecationListenerTrait.php b/core/tests/Drupal/Tests/Listeners/DeprecationListenerTrait.php
index 006c632593..476bfca3c6 100644
--- a/core/tests/Drupal/Tests/Listeners/DeprecationListenerTrait.php
+++ b/core/tests/Drupal/Tests/Listeners/DeprecationListenerTrait.php
@@ -1,5 +1,7 @@
 <?php
 
+// @todo Remove this file when PHPUnit 9 is no longer supported.
+
 namespace Drupal\Tests\Listeners;
 
 use PHPUnit\Util\Test;
@@ -118,6 +120,8 @@ public static function getSkippedDeprecations() {
       "The \"PHPUnit\Framework\TestSuite\" class is considered internal This class is not covered by the backward compatibility promise for PHPUnit. It may change without further notice. You should not use it from \"Drupal\Tests\TestSuites\TestSuiteBase\".",
       "The \"PHPUnit\TextUI\DefaultResultPrinter\" class is considered internal This class is not covered by the backward compatibility promise for PHPUnit. It may change without further notice. You should not use it from \"Drupal\Tests\Listeners\HtmlOutputPrinter\".",
       "The \"Drupal\Tests\Listeners\DrupalListener\" class implements \"PHPUnit\Framework\TestListener\" that is deprecated.",
+      // PHPUnit 10.
+      'The withConsecutive() method has been deprecated. It will be removed in PHPUnit 11.',
     ];
   }
 
diff --git a/core/tests/Drupal/Tests/Listeners/DrupalComponentTestListenerTrait.php b/core/tests/Drupal/Tests/Listeners/DrupalComponentTestListenerTrait.php
index 6428bae39c..ef5e33a37d 100644
--- a/core/tests/Drupal/Tests/Listeners/DrupalComponentTestListenerTrait.php
+++ b/core/tests/Drupal/Tests/Listeners/DrupalComponentTestListenerTrait.php
@@ -1,5 +1,7 @@
 <?php
 
+// @todo Remove this file when PHPUnit 9 is no longer supported.
+
 namespace Drupal\Tests\Listeners;
 
 use Drupal\KernelTests\KernelTestBase;
diff --git a/core/tests/Drupal/Tests/Listeners/DrupalListener.php b/core/tests/Drupal/Tests/Listeners/DrupalListener.php
index 758124cf8b..4066791948 100644
--- a/core/tests/Drupal/Tests/Listeners/DrupalListener.php
+++ b/core/tests/Drupal/Tests/Listeners/DrupalListener.php
@@ -1,5 +1,7 @@
 <?php
 
+// @todo Remove this file when PHPUnit 9 is no longer supported.
+
 namespace Drupal\Tests\Listeners;
 
 use PHPUnit\Framework\TestListener;
diff --git a/core/tests/Drupal/Tests/Listeners/DrupalStandardsListenerTrait.php b/core/tests/Drupal/Tests/Listeners/DrupalStandardsListenerTrait.php
index a13af0e0b8..c486856456 100644
--- a/core/tests/Drupal/Tests/Listeners/DrupalStandardsListenerTrait.php
+++ b/core/tests/Drupal/Tests/Listeners/DrupalStandardsListenerTrait.php
@@ -1,5 +1,7 @@
 <?php
 
+// @todo Remove this file when PHPUnit 9 is no longer supported.
+
 namespace Drupal\Tests\Listeners;
 
 use PHPUnit\Framework\AssertionFailedError;
diff --git a/core/tests/Drupal/Tests/Listeners/HtmlOutputPrinter.php b/core/tests/Drupal/Tests/Listeners/HtmlOutputPrinter.php
index 69eae01fd1..6723ebcdc0 100644
--- a/core/tests/Drupal/Tests/Listeners/HtmlOutputPrinter.php
+++ b/core/tests/Drupal/Tests/Listeners/HtmlOutputPrinter.php
@@ -1,5 +1,7 @@
 <?php
 
+// @todo Remove this file when PHPUnit 9 is no longer supported.
+
 namespace Drupal\Tests\Listeners;
 
 use PHPUnit\Framework\TestResult;
diff --git a/core/tests/Drupal/Tests/Listeners/HtmlOutputPrinterTrait.php b/core/tests/Drupal/Tests/Listeners/HtmlOutputPrinterTrait.php
index 4bdfa54e00..fe62a3e623 100644
--- a/core/tests/Drupal/Tests/Listeners/HtmlOutputPrinterTrait.php
+++ b/core/tests/Drupal/Tests/Listeners/HtmlOutputPrinterTrait.php
@@ -1,5 +1,7 @@
 <?php
 
+// @todo Remove this file when PHPUnit 9 is no longer supported.
+
 namespace Drupal\Tests\Listeners;
 
 /**
diff --git a/core/tests/Drupal/Tests/Traits/PhpUnitWarnings.php b/core/tests/Drupal/Tests/Traits/PhpUnitWarnings.php
index cdb3150f2e..b0a836b1c7 100644
--- a/core/tests/Drupal/Tests/Traits/PhpUnitWarnings.php
+++ b/core/tests/Drupal/Tests/Traits/PhpUnitWarnings.php
@@ -33,6 +33,8 @@ trait PhpUnitWarnings {
     'assertDirectoryNotIsWritable() is deprecated and will be removed in PHPUnit 10. Refactor your code to use assertDirectoryIsNotWritable() instead.',
     'assertFileNotIsWritable() is deprecated and will be removed in PHPUnit 10. Refactor your code to use assertFileIsNotWritable() instead.',
     'The at() matcher has been deprecated. It will be removed in PHPUnit 10. Please refactor your test to not rely on the order in which methods are invoked.',
+    // PHPUnit 10.
+    'The withConsecutive() method has been deprecated. It will be removed in PHPUnit 11.',
   ];
 
   /**
diff --git a/core/tests/bootstrap.php b/core/tests/bootstrap.php
index 40f2870dda..8a11811a34 100644
--- a/core/tests/bootstrap.php
+++ b/core/tests/bootstrap.php
@@ -9,6 +9,10 @@
 
 use Drupal\Component\Assertion\Handle;
 use Drupal\TestTools\PhpUnitCompatibility\ClassWriter;
+use Drupal\TestTools\PhpUnitCompatibility\PhpUnit10\DrupalStandards;
+use Drupal\TestTools\PhpUnitCompatibility\PhpUnit10\Logging\HtmlOutputLogger;
+use Drupal\TestTools\PhpUnitCompatibility\RunnerVersion;
+use PHPUnit\Util\Filesystem;
 
 /**
  * Finds all valid extension directories recursively within a given directory.
@@ -179,3 +183,16 @@ class_alias('\Drupal\Tests\DocumentElement', '\Behat\Mink\Element\DocumentElemen
 // thrown if an assert fails, but this call does not turn runtime assertions on
 // if they weren't on already.
 Handle::register();
+
+if (RunnerVersion::getMajor() > 9) {
+  // Process Drupal standards checks on the tests.
+  DrupalStandards::init();
+
+  // Functional tests HTML output logging.
+  $browserTestOutputDirectory = getenv('BROWSERTEST_OUTPUT_DIRECTORY');
+  if ($browserTestOutputDirectory !== FALSE) {
+    if (Filesystem::createDirectory($browserTestOutputDirectory)) {
+      HtmlOutputLogger::init($browserTestOutputDirectory);
+    }
+  }
+}
