diff --git a/core/modules/system/src/Tests/Form/AccessibilityTest.php b/core/modules/system/src/Tests/Form/AccessibilityTest.php
new file mode 100644
index 0000000..271580e
--- /dev/null
+++ b/core/modules/system/src/Tests/Form/AccessibilityTest.php
@@ -0,0 +1,90 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Tests\Core\Form\AccessibilityTest.
+ */
+
+namespace Drupal\system\Tests\Form;
+
+use Drupal\simpletest\WebTestBase;
+use Drupal\system\Tests\Common\SystemListingTest;
+
+/**
+ * Performs basic accessibility tests for all forms provided by extensions.
+ *
+ * To save some processing power, this test only scans for forms in the
+ * Drupal\$extension\Form namespace of all modules.
+ */
+class AccessibilityTest extends WebTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name' => 'Form accessibility',
+      'description' => 'Tests that all forms follow basic accessibility best practices.',
+      'group' => 'Form API',
+    );
+  }
+
+  /**
+   * Performs accessibility tests on all forms provided by modules.
+   */
+  public function testFormAccessibility() {
+    $module_handler = \Drupal::moduleHandler();
+
+    // Scan all modules for forms.
+    $forms = array();
+    $scanner = new SystemListingTest(array(drupal_get_profile());
+    $modules = $scanner->scan('/^' . DRUPAL_PHP_FUNCTION_PATTERN . '\.info.yml$/', 'modules');
+    foreach ($modules as $module_file) {
+      $module_name = basename($module_file->filename, '.info.yml');
+      // We only look for files in the Drupal\$module_name\Form namespace, and assume
+      // there are no further directories.
+      $directory = dirname($module_file->uri) . "/lib/Drupal/$module_name/Form";
+      if (is_dir($directory)) {
+        $files = array_diff(scandir($directory), array('.', '..'));
+        foreach ($files as $file) {
+          $class = "Drupal\\$module_name\\Form\\" . basename($file, '.php');
+          if (is_subclass_of($class, 'Drupal\Core\Form\FormInterface')) {
+            $forms[$module_name][] = $class;
+          }
+        }
+      }
+    }
+
+    // Perform tests on all forms.
+    foreach ($forms as $module_name => $module_forms) {
+      $module_handler->install(array($module_name));
+      foreach ($module_forms as $form_class) {
+        $this->doTestFormElementTitle($form_class);
+      }
+    }
+  }
+
+  /**
+   * Tests that all form elements of a form have a title.
+   *
+   * @param string $class
+   *   The class name of the form.
+   */
+  public function doTestFormElementTitle($class) {
+    // @todo Entity form controllers need an entity to be constructed
+    //   properly.
+    if (is_subclass_of($class, 'Drupal\Core\Entity\EntityFormControllerInterface')) {
+      $this->verbose("Skipping class '$class' because entity forms cannot be instantiated generically.");
+      return;
+    }
+    // Some forms throw exceptions if the arguments passed into
+    // FormInterface::buildForm() are missing or incorrect.
+    try {
+      $form = \Drupal::formBuilder()->getForm($class);
+    } catch (\Exception $e) {
+      $this->verbose("Skipping class '$class' because it threw an exception during form building.");
+      return;
+    }
+  }
+
+}
