diff --git a/core/includes/common.inc b/core/includes/common.inc
index b97cc5e..0a3c96a 100644
--- a/core/includes/common.inc
+++ b/core/includes/common.inc
@@ -1926,18 +1926,7 @@ function drupal_html_id($id) {
   }
   $seen_ids = &drupal_static(__FUNCTION__, $seen_ids_init);
 
-  $id = strtr(drupal_strtolower($id), array(' ' => '-', '_' => '-', '[' => '-', ']' => ''));
-
-  // As defined in http://www.w3.org/TR/html4/types.html#type-name, HTML IDs can
-  // only contain letters, digits ([0-9]), hyphens ("-"), underscores ("_"),
-  // colons (":"), and periods ("."). We strip out any character not in that
-  // list. Note that the CSS spec doesn't allow colons or periods in identifiers
-  // (http://www.w3.org/TR/CSS21/syndata.html#characters), so we strip those two
-  // characters as well.
-  $id = preg_replace('/[^A-Za-z0-9\-_]/', '', $id);
-
-  // Removing multiple consecutive hyphens.
-  $id = preg_replace('/\-+/', '-', $id);
+  $id = drupal_clean_id_identifier($id);
   // Ensure IDs are unique by appending a counter after the first occurrence.
   // The counter needs to be appended with a delimiter that does not exist in
   // the base ID. Requiring a unique delimiter helps ensure that we really do
