diff --git a/core/phpunit.xml.dist b/core/phpunit.xml.dist
index bd9c8338097f33b02fbed76fd8770314a1575626..42f4419115f8893a68bc38ed0b46389601a48e80 100644
--- a/core/phpunit.xml.dist
+++ b/core/phpunit.xml.dist
@@ -9,6 +9,7 @@
          beStrictAboutTestsThatDoNotTestAnything="true"
          beStrictAboutOutputDuringTests="true"
          beStrictAboutChangesToGlobalState="true"
+         failOnWarning="true"
          printerClass="\Drupal\Tests\Listeners\HtmlOutputPrinter"
          cacheResult="false">
   <php>
diff --git a/core/tests/Drupal/BuildTests/Framework/BuildTestBase.php b/core/tests/Drupal/BuildTests/Framework/BuildTestBase.php
index 47a086064f4f1ac939dfe89a2b8a7ba3df7e8702..984c363c9f25fd8d40a51eed25685ae69caef3ed 100644
--- a/core/tests/Drupal/BuildTests/Framework/BuildTestBase.php
+++ b/core/tests/Drupal/BuildTests/Framework/BuildTestBase.php
@@ -7,6 +7,7 @@
 use Behat\Mink\Mink;
 use Behat\Mink\Session;
 use Drupal\Component\FileSystem\FileSystem as DrupalFilesystem;
+use Drupal\Tests\Traits\PHPUnit8Warnings;
 use PHPUnit\Framework\TestCase;
 use Symfony\Component\BrowserKit\Client as SymfonyClient;
 use Symfony\Component\Filesystem\Filesystem as SymfonyFilesystem;
