diff --git a/core/modules/simpletest/src/TestBase.php b/core/modules/simpletest/src/TestBase.php
index 1491cc2af1..945db6a141 100644
--- a/core/modules/simpletest/src/TestBase.php
+++ b/core/modules/simpletest/src/TestBase.php
@@ -7,6 +7,7 @@
 use Drupal\Component\Utility\Crypt;
 use Drupal\Component\Utility\SafeMarkup;
 use Drupal\Core\Database\Database;
+use Drupal\Core\Extension\ExtensionDiscovery;
 use Drupal\Core\Site\Settings;
 use Drupal\Core\StreamWrapper\PublicStream;
 use Drupal\Core\Test\TestDatabase;
@@ -249,10 +250,51 @@ public function __construct($test_id = NULL) {
   abstract protected function setUp();
 
   /**
-   * Checks the matching requirements for Test.
+   * Check annotated requirements for this test class.
    *
-   * @return
-   *   Array of errors containing a list of unmet requirements.
+   * Currently supported test class annotations:
+   * - @requires module module_name
+   * - @dependencies module_name1, module_name2, etc
+   *
+   * Test classes can be annotated with multiple '@requires module' annotations,
+   * which is functionally identical to listing multiple modules in
+   * @dependencies.
+   *
+   * This method is private and final because these are the only supported
+   * annotation declarations for Simpletest-based tests in Drupal. Tests with
+   * more sophisticated requirement declaration needs should convert to
+   * KernelTestBase or BrowserTestBase.
+   *
+   * @param string[] $annotations
+   *   Keyed array of annotations for this class. This should be the output of
+   *   \Drupal\simpletest\TestDiscovery::getInfo().
+   *
+   * @return string[]
+   *   Array of error messages describing unmet requirements, or empty array if
+   *   all requirements are met.
+   *
+   * @see \Drupal\simpletest\TestDiscovery::getInfo()
+   * @see \Drupal\simpletest\TestBase::checkRequirements()
+   */
+  final private function checkAnnotatedRequirements($annotations) {
+    // Annotations for @dependencies are converted to a 'requires' array.
+    if (!empty($annotations['requires']['module'])) {
+      $extension_discovery = new ExtensionDiscovery(\Drupal::root(), TRUE);
+      $extensions = array_keys($extension_discovery->scan('module', TRUE));
+      if ($diff = array_diff($annotations['requires']['module'], $extensions)) {
+        return ['This test requires the following modules to be discoverable on the file system: ' . implode(', ', $diff)];
+      }
+    }
+    return [];
+  }
+
+  /**
+   * Checks the requirements for this test.
+   *
+   * Subclasses implementing this method should
+   *
+   * @return string[]
+   *   Array of error messages describing unmet requirements.
    */
   protected function checkRequirements() {
     return [];
@@ -861,7 +903,13 @@ protected function verbose($message) {
   public function run(array $methods = []) {
     $class = get_class($this);
 
-    if ($missing_requirements = $this->checkRequirements()) {
+    // Check for unmet requirements.
+    $missing_requirements = array_merge(
+      $this->checkAnnotatedRequirements(TestDiscovery::getTestInfo(get_class($this))),
+      $this->checkRequirements()
+    );
+    // Report the unmet requirements if there are any.
+    if ($missing_requirements) {
       $object_info = new \ReflectionObject($this);
       $caller = [
         'file' => $object_info->getFileName(),
diff --git a/core/modules/simpletest/src/TestDiscovery.php b/core/modules/simpletest/src/TestDiscovery.php
index 5374520e56..d6fb69e7cb 100644
--- a/core/modules/simpletest/src/TestDiscovery.php
+++ b/core/modules/simpletest/src/TestDiscovery.php
@@ -189,14 +189,15 @@ public function getTestClasses($extension = NULL, array $types = []) {
         // abstract class, trait or test fixture.
         continue;
       }
-      // Skip this test class if it requires unavailable modules.
-      // @todo PHPUnit skips tests with unmet requirements when executing a test
-      //   (instead of excluding them upfront). Refactor test runner to follow
-      //   that approach.
-      // @see https://www.drupal.org/node/1273478
-      if (!empty($info['requires']['module'])) {
-        if (array_diff($info['requires']['module'], $this->availableExtensions['module'])) {
-          continue;
+      // Skip tests that are not Simpletest-based tests.
+      // @todo Remove this when all test types can figure out their own
+      // requirements.
+      // @see https://www.drupal.org/node/2728579
+      if ($info['type'] !== 'Simpletest') {
+        if (!empty($info['requires']['module'])) {
+          if (array_diff($info['requires']['module'], $this->availableExtensions['module'])) {
+            continue;
+          }
         }
       }
 
diff --git a/core/modules/simpletest/tests/src/Kernel/TestBaseTest.php b/core/modules/simpletest/tests/src/Kernel/TestBaseTest.php
new file mode 100644
index 0000000000..83c1c041d1
--- /dev/null
+++ b/core/modules/simpletest/tests/src/Kernel/TestBaseTest.php
@@ -0,0 +1,54 @@
+<?php
+
+namespace Drupal\Tests\simpletest\Kernel;
+
+use Drupal\KernelTests\KernelTestBase;
+use Drupal\simpletest\TestBase;
+
+/**
+ * @group simpletest
+ *
+ * @coversDefaultClass Drupal\simpletest\TestBase
+ */
+class TestBaseTest extends KernelTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static $modules = ['simpletest'];
+
+  public function provideAnnotatedRequirements() {
+    return [
+      'all_requirements_met' => [
+        [],
+        ['requires' => ['module' => ['simpletest']]],
+      ],
+      'requirement_not_met' => [
+        ['This test requires the following modules to be discoverable on the file system: test_module_dne'],
+        ['requires' => ['module' => ['test_module_dne']]],
+      ],
+      'dependencies_should_have_been_converted' => [
+        [],
+        ['dependencies' => ['module' => ['test_module_dne']]],
+      ],
+      'second_req_not_met' => [
+        ['This test requires the following modules to be discoverable on the file system: test_module_dne'],
+        ['requires' => ['module' => ['simpletest', 'test_module_dne']]],
+      ],
+    ];
+  }
+
+  /**
+   * @covers ::checkAnnotatedRequirements
+   * @dataProvider provideAnnotatedRequirements
+   */
+  public function testCheckAnnotatedRequirements($expected, $annotations) {
+    $test_base = $this->getMockBuilder(TestBase::class)
+      ->getMockForAbstractClass();
+    $check_ref = new \ReflectionMethod($test_base, 'checkAnnotatedRequirements');
+    $check_ref->setAccessible(TRUE);
+
+    $this->assertSame($expected, $check_ref->invokeArgs($test_base, [$annotations]));
+  }
+  
+}