@@ -1954,6 +1943,36 @@ function drupal_html_id($id) {
 }
 
 /**
+ * Prepares a string for use as a valid HTML ID.
+ *
+ * Only use this function when you want to intentionally skip the uniqueness
+ * guarantee of drupal_html_id().
+ *
+ * @param string $id
+ *   The ID to clean.
+ *
+ * @return string
+ *   The cleaned ID.
+ *
+ * @see drupal_html_id()
+ */
+function drupal_clean_id_identifier($id) {
+  $id = strtr(drupal_strtolower($id), array(' ' => '-', '_' => '-', '[' => '-', ']' => ''));
+
+  // As defined in http://www.w3.org/TR/html4/types.html#type-name, HTML IDs can
+  // only contain letters, digits ([0-9]), hyphens ("-"), underscores ("_"),
+  // colons (":"), and periods ("."). We strip out any character not in that
+  // list. Note that the CSS spec doesn't allow colons or periods in identifiers
+  // (http://www.w3.org/TR/CSS21/syndata.html#characters), so we strip those two
+  // characters as well.
+  $id = preg_replace('/[^A-Za-z0-9\-_]/', '', $id);
+
+  // Removing multiple consecutive hyphens.
+  $id = preg_replace('/\-+/', '-', $id);
+  return $id;
+}
+
+/**
  * Adds a JavaScript file, setting, or inline code to the page.
  *
  * The behavior of this function depends on the parameters it is called with.
diff --git a/core/includes/form.inc b/core/includes/form.inc
index 5d4a943..65c15f2 100644
--- a/core/includes/form.inc
+++ b/core/includes/form.inc
@@ -1697,52 +1697,81 @@ function form_process_table($element, &$form_state) {
     // tableselect element behaves as if it had been of #type checkboxes or
     // radios.
     foreach (element_children($element) as $key) {
+      $row = &$element[$key];
+      // Prepare the element #parents for the tableselect form element.
+      // Their values have to be located in child keys (#tree is ignored), since
+      // form_validate_table() has to be able to validate whether input (for the
+      // parent #type 'table' element) has been submitted.
+      $element_parents = array_merge($element['#parents'], array($key));
+
+      // Since the #parents of the tableselect form element will equal the
+      // #parents of the row element, prevent FormBuilder from auto-generating
+      // an #id for the row element, since drupal_html_id() would automatically
+      // append a suffix to the tableselect form element's #id otherwise.
+      $row['#id'] = drupal_html_id('edit-' . implode('-', $element_parents) . '-row');
+
       // Do not overwrite manually created children.
-      if (!isset($element[$key]['select'])) {
+      if (!isset($row['select'])) {
         // Determine option label; either an assumed 'title' column, or the
         // first available column containing a #title or #markup.
         // @todo Consider to add an optional $element[$key]['#title_key']
         //   defaulting to 'title'?
-        $title = '';
-        if (!empty($element[$key]['title']['#title'])) {
-          $title = $element[$key]['title']['#title'];
+        unset($label_element);
+        $title = NULL;
+        if (isset($row['title']['#type']) && $row['title']['#type'] == 'label') {
+          $label_element = &$row['title'];
         }
         else {
-          foreach (element_children($element[$key]) as $column) {
-            if (isset($element[$key][$column]['#title'])) {
-              $title = $element[$key][$column]['#title'];
-              break;
-            }
-            if (isset($element[$key][$column]['#markup'])) {
-              $title = $element[$key][$column]['#markup'];
-              break;
+          if (!empty($row['title']['#title'])) {
+            $title = $row['title']['#title'];
+          }
+          else {
+            foreach (element_children($row) as $column) {
+              if (isset($row[$column]['#title'])) {
+                $title = $row[$column]['#title'];
+                break;
+              }
+              if (isset($row[$column]['#markup'])) {
+                $title = $row[$column]['#markup'];
+                break;
+              }
             }
           }
-        }
-        if ($title !== '') {
-          $title = t('Update !title', array('!title' => $title));
+          if (isset($title) && $title !== '') {
+            $title = t('Update !title', array('!title' => $title));
+          }
         }
 
         // Prepend the select column to existing columns.
-        $element[$key] = array('select' => array()) + $element[$key];
-        $element[$key]['select'] += array(
+        $row = array('select' => array()) + $row;
+        $row['select'] += array(
           '#type' => $element['#multiple'] ? 'checkbox' : 'radio',
-          '#title' => $title,
-          '#title_display' => 'invisible',
+          '#id' => drupal_html_id('edit-' . implode('-', $element_parents)),
           // @todo If rows happen to use numeric indexes instead of string keys,
           //   this results in a first row with $key === 0, which is always FALSE.
           '#return_value' => $key,
           '#attributes' => $element['#attributes'],
+          '#wrapper_attributes' => array(
+            'class' => array('table-select'),
+          ),
         );
-        $element_parents = array_merge($element['#parents'], array($key));
         if ($element['#multiple']) {
-          $element[$key]['select']['#default_value'] = isset($value[$key]) ? $key : NULL;
-          $element[$key]['select']['#parents'] = $element_parents;
+          $row['select']['#default_value'] = isset($value[$key]) ? $key : NULL;
+          $row['select']['#parents'] = $element_parents;
         }
         else {
-          $element[$key]['select']['#default_value'] = ($element['#default_value'] == $key ? $key : NULL);
-          $element[$key]['select']['#parents'] = $element['#parents'];
-          $element[$key]['select']['#id'] = drupal_html_id('edit-' . implode('-', $element_parents));
+          $row['select']['#default_value'] = ($element['#default_value'] == $key ? $key : NULL);
+          $row['select']['#parents'] = $element['#parents'];
+        }
+        if ($label_element) {
+          $label_element['#id'] = $row['select']['#id'] . '--label';
+          $label_element['#for'] = $row['select']['#id'];
+          $row['select']['#attributes']['aria-labelledby'] = $label_element['#id'];
+          $row['select']['#title_display'] = 'none';
+        }
+        else {
+          $row['select']['#title'] = $title;
+          $row['select']['#title_display'] = 'invisible';
         }
       }
     }
@@ -2866,7 +2895,17 @@ function theme_form_element_label($variables) {
     $attributes['class'] = 'visually-hidden';
   }
 
-  if (!empty($element['#id'])) {
+  // A #for property of a dedicated #type 'label' element as precedence.
+  if (!empty($element['#for'])) {
+    $attributes['for'] = $element['#for'];
+    // A custom #id allows the referenced form input element to refer back to
+    // the label element; e.g., in the 'aria-labelledby' attribute.
+    if (!empty($element['#id'])) {
+      $attributes['id'] = $element['#id'];
+    }
+  }
+  // Otherwise, point to the #id of the form input element.
+  elseif (!empty($element['#id'])) {
     $attributes['for'] = $element['#id'];
   }
 
diff --git a/core/modules/simpletest/css/simpletest.module.css b/core/modules/simpletest/css/simpletest.module.css
index 86bd04b..611cc4a 100644
--- a/core/modules/simpletest/css/simpletest.module.css
+++ b/core/modules/simpletest/css/simpletest.module.css
@@ -3,7 +3,7 @@
 #simpletest-form-table th.select-all {
   width: 1em;
 }
-th.simpletest_test {
+th.simpletest-test-label {
   width: 16em;
 }
 
diff --git a/core/modules/simpletest/lib/Drupal/simpletest/Form/SimpletestTestForm.php b/core/modules/simpletest/lib/Drupal/simpletest/Form/SimpletestTestForm.php
index c469b52..57e1a20 100644
--- a/core/modules/simpletest/lib/Drupal/simpletest/Form/SimpletestTestForm.php
+++ b/core/modules/simpletest/lib/Drupal/simpletest/Form/SimpletestTestForm.php
@@ -7,6 +7,8 @@
 
 namespace Drupal\simpletest\Form;
 
+use Drupal\Component\Utility\SortArray;
+use Drupal\Component\Utility\String;
 use Drupal\Core\Form\FormBase;
 
 /**
@@ -51,8 +53,46 @@ public function buildForm(array $form, array &$form_state) {
       '#description' => $this->t('Select the test(s) or test group(s) you would like to run, and click <em>Run tests</em>.'),
     );
 
-    $form['tests']['table'] = array(
-      '#theme' => 'simpletest_test_table',
+    $form['tests'] = array(
+      '#type' => 'table',
+      '#id' => 'simpletest-form-table',
+      '#tableselect' => TRUE,
+      '#header' => array(
+        array('data' => $this->t('Test'), 'class' => array('simpletest-test-label')),
+        array('data' => $this->t('Description'), 'class' => array('simpletest-test-description')),
+      ),
+      '#empty' => $this->t('No tests to display.'),
+      '#attached' => array(
+        'library' => array(
+          array('simpletest', 'drupal.simpletest'),
+        ),
+      ),
+    );
+
+    // Define the images used to expand/collapse the test groups.
+    $image_collapsed = array(
+      '#theme' => 'image',
+      '#uri' => 'core/misc/menu-collapsed.png',
+      '#width' => '7',
+      '#height' => '7',
+      '#alt' => $this->t('Expand'),
+      '#title' => $this->t('Expand'),
+      '#suffix' => '<a href="#" class="simpletest-collapse">(' . $this->t('Expand') . ')</a>',
+    );
+    $image_extended = array(
+      '#theme' => 'image',
+      '#uri' => 'core/misc/menu-expanded.png',
+      '#width' => '7',
+      '#height' => '7',
+      '#alt' => $this->t('Collapse'),
+      '#title' => $this->t('Collapse'),
+      '#suffix' => '<a href="#" class="simpletest-collapse">(' . $this->t('Collapse') . ')</a>',
+    );
+    $js = array(
+      'images' => array(
+        drupal_render($image_collapsed),
+        drupal_render($image_extended),
+      ),
     );
 
     // Generate the list of tests arranged by group.
@@ -61,28 +101,103 @@ public function buildForm(array $form, array &$form_state) {
     $form_state['storage']['PHPUnit'] = $groups['PHPUnit'];
 
     foreach ($groups as $group => $tests) {
-      $form['tests']['table'][$group] = array(
-        '#collapsed' => TRUE,
+      $form['tests'][$group] = array(
+        '#attributes' => array('class' => array('simpletest-group')),
+      );
+
+      // Make the class name safe for output on the page by replacing all
+      // non-word/decimal characters with a dash (-).
+      $group_class = 'module-' . strtolower(trim(preg_replace("/[^\w\d]/", "-", $group)));
+
+      // Override tableselect column with custom selector for this group.
+      // This group-select-all checkbox is injected via JavaScript.
+      $form['tests'][$group]['select'] = array(
+        '#wrapper_attributes' => array(
+          'id' => $group_class,
+          'class' => array('simpletest-select-all'),
+        ),
+      );
+      $form['tests'][$group]['title'] = array(
+        // Expand/collapse image.
+        '#prefix' => '<div class="simpletest-image" id="simpletest-test-group-' . $group_class . '"></div>',
+        '#markup' => '<label for="' . $group_class . '-select-all" class="simpletest-group-label">' . $group . '</label>',
+        '#wrapper_attributes' => array(
+          'class' => array('simpletest-group-label'),
+        ),
+      );
+      $form['tests'][$group]['description'] = array(
+        '#markup' => '&nbsp;',
+        '#wrapper_attributes' => array(
+          'class' => array('simpletest-group-description'),
+        ),
+      );
+
+      // Add individual tests to group.
+      $current_js = array(
+        'testClass' => $group_class . '-test',
+        'testNames' => array(),
+        // imageDirection maps to the 'images' index in the $js array.
+        'imageDirection' => 0,
+        'clickActive' => FALSE,
       );
 
+      // Sort test classes within group alphabetically by name/label.
+      uasort($tests, function ($a, $b) {
+        return SortArray::sortByKeyString($a, $b, 'name');
+      });
+
+      // Cycle through each test within the current group.
       foreach ($tests as $class => $info) {
-        $form['tests']['table'][$group][$class] = array(
-          '#type' => 'checkbox',
+        $test_id = drupal_clean_id_identifier($class);
+        $test_checkbox_id = 'edit-tests-' . $test_id;
+        $current_js['testNames'][] = $test_checkbox_id;
+
+        $form['tests'][$class] = array(
+          '#attributes' => array('class' => array($group_class . '-test', 'js-hide')),
+        );
+        $form['tests'][$class]['title'] = array(
+          '#type' => 'label',
           '#title' => $info['name'],
-          '#description' => $info['description'],
+          '#wrapper_attributes' => array(
+            'class' => array('simpletest-test-label', 'table-filter-text-source'),
+          ),
+        );
+        $form['tests'][$class]['description'] = array(
+          '#prefix' => '<div class="description">',
+          '#markup' => String::format('@description (@class)', array(
+            '@description' => $info['description'],
+            '@class' => $class,
+          )),
+          '#suffix' => '</div>',
+          '#wrapper_attributes' => array(
+            'class' => array('simpletest-test-description', 'table-filter-text-source'),
+          ),
         );
       }
+
+      $js['simpletest-test-group-' . $group_class] = $current_js;
     }
 
+    // Add JavaScript array of settings.
+    $form['tests']['#attached']['js'][] = array(
+      'type' => 'setting',
+      'data' => array('simpleTest' => $js),
+    );
+
     // Action buttons.
-    $form['tests']['op'] = array(
+    $form['actions'] = array('#type' => 'actions');
+    $form['actions']['submit'] = array(
       '#type' => 'submit',
       '#value' => $this->t('Run tests'),
+      '#tableselect' => TRUE,
+      '#button_type' => 'primary',
     );
+
     $form['clean'] = array(
       '#type' => 'fieldset',
       '#title' => $this->t('Clean test environment'),
       '#description' => $this->t('Remove tables with the prefix "simpletest" and temporary directories that are left over from tests that crashed. This is intended for developers when creating tests.'),
+      '#weight' => 200,
     );
     $form['clean']['op'] = array(
       '#type' => 'submit',
@@ -97,21 +212,20 @@ public function buildForm(array $form, array &$form_state) {
    * {@inheritdoc}
    */
   public function submitForm(array &$form, array &$form_state) {
-    // Get list of tests.
-    $tests_list = array();
     simpletest_classloader_register();
 
     $phpunit_all = array_keys($form_state['storage']['PHPUnit']);
 
-    foreach ($form_state['values'] as $class_name => $value) {
+    $tests_list = array();
+    foreach ($form_state['values']['tests'] as $class_name => $value) {
       // Since class_exists() will likely trigger an autoload lookup,
       // we do the fast check first.
-      if ($value === 1 && class_exists($class_name)) {
+      if ($value === $class_name && class_exists($class_name)) {
         $test_type = in_array($class_name, $phpunit_all) ? 'UnitTest' : 'WebTest';
         $tests_list[$test_type][] = $class_name;
       }
     }
-    if (count($tests_list) > 0 ) {
+    if (!empty($tests_list)) {
       $test_id = simpletest_run_tests($tests_list, 'drupal');
       $form_state['redirect_route'] = array(
         'route_name' => 'simpletest.result_form',
@@ -120,9 +234,6 @@ public function submitForm(array &$form, array &$form_state) {
         ),
       );
     }
-    else {
-      drupal_set_message($this->t('No test(s) selected.'), 'error');
-    }
   }
 
 }
diff --git a/core/modules/simpletest/lib/Drupal/simpletest/Tests/BrokenSetUpTest.php b/core/modules/simpletest/lib/Drupal/simpletest/Tests/BrokenSetUpTest.php
index 42b786a..6b13160 100644
--- a/core/modules/simpletest/lib/Drupal/simpletest/Tests/BrokenSetUpTest.php
+++ b/core/modules/simpletest/lib/Drupal/simpletest/Tests/BrokenSetUpTest.php
@@ -77,7 +77,7 @@ function testMethod() {
     if (!drupal_valid_test_ua()) {
       // Verify that a broken setUp() method is caught.
       file_put_contents($this->originalFileDirectory . '/simpletest/trigger', 'setup');
-      $edit['Drupal\simpletest\Tests\BrokenSetUpTest'] = TRUE;
+      $edit['tests[Drupal\simpletest\Tests\BrokenSetUpTest]'] = TRUE;
       $this->drupalPostForm('admin/config/development/testing', $edit, t('Run tests'));
       $this->assertRaw('Broken setup');
       $this->assertNoRaw('The setUp() method has run.');
@@ -88,7 +88,7 @@ function testMethod() {
 
       // Verify that a broken tearDown() method is caught.
       file_put_contents($this->originalFileDirectory . '/simpletest/trigger', 'teardown');
-      $edit['Drupal\simpletest\Tests\BrokenSetUpTest'] = TRUE;
+      $edit['tests[Drupal\simpletest\Tests\BrokenSetUpTest]'] = TRUE;
       $this->drupalPostForm('admin/config/development/testing', $edit, t('Run tests'));
       $this->assertNoRaw('Broken setup');
       $this->assertRaw('The setUp() method has run.');
@@ -99,7 +99,7 @@ function testMethod() {
 
       // Verify that a broken test method is caught.
       file_put_contents($this->originalFileDirectory . '/simpletest/trigger', 'test');
-      $edit['Drupal\simpletest\Tests\BrokenSetUpTest'] = TRUE;
+      $edit['tests[Drupal\simpletest\Tests\BrokenSetUpTest]'] = TRUE;
       $this->drupalPostForm('admin/config/development/testing', $edit, t('Run tests'));
       $this->assertNoRaw('Broken setup');
       $this->assertRaw('The setUp() method has run.');
diff --git a/core/modules/simpletest/lib/Drupal/simpletest/Tests/InstallationProfileModuleTestsTest.php b/core/modules/simpletest/lib/Drupal/simpletest/Tests/InstallationProfileModuleTestsTest.php
index 911c824..994fb36 100644
--- a/core/modules/simpletest/lib/Drupal/simpletest/Tests/InstallationProfileModuleTestsTest.php
+++ b/core/modules/simpletest/lib/Drupal/simpletest/Tests/InstallationProfileModuleTestsTest.php
@@ -57,7 +57,7 @@ function testInstallationProfileTests() {
     $this->drupalGet('admin/config/development/testing');
     $this->assertText('Installation profile module tests helper');
     $edit = array(
-      'Drupal\drupal_system_listing_compatible_test\Tests\SystemListingCompatibleTest' => TRUE,
+      'tests[Drupal\drupal_system_listing_compatible_test\Tests\SystemListingCompatibleTest]' => TRUE,
     );
     $this->drupalPostForm(NULL, $edit, t('Run tests'));
     $this->assertText('SystemListingCompatibleTest test executed.');
diff --git a/core/modules/simpletest/lib/Drupal/simpletest/Tests/MissingCheckedRequirementsTest.php b/core/modules/simpletest/lib/Drupal/simpletest/Tests/MissingCheckedRequirementsTest.php
index 61d6401..8b15c29 100644
--- a/core/modules/simpletest/lib/Drupal/simpletest/Tests/MissingCheckedRequirementsTest.php
+++ b/core/modules/simpletest/lib/Drupal/simpletest/Tests/MissingCheckedRequirementsTest.php
@@ -55,7 +55,7 @@ protected function testCheckRequirements() {
     // that the child tests did not run.
     if (!drupal_valid_test_ua()) {
       // Run this test from web interface.
-      $edit['Drupal\simpletest\Tests\MissingCheckedRequirementsTest'] = TRUE;
+      $edit['tests[Drupal\simpletest\Tests\MissingCheckedRequirementsTest]'] = TRUE;
       $this->drupalPostForm('admin/config/development/testing', $edit, t('Run tests'));
       $this->assertRaw('Test is not allowed to run.', 'Test check for requirements came up.');
       $this->assertNoText('Test ran when it failed requirements check.', 'Test requirements stopped test from running.');
diff --git a/core/modules/simpletest/lib/Drupal/simpletest/Tests/SimpleTestTest.php b/core/modules/simpletest/lib/Drupal/simpletest/Tests/SimpleTestTest.php
index 2a19a5c1..fa985ed 100644
--- a/core/modules/simpletest/lib/Drupal/simpletest/Tests/SimpleTestTest.php
+++ b/core/modules/simpletest/lib/Drupal/simpletest/Tests/SimpleTestTest.php
@@ -160,7 +160,7 @@ function testWebTestRunner() {
         $this->drupalGet('admin/config/development/testing');
 
         $edit = array();
-        $edit['Drupal\simpletest\Tests\SimpleTestTest'] = TRUE;
+        $edit['tests[Drupal\simpletest\Tests\SimpleTestTest]'] = TRUE;
         $this->drupalPostForm(NULL, $edit, t('Run tests'));
 
         // Parse results and confirm that they are correct.
diff --git a/core/modules/simpletest/simpletest.module b/core/modules/simpletest/simpletest.module
index c6b53bf..a3d722a 100644
--- a/core/modules/simpletest/simpletest.module
+++ b/core/modules/simpletest/simpletest.module
@@ -79,10 +79,6 @@ function simpletest_permission() {
  */
 function simpletest_theme() {
   return array(
-    'simpletest_test_table' => array(
-      'render element' => 'table',
-      'file' => 'simpletest.theme.inc',
-    ),
     'simpletest_result_summary' => array(
       'render element' => 'form',
       'file' => 'simpletest.theme.inc',
diff --git a/core/modules/simpletest/simpletest.theme.inc b/core/modules/simpletest/simpletest.theme.inc
index 1743b74..9890c62 100644
--- a/core/modules/simpletest/simpletest.theme.inc
+++ b/core/modules/simpletest/simpletest.theme.inc
@@ -6,154 +6,6 @@
  */
 
 /**
- * Returns an HTML table for a test list generated by simpletest_test_form().
- *
- * @param $variables
- *   An associative array containing:
- *   - table: A render element representing the table.
- *
- * @ingroup themeable
- */
-function theme_simpletest_test_table($variables) {
-  $table = $variables['table'];
-
-  drupal_add_library('simpletest', 'drupal.simpletest');
-
-  // Create header for test selection table.
-  $header = array(
-    array('class' => array('select-all')),
-    array('data' => t('Test'), 'class' => array('simpletest_test')),
-    array('data' => t('Description'), 'class' => array('simpletest_description')),
-  );
-
-  // Define the images used to expand/collapse the test groups.
-  $image_collapsed = array(
-    '#theme' => 'image',
-    '#uri' => 'core/misc/menu-collapsed.png',
-    '#width' => '7',
-    '#height' => '7',
-    '#alt' => t('Expand'),
-    '#title' => t('Expand'),
-    '#suffix' => '<a href="#" class="simpletest-collapse">(' . t('Expand') . ')</a>',
-  );
-  $image_extended = array(
-    '#theme' => 'image',
-    '#uri' => 'core/misc/menu-expanded.png',
-    '#width' => '7',
-    '#height' => '7',
-    '#alt' => t('Collapse'),
-    '#title' => t('Collapse'),
-    '#suffix' => ' <a href="#" class="simpletest-collapse">(' . t('Collapse') . ')</a>',
-   );
-  $js = array(
-    'images' => array(
-      drupal_render($image_collapsed),
-      drupal_render($image_extended),
-    ),
-  );
-
-  // Cycle through each test group and create a row.
-  $rows = array();
-  foreach (element_children($table) as $key) {
-    $element = &$table[$key];
-    $row = array();
-
-    // Make the class name safe for output on the page by replacing all
-    // non-word/decimal characters with a dash (-).
-    $test_class = 'module-' . strtolower(trim(preg_replace("/[^\w\d]/", "-", $key)));
-
-    // Select the right "expand"/"collapse" image, depending on whether the
-    // category is expanded (at least one test selected) or not.
-    $collapsed = !empty($element['#collapsed']);
-    $image_index = $collapsed ? 0 : 1;
-
-    // Place-holder for checkboxes to select group of tests.
-    $row[] = array('id' => $test_class, 'class' => array('simpletest-select-all'));
-
-    // Expand/collapse image and group title.
-    $row[] = array(
-      'data' => '<div class="simpletest-image" id="simpletest-test-group-' . $test_class . '"></div>' .
-        '<label for="' . $test_class . '-select-all" class="simpletest-group-label">' . $key . '</label>',
-      'class' => array('simpletest-group-label'),
-    );
-
-    $row[] = array(
-      'data' => '&nbsp;',
-      'class' => array('simpletest-group-description'),
-    );
-
-    $rows[] = array('data' => $row, 'class' => array('simpletest-group'));
-
-    // Add individual tests to group.
-    $current_js = array(
-      'testClass' => $test_class . '-test',
-      'testNames' => array(),
-      'imageDirection' => $image_index,
-      'clickActive' => FALSE,
-    );
-
-    // Sorting $element by children's #title attribute instead of by class name.
-    uasort($element, 'element_sort_by_title');
-
-    // Cycle through each test within the current group.
-    foreach (element_children($element) as $test_name) {
-      $test = $element[$test_name];
-      $row = array();
-
-      $current_js['testNames'][] = $test['#id'];
-
-      // Store test title and description so that checkbox won't render them.
-      $title = $test['#title'];
-      $description = $test['#description'];
-
-      $test['#title_display'] = 'invisible';
-      unset($test['#description']);
-
-      // Test name is used to determine what tests to run.
-      $test['#name'] = $test_name;
-
-      $row[] = array(
-        'data' => drupal_render($test),
-        'class' => array('simpletest-test-select'),
-      );
-      $row[] = array(
-        'data' => '<label for="' . $test['#id'] . '">' . $title . '</label>',
-        'class' => array('simpletest-test-label', 'table-filter-text-source'),
-      );
-      $row[] = array(
-        'data' => '<div class="description">' . format_string('@description (@class)', array('@description' => $description, '@class' => $test_name)) . '</div>',
-        'class' => array('simpletest-test-description', 'table-filter-text-source'),
-      );
-
-      $rows[] = array('data' => $row, 'class' => array($test_class . '-test', ($collapsed ? 'js-hide' : '')));
-    }
-    $js['simpletest-test-group-' . $test_class] = $current_js;
-    unset($table[$key]);
-  }
-
-  // Add js array of settings.
-  $attached = array();
-  $attached['#attached']['js'][] = array(
-    'data' => array('simpleTest' => $js),
-    'type' => 'setting',
-  );
-  drupal_render($attached);
-
-  if (empty($rows)) {
-    return '<strong>' . t('No tests to display.') . '</strong>';
-  }
-  else {
-    $simpletest_form_table = array(
-      '#theme' => 'table',
-      '#header' => $header,
-      '#rows' => $rows,
-      '#attributes' => array('id' => 'simpletest-form-table'),
-    );
-    return drupal_render($simpletest_form_table);
-  }
-}
-
-/**
  * Returns HTML for the summary status of a simpletest result.
  *
  * @param $variables
diff --git a/core/modules/system/system.module b/core/modules/system/system.module
index cc647a2..9d237f2 100644
--- a/core/modules/system/system.module
+++ b/core/modules/system/system.module
@@ -517,6 +517,9 @@ function system_element_info() {
   );
 
   // Form structure.
+  $types['label'] = array(
+    '#theme' => 'form_element_label',
+  );
   $types['item'] = array(
     // Forms that show author fields to both anonymous and authenticated users
     // need to dynamically switch between #type 'textfield' and #type 'item' to