@@ -52,6 +53,7 @@
 abstract class BuildTestBase extends TestCase {
 
   use ExternalCommandRequirementsTrait;
+  use PHPUnit8Warnings;
 
   /**
    * The working directory where this test will manipulate files.
diff --git a/core/tests/Drupal/KernelTests/KernelTestBase.php b/core/tests/Drupal/KernelTests/KernelTestBase.php
index a74c1cbbd07fb007fcf4986a291db481d6704a92..4539ed485028ec4c110ae2fdea996e07072edd52 100644
--- a/core/tests/Drupal/KernelTests/KernelTestBase.php
+++ b/core/tests/Drupal/KernelTests/KernelTestBase.php
@@ -21,6 +21,7 @@
 use Drupal\Tests\ConfigTestTrait;
 use Drupal\Tests\RandomGeneratorTrait;
 use Drupal\Tests\TestRequirementsTrait;
+use Drupal\Tests\Traits\PHPUnit8Warnings;
 use Drupal\TestTools\Comparator\MarkupInterfaceComparator;
 use PHPUnit\Framework\Exception;
 use PHPUnit\Framework\TestCase;
@@ -80,6 +81,7 @@ abstract class KernelTestBase extends TestCase implements ServiceProviderInterfa
   use RandomGeneratorTrait;
   use ConfigTestTrait;
   use TestRequirementsTrait;
+  use PHPUnit8Warnings;
 
   /**
    * {@inheritdoc}
diff --git a/core/tests/Drupal/Tests/BrowserTestBase.php b/core/tests/Drupal/Tests/BrowserTestBase.php
index e3028748bfdab6f53269766cee3f369ea233f433..7226e9a4a6e621a455cfad8f0eac90a6fd868867 100644
--- a/core/tests/Drupal/Tests/BrowserTestBase.php
+++ b/core/tests/Drupal/Tests/BrowserTestBase.php
@@ -16,6 +16,7 @@
 use Drupal\Tests\block\Traits\BlockCreationTrait;
 use Drupal\Tests\node\Traits\ContentTypeCreationTrait;
 use Drupal\Tests\node\Traits\NodeCreationTrait;
+use Drupal\Tests\Traits\PHPUnit8Warnings;
 use Drupal\Tests\user\Traits\UserCreationTrait;
 use Drupal\TestTools\Comparator\MarkupInterfaceComparator;
 use GuzzleHttp\Cookie\CookieJar;
@@ -63,6 +64,7 @@ abstract class BrowserTestBase extends TestCase {
     createUser as drupalCreateUser;
   }
   use XdebugRequestTrait;
+  use PHPUnit8Warnings;
 
   /**
    * The database prefix of this test run.
diff --git a/core/tests/Drupal/Tests/Component/Annotation/Doctrine/DocParserTest.php b/core/tests/Drupal/Tests/Component/Annotation/Doctrine/DocParserTest.php
index 1e2eec14f9cd479d3b3bee4539e402c1883adf9c..d894ddccbd224460be95fe2963434c075804e0e8 100644
--- a/core/tests/Drupal/Tests/Component/Annotation/Doctrine/DocParserTest.php
+++ b/core/tests/Drupal/Tests/Component/Annotation/Doctrine/DocParserTest.php
@@ -561,7 +561,7 @@ public function testAnnotationWithVarTypeError($attribute,$type,$value,$given)
             $parser->parse($docblock, $context);
             $this->fail();
         } catch (\Doctrine\Common\Annotations\AnnotationException $exc) {
-            $this->assertContains("[Type Error] Attribute \"$attribute\" of @Drupal\Tests\Component\Annotation\Doctrine\Fixtures\AnnotationWithVarType declared on property SomeClassName::invalidProperty. expects a(n) $type, but got $given.", $exc->getMessage());
+            $this->assertStringContainsString("[Type Error] Attribute \"$attribute\" of @Drupal\Tests\Component\Annotation\Doctrine\Fixtures\AnnotationWithVarType declared on property SomeClassName::invalidProperty. expects a(n) $type, but got $given.", $exc->getMessage());
         }
     }
 
@@ -580,7 +580,7 @@ public function testAnnotationWithVarTypeArrayError($attribute,$type,$value,$giv
             $parser->parse($docblock, $context);
             $this->fail();
         } catch (\Doctrine\Common\Annotations\AnnotationException $exc) {
-            $this->assertContains("[Type Error] Attribute \"$attribute\" of @Drupal\Tests\Component\Annotation\Doctrine\Fixtures\AnnotationWithVarType declared on property SomeClassName::invalidProperty. expects either a(n) $type, or an array of {$type}s, but got $given.", $exc->getMessage());
+            $this->assertStringContainsString("[Type Error] Attribute \"$attribute\" of @Drupal\Tests\Component\Annotation\Doctrine\Fixtures\AnnotationWithVarType declared on property SomeClassName::invalidProperty. expects either a(n) $type, or an array of {$type}s, but got $given.", $exc->getMessage());
         }
     }
 
@@ -616,7 +616,7 @@ public function testAnnotationWithAttributesError($attribute,$type,$value,$given
             $parser->parse($docblock, $context);
             $this->fail();
         } catch (\Doctrine\Common\Annotations\AnnotationException $exc) {
-            $this->assertContains("[Type Error] Attribute \"$attribute\" of @Drupal\Tests\Component\Annotation\Doctrine\Fixtures\AnnotationWithAttributes declared on property SomeClassName::invalidProperty. expects a(n) $type, but got $given.", $exc->getMessage());
+            $this->assertStringContainsString("[Type Error] Attribute \"$attribute\" of @Drupal\Tests\Component\Annotation\Doctrine\Fixtures\AnnotationWithAttributes declared on property SomeClassName::invalidProperty. expects a(n) $type, but got $given.", $exc->getMessage());
         }
     }
 
@@ -635,7 +635,7 @@ public function testAnnotationWithAttributesWithVarTypeArrayError($attribute,$ty
             $parser->parse($docblock, $context);
             $this->fail();
         } catch (\Doctrine\Common\Annotations\AnnotationException $exc) {
-            $this->assertContains("[Type Error] Attribute \"$attribute\" of @Drupal\Tests\Component\Annotation\Doctrine\Fixtures\AnnotationWithAttributes declared on property SomeClassName::invalidProperty. expects either a(n) $type, or an array of {$type}s, but got $given.", $exc->getMessage());
+            $this->assertStringContainsString("[Type Error] Attribute \"$attribute\" of @Drupal\Tests\Component\Annotation\Doctrine\Fixtures\AnnotationWithAttributes declared on property SomeClassName::invalidProperty. expects either a(n) $type, or an array of {$type}s, but got $given.", $exc->getMessage());
         }
     }
 
@@ -660,7 +660,7 @@ public function testAnnotationWithRequiredAttributes()
             $result = $parser->parse($docblock,$context);
             $this->fail();
         } catch (\Doctrine\Common\Annotations\AnnotationException $exc) {
-            $this->assertContains('Attribute "annot" of @Drupal\Tests\Component\Annotation\Doctrine\Fixtures\AnnotationWithRequiredAttributes declared on property SomeClassName::invalidProperty. expects a(n) Drupal\Tests\Component\Annotation\Doctrine\Fixtures\AnnotationTargetAnnotation. This value should not be null.', $exc->getMessage());
+            $this->assertStringContainsString('Attribute "annot" of @Drupal\Tests\Component\Annotation\Doctrine\Fixtures\AnnotationWithRequiredAttributes declared on property SomeClassName::invalidProperty. expects a(n) Drupal\Tests\Component\Annotation\Doctrine\Fixtures\AnnotationTargetAnnotation. This value should not be null.', $exc->getMessage());
         }
 
         $docblock   = '@Drupal\Tests\Component\Annotation\Doctrine\Fixtures\AnnotationWithRequiredAttributes(annot = @Drupal\Tests\Component\Annotation\Doctrine\Fixtures\AnnotationTargetAnnotation)';
@@ -668,7 +668,7 @@ public function testAnnotationWithRequiredAttributes()
             $result = $parser->parse($docblock,$context);
             $this->fail();
         } catch (\Doctrine\Common\Annotations\AnnotationException $exc) {
-            $this->assertContains('Attribute "value" of @Drupal\Tests\Component\Annotation\Doctrine\Fixtures\AnnotationWithRequiredAttributes declared on property SomeClassName::invalidProperty. expects a(n) string. This value should not be null.', $exc->getMessage());
+            $this->assertStringContainsString('Attribute "value" of @Drupal\Tests\Component\Annotation\Doctrine\Fixtures\AnnotationWithRequiredAttributes declared on property SomeClassName::invalidProperty. expects a(n) string. This value should not be null.', $exc->getMessage());
         }
 
     }
@@ -694,7 +694,7 @@ public function testAnnotationWithRequiredAttributesWithoutContructor()
             $result = $parser->parse($docblock,$context);
             $this->fail();
         } catch (\Doctrine\Common\Annotations\AnnotationException $exc) {
-            $this->assertContains('Attribute "annot" of @Drupal\Tests\Component\Annotation\Doctrine\Fixtures\AnnotationWithRequiredAttributesWithoutContructor declared on property SomeClassName::invalidProperty. expects a(n) Drupal\Tests\Component\Annotation\Doctrine\Fixtures\AnnotationTargetAnnotation. This value should not be null.', $exc->getMessage());
+            $this->assertStringContainsString('Attribute "annot" of @Drupal\Tests\Component\Annotation\Doctrine\Fixtures\AnnotationWithRequiredAttributesWithoutContructor declared on property SomeClassName::invalidProperty. expects a(n) Drupal\Tests\Component\Annotation\Doctrine\Fixtures\AnnotationTargetAnnotation. This value should not be null.', $exc->getMessage());
         }
 
         $docblock   = '@Drupal\Tests\Component\Annotation\Doctrine\Fixtures\AnnotationWithRequiredAttributesWithoutContructor(annot = @Drupal\Tests\Component\Annotation\Doctrine\Fixtures\AnnotationTargetAnnotation)';
@@ -702,7 +702,7 @@ public function testAnnotationWithRequiredAttributesWithoutContructor()
             $result = $parser->parse($docblock,$context);
             $this->fail();
         } catch (\Doctrine\Common\Annotations\AnnotationException $exc) {
-            $this->assertContains('Attribute "value" of @Drupal\Tests\Component\Annotation\Doctrine\Fixtures\AnnotationWithRequiredAttributesWithoutContructor declared on property SomeClassName::invalidProperty. expects a(n) string. This value should not be null.', $exc->getMessage());
+            $this->assertStringContainsString('Attribute "value" of @Drupal\Tests\Component\Annotation\Doctrine\Fixtures\AnnotationWithRequiredAttributesWithoutContructor declared on property SomeClassName::invalidProperty. expects a(n) string. This value should not be null.', $exc->getMessage());
         }
 
     }
@@ -1145,7 +1145,7 @@ public function testCastInt()
 
         $result = $parser->parse("@Name(foo=1234)");
         $annot = $result[0];
-        $this->assertInternalType('int', $annot->foo);
+        $this->assertIsInt($annot->foo);
     }
 
     /**
@@ -1157,7 +1157,7 @@ public function testCastNegativeInt()
 
         $result = $parser->parse("@Name(foo=-1234)");
         $annot = $result[0];
-        $this->assertInternalType('int', $annot->foo);
+        $this->assertIsInt($annot->foo);
     }
 
     /**
@@ -1169,7 +1169,7 @@ public function testCastFloat()
 
         $result = $parser->parse("@Name(foo=1234.345)");
         $annot = $result[0];
-        $this->assertInternalType('float', $annot->foo);
+        $this->assertIsFloat($annot->foo);
     }
 
     /**
@@ -1181,11 +1181,11 @@ public function testCastNegativeFloat()
 
         $result = $parser->parse("@Name(foo=-1234.345)");
         $annot = $result[0];
-        $this->assertInternalType('float', $annot->foo);
+        $this->assertIsFloat($annot->foo);
 
         $result = $parser->parse("@Marker(-1234.345)");
         $annot = $result[0];
-        $this->assertInternalType('float', $annot->value);
+        $this->assertIsFloat($annot->value);
     }
 
     public function testReservedKeywordsInAnnotations()
diff --git a/core/tests/Drupal/Tests/Component/FileSecurity/FileSecurityTest.php b/core/tests/Drupal/Tests/Component/FileSecurity/FileSecurityTest.php
index 0066f53d7cf01181862070e558cc63a1f8bcf921..4e4182bae605aa506189b859b4b2f7c830ad9c25 100644
--- a/core/tests/Drupal/Tests/Component/FileSecurity/FileSecurityTest.php
+++ b/core/tests/Drupal/Tests/Component/FileSecurity/FileSecurityTest.php
@@ -24,7 +24,7 @@ public function testWriteHtaccessPrivate() {
     $this->assertFileExists($htaccess_file);
     $this->assertEquals('0444', substr(sprintf('%o', fileperms($htaccess_file)), -4));
     $htaccess_contents = file_get_contents($htaccess_file);
-    $this->assertContains("Require all denied", $htaccess_contents);
+    $this->assertStringContainsString("Require all denied", $htaccess_contents);
   }
 
   /**
@@ -37,7 +37,7 @@ public function testWriteHtaccessPublic() {
     $this->assertFileExists($htaccess_file);
     $this->assertEquals('0444', substr(sprintf('%o', fileperms($htaccess_file)), -4));
     $htaccess_contents = file_get_contents($htaccess_file);
-    $this->assertNotContains("Require all denied", $htaccess_contents);
+    $this->assertStringNotContainsString("Require all denied", $htaccess_contents);
   }
 
   /**
@@ -49,8 +49,8 @@ public function testWriteHtaccessForceOverwrite() {
     file_put_contents($htaccess_file, "foo");
     $this->assertTrue(FileSecurity::writeHtaccess(vfsStream::url('root'), TRUE, TRUE));
     $htaccess_contents = file_get_contents($htaccess_file);
-    $this->assertContains("Require all denied", $htaccess_contents);
-    $this->assertNotContains("foo", $htaccess_contents);
+    $this->assertStringContainsString("Require all denied", $htaccess_contents);
+    $this->assertStringNotContainsString("foo", $htaccess_contents);
   }
 
   /**
@@ -82,7 +82,7 @@ public function testWriteWebConfigForceOverwrite() {
     $this->assertTrue(FileSecurity::writeWebConfig(vfsStream::url('root'), TRUE));
     $this->assertFileExists($web_config_file);
     $this->assertEquals('0444', substr(sprintf('%o', fileperms($web_config_file)), -4));
-    $this->assertNotContains("foo", $web_config_file);
+    $this->assertStringNotContainsString("foo", $web_config_file);
   }
 
   /**
diff --git a/core/tests/Drupal/Tests/Composer/Plugin/Scaffold/AssertUtilsTrait.php b/core/tests/Drupal/Tests/Composer/Plugin/Scaffold/AssertUtilsTrait.php
index 2f39d832ec802a5c4592eaace52363863b48deb6..f4164c7aedb69f19226fe61b521545e3c76f430c 100644
--- a/core/tests/Drupal/Tests/Composer/Plugin/Scaffold/AssertUtilsTrait.php
+++ b/core/tests/Drupal/Tests/Composer/Plugin/Scaffold/AssertUtilsTrait.php
@@ -2,10 +2,13 @@
 
 namespace Drupal\Tests\Composer\Plugin\Scaffold;
 
+use Drupal\Tests\Traits\PHPUnit8Warnings;
+
 /**
  * Convenience class for creating fixtures.
  */
 trait AssertUtilsTrait {
+  use PHPUnit8Warnings;
 
   /**
    * Asserts that a given file exists and is/is not a symlink.
diff --git a/core/tests/Drupal/Tests/Composer/Plugin/Scaffold/Integration/AppendOpTest.php b/core/tests/Drupal/Tests/Composer/Plugin/Scaffold/Integration/AppendOpTest.php
index d5fadedec12ed5b01709883537a5d20b0cfafff0..706ca674158e77b91002a3708f19ea48c95a51f5 100644
--- a/core/tests/Drupal/Tests/Composer/Plugin/Scaffold/Integration/AppendOpTest.php
+++ b/core/tests/Drupal/Tests/Composer/Plugin/Scaffold/Integration/AppendOpTest.php
@@ -5,6 +5,7 @@
 use Drupal\Composer\Plugin\Scaffold\Operations\AppendOp;
 use Drupal\Composer\Plugin\Scaffold\ScaffoldOptions;
 use Drupal\Tests\Composer\Plugin\Scaffold\Fixtures;
+use Drupal\Tests\Traits\PHPUnit8Warnings;
 use PHPUnit\Framework\TestCase;
 
 /**
@@ -13,6 +14,7 @@
  * @group Scaffold
  */
 class AppendOpTest extends TestCase {
+  use PHPUnit8Warnings;
 
   /**
    * @covers ::process
diff --git a/core/tests/Drupal/Tests/Composer/Plugin/Scaffold/Integration/ReplaceOpTest.php b/core/tests/Drupal/Tests/Composer/Plugin/Scaffold/Integration/ReplaceOpTest.php
index ee6bb73a8d8ea03ab24ae4e2d90789ed5529b96d..0f3d6934f51429aa48dc5f8e4ea27515d822ea99 100644
--- a/core/tests/Drupal/Tests/Composer/Plugin/Scaffold/Integration/ReplaceOpTest.php
+++ b/core/tests/Drupal/Tests/Composer/Plugin/Scaffold/Integration/ReplaceOpTest.php
@@ -5,6 +5,7 @@
 use Drupal\Composer\Plugin\Scaffold\Operations\ReplaceOp;
 use Drupal\Composer\Plugin\Scaffold\ScaffoldOptions;
 use Drupal\Tests\Composer\Plugin\Scaffold\Fixtures;
+use Drupal\Tests\Traits\PHPUnit8Warnings;
 use PHPUnit\Framework\TestCase;
 
 /**
@@ -13,6 +14,7 @@
  * @group Scaffold
  */
 class ReplaceOpTest extends TestCase {
+  use PHPUnit8Warnings;
 
   /**
    * @covers ::process
diff --git a/core/tests/Drupal/Tests/Composer/Plugin/Scaffold/Integration/SkipOpTest.php b/core/tests/Drupal/Tests/Composer/Plugin/Scaffold/Integration/SkipOpTest.php
index 75c07a1f6ef5e4ed68f0f722e791bb28a5e08cd4..77ece82c83d7f7b635c66f252c0cbc92286a123f 100644
--- a/core/tests/Drupal/Tests/Composer/Plugin/Scaffold/Integration/SkipOpTest.php
+++ b/core/tests/Drupal/Tests/Composer/Plugin/Scaffold/Integration/SkipOpTest.php
@@ -5,6 +5,7 @@
 use Drupal\Composer\Plugin\Scaffold\Operations\SkipOp;
 use Drupal\Composer\Plugin\Scaffold\ScaffoldOptions;
 use Drupal\Tests\Composer\Plugin\Scaffold\Fixtures;
+use Drupal\Tests\Traits\PHPUnit8Warnings;
 use PHPUnit\Framework\TestCase;
 
 /**
@@ -13,6 +14,7 @@
  * @group Scaffold
  */
 class SkipOpTest extends TestCase {
+  use PHPUnit8Warnings;
 
   /**
    * @covers ::process
diff --git a/core/tests/Drupal/Tests/Composer/Plugin/VendorHardening/ConfigTest.php b/core/tests/Drupal/Tests/Composer/Plugin/VendorHardening/ConfigTest.php
index 71b1c0ae104b93cd5ba85042310a735abd5f599b..9755278b512ccfc89798b121e0dd79d6f6506a58 100644
--- a/core/tests/Drupal/Tests/Composer/Plugin/VendorHardening/ConfigTest.php
+++ b/core/tests/Drupal/Tests/Composer/Plugin/VendorHardening/ConfigTest.php
@@ -77,10 +77,8 @@ public function testRootMergeConfig() {
 
     $plugin_config = $ref_plugin_config->invoke($config);
 
-    $this->assertArraySubset([
-      'isa/string' => ['test_dir'],
-      'an/array' => ['test_dir', 'doc_dir'],
-    ], $plugin_config);
+    $this->assertSame(['test_dir'], $plugin_config['isa/string']);
+    $this->assertSame(['test_dir', 'doc_dir'], $plugin_config['an/array']);
   }
 
   /**
diff --git a/core/tests/Drupal/Tests/Core/Command/QuickStartTest.php b/core/tests/Drupal/Tests/Core/Command/QuickStartTest.php
index b9e8566d9c3d610b9d59dead2691f3a20373a530..9ba14675dd84dd62683d03e9c89b954da45fb484 100644
--- a/core/tests/Drupal/Tests/Core/Command/QuickStartTest.php
+++ b/core/tests/Drupal/Tests/Core/Command/QuickStartTest.php
@@ -114,12 +114,12 @@ public function testQuickStartCommand() {
       sleep(1);
     }
     // The progress bar uses STDERR to write messages.
-    $this->assertContains('Congratulations, you installed Drupal!', $process->getErrorOutput());
+    $this->assertStringContainsString('Congratulations, you installed Drupal!', $process->getErrorOutput());
     $this->assertNotFalse($port, "Web server running on port $port");
 
     // Give the server a couple of seconds to be ready.
     sleep(2);
-    $this->assertContains("127.0.0.1:$port/user/reset/1/", $process->getOutput());
+    $this->assertStringContainsString("127.0.0.1:$port/user/reset/1/", $process->getOutput());
 
     // Generate a cookie so we can make a request against the installed site.
     define('DRUPAL_TEST_IN_CHILD_SITE', FALSE);
@@ -130,7 +130,7 @@ public function testQuickStartCommand() {
 
     $response = $guzzle->get('http://127.0.0.1:' . $port, ['cookies' => $cookieJar]);
     $content = (string) $response->getBody();
-    $this->assertContains('Test site ' . $this->testDb->getDatabasePrefix(), $content);
+    $this->assertStringContainsString('Test site ' . $this->testDb->getDatabasePrefix(), $content);
 
     // Stop the web server.
     $process->stop();
@@ -162,9 +162,9 @@ public function testPhpRequirement() {
     }
 
     $error_output = $process->getErrorOutput();
-    $this->assertContains('Your PHP installation is too old.', $error_output);
-    $this->assertContains('Drupal requires at least PHP', $error_output);
-    $this->assertContains(DRUPAL_MINIMUM_SUPPORTED_PHP, $error_output);
+    $this->assertStringContainsString('Your PHP installation is too old.', $error_output);
+    $this->assertStringContainsString('Drupal requires at least PHP', $error_output);
+    $this->assertStringContainsString(DRUPAL_MINIMUM_SUPPORTED_PHP, $error_output);
 
     // Stop the web server.
     $process->stop();
@@ -191,7 +191,7 @@ public function testQuickStartInstallAndServerCommands() {
     $install_process->setTimeout(500);
     $result = $install_process->run();
     // The progress bar uses STDERR to write messages.
-    $this->assertContains('Congratulations, you installed Drupal!', $install_process->getErrorOutput());
+    $this->assertStringContainsString('Congratulations, you installed Drupal!', $install_process->getErrorOutput());
     $this->assertSame(0, $result);
 
     // Run the PHP built-in webserver.
@@ -215,7 +215,7 @@ public function testQuickStartInstallAndServerCommands() {
       sleep(1);
     }
     $this->assertEquals('', $server_process->getErrorOutput());
-    $this->assertContains("127.0.0.1:$port/user/reset/1/", $server_process->getOutput());
+    $this->assertStringContainsString("127.0.0.1:$port/user/reset/1/", $server_process->getOutput());
     $this->assertNotFalse($port, "Web server running on port $port");
 
     // Give the server a couple of seconds to be ready.
@@ -230,7 +230,7 @@ public function testQuickStartInstallAndServerCommands() {
 
     $response = $guzzle->get('http://127.0.0.1:' . $port, ['cookies' => $cookieJar]);
     $content = (string) $response->getBody();
-    $this->assertContains('Test site ' . $this->testDb->getDatabasePrefix(), $content);
+    $this->assertStringContainsString('Test site ' . $this->testDb->getDatabasePrefix(), $content);
 
     // Try to re-install over the top of an existing site.
     $install_command = [
@@ -244,13 +244,13 @@ public function testQuickStartInstallAndServerCommands() {
     $install_process->inheritEnvironmentVariables();
     $install_process->setTimeout(500);
     $result = $install_process->run();
-    $this->assertContains('Drupal is already installed.', $install_process->getOutput());
+    $this->assertStringContainsString('Drupal is already installed.', $install_process->getOutput());
     $this->assertSame(0, $result);
 
     // Ensure the site name has not changed.
     $response = $guzzle->get('http://127.0.0.1:' . $port, ['cookies' => $cookieJar]);
     $content = (string) $response->getBody();
-    $this->assertContains('Test site ' . $this->testDb->getDatabasePrefix(), $content);
+    $this->assertStringContainsString('Test site ' . $this->testDb->getDatabasePrefix(), $content);
 
     // Stop the web server.
     $server_process->stop();
@@ -272,7 +272,7 @@ public function testQuickStartCommandProfileValidation() {
     $process = new Process($install_command, NULL, ['DRUPAL_DEV_SITE_PATH' => $this->testDb->getTestSitePath()]);
     $process->inheritEnvironmentVariables();
     $process->run();
-    $this->assertContains('\'umami\' is not a valid install profile. Did you mean \'demo_umami\'?', $process->getErrorOutput());
+    $this->assertStringContainsString('\'umami\' is not a valid install profile. Did you mean \'demo_umami\'?', $process->getErrorOutput());
   }
 
   /**
@@ -288,7 +288,7 @@ public function testServerWithNoInstall() {
     $server_process = new Process($server_command, NULL, ['DRUPAL_DEV_SITE_PATH' => $this->testDb->getTestSitePath()]);
     $server_process->inheritEnvironmentVariables();
     $server_process->run();
-    $this->assertContains('No installation found. Use the \'install\' command.', $server_process->getErrorOutput());
+    $this->assertStringContainsString('No installation found. Use the \'install\' command.', $server_process->getErrorOutput());
   }
 
   /**
diff --git a/core/tests/Drupal/Tests/Listeners/DeprecationListenerTrait.php b/core/tests/Drupal/Tests/Listeners/DeprecationListenerTrait.php
index 362f38c3c234eecc0e19665f221baa2482fed2d2..40eecbf2c5d489ef375f0d96e8dd311e5e1e7878 100644
--- a/core/tests/Drupal/Tests/Listeners/DeprecationListenerTrait.php
+++ b/core/tests/Drupal/Tests/Listeners/DeprecationListenerTrait.php
@@ -114,6 +114,7 @@ public static function isDeprecationSkipped($message) {
       '%The "[^"]+" class extends "Symfony\\\\Component\\\\EventDispatcher\\\\Event" that is deprecated since Symfony 4\.3, use "Symfony\\\\Contracts\\\\EventDispatcher\\\\Event" instead\.$%',
       '%The "Symfony\\\\Component\\\\Validator\\\\Context\\\\ExecutionContextInterface::.*\(\)" method is considered internal Used by the validator engine. Should not be called by user\s\*\s*code\. It may change without further notice\. You should not extend it from "[^"]+".%',
       '%The ".*" service relies on the deprecated "Symfony\\\\Component\\\\Debug\\\\BufferingLogger" class\. It should either be deprecated or its implementation upgraded\.%',
+      '%The "PHPUnit\\\\Framework\\\\TestCase::addWarning\(\)" method is considered internal%',
     ];
     return (bool) preg_filter($dynamic_skipped_deprecations, '$0', $message);
   }
diff --git a/core/tests/Drupal/Tests/Traits/PHPUnit8Warnings.php b/core/tests/Drupal/Tests/Traits/PHPUnit8Warnings.php
new file mode 100644
index 0000000000000000000000000000000000000000..5912ff048c102fdb43deefce3f2f6818f779d5be
--- /dev/null
+++ b/core/tests/Drupal/Tests/Traits/PHPUnit8Warnings.php
@@ -0,0 +1,55 @@
+<?php
+
+namespace Drupal\Tests\Traits;
+
+/**
+ * Used to ignore warnings being added by PHPUnit 8.
+ *
+ * This trait exists to allow Drupal 8 tests using PHPUnit 7 and Drupal 9 tests
+ * using PHPUnit 8 to happily co-exist. Once Drupal 8 and Drupal 9 are not so
+ * closely aligned these will be fixed in core and the warnings will be emitted
+ * from the test runner.
+ *
+ * @todo https://www.drupal.org/project/drupal/issues/3110543 Remove the ignored
+ *   warnings to support PHPUnit 9.
+ *
+ * @internal
+ */
+trait PHPUnit8Warnings {
+
+  /**
+   * The list of warnings to ignore.
+   *
+   * @var string[]
+   */
+  private static $ignoredWarnings = [
+    'Using assertContains() with string haystacks is deprecated and will not be supported in PHPUnit 9. Refactor your test to use assertStringContainsString() or assertStringContainsStringIgnoringCase() instead.',
+    'Using assertNotContains() with string haystacks is deprecated and will not be supported in PHPUnit 9. Refactor your test to use assertStringNotContainsString() or assertStringNotContainsStringIgnoringCase() instead.',
+    'assertArraySubset() is deprecated and will be removed in PHPUnit 9.',
+    'assertInternalType() is deprecated and will be removed in PHPUnit 9. Refactor your test to use assertIsArray(), assertIsBool(), assertIsFloat(), assertIsInt(), assertIsNumeric(), assertIsObject(), assertIsResource(), assertIsString(), assertIsScalar(), assertIsCallable(), or assertIsIterable() instead.',
+    'readAttribute() is deprecated and will be removed in PHPUnit 9.',
+    'getObjectAttribute() is deprecated and will be removed in PHPUnit 9.',
+    'The optional $canonicalize parameter of assertEquals() is deprecated and will be removed in PHPUnit 9. Refactor your test to use assertEqualsCanonicalizing() instead.',
+    'assertAttributeEquals() is deprecated and will be removed in PHPUnit 9.',
+    'assertAttributeSame() is deprecated and will be removed in PHPUnit 9.',
+    'assertAttributeInstanceOf() is deprecated and will be removed in PHPUnit 9.',
+    'assertAttributeEmpty() is deprecated and will be removed in PHPUnit 9.',
+    'The optional $ignoreCase parameter of assertContains() is deprecated and will be removed in PHPUnit 9.',
+    'The optional $ignoreCase parameter of assertNotContains() is deprecated and will be removed in PHPUnit 9.',
+  ];
+
+  /**
+   * Ignores specific PHPUnit 8 warnings.
+   *
+   * @see \PHPUnit\Framework\TestCase::addWarning()
+   *
+   * @internal
+   */
+  public function addWarning(string $warning): void {
+    if (in_array($warning, self::$ignoredWarnings, TRUE)) {
+      return;
+    }
+    parent::addWarning($warning);
+  }
+
+}
diff --git a/core/tests/Drupal/Tests/UnitTestCase.php b/core/tests/Drupal/Tests/UnitTestCase.php
index f6cfaf4cbe512aa2830c8af3f7057f2901cf798c..8f5b85640266d5562e4d2fc1c039388565e9f726 100644
--- a/core/tests/Drupal/Tests/UnitTestCase.php
+++ b/core/tests/Drupal/Tests/UnitTestCase.php
@@ -9,6 +9,7 @@
 use Drupal\Core\DependencyInjection\ContainerBuilder;
 use Drupal\Core\StringTranslation\TranslatableMarkup;
 use Drupal\Core\StringTranslation\PluralTranslatableMarkup;
+use Drupal\Tests\Traits\PHPUnit8Warnings;
 use PHPUnit\Framework\TestCase;
 
 /**
@@ -17,6 +18,7 @@
  * @ingroup testing
  */
 abstract class UnitTestCase extends TestCase {
+  use PHPUnit8Warnings;
 
   /**
    * The random generator.