diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc
index 95adc95..f1bb22e 100644
--- a/core/includes/bootstrap.inc
+++ b/core/includes/bootstrap.inc
@@ -2575,6 +2575,8 @@ function drupal_fast_404() {
  * Returns TRUE if a Drupal installation is currently being attempted.
  */
 function drupal_installation_attempted() {
+  return isset($GLOBALS['install_state']);
+  // @todo Entirely incompatible with non-interactive installer invoked from SimpleTest.
   return defined('MAINTENANCE_MODE') && MAINTENANCE_MODE == 'install';
 }
 
diff --git a/core/includes/form.inc b/core/includes/form.inc
index 395cca7..dfc1cb5 100644
--- a/core/includes/form.inc
+++ b/core/includes/form.inc
@@ -3178,6 +3178,10 @@ function form_process_checkbox($element, $form_state) {
  * Processes a checkboxes form element.
  */
 function form_process_checkboxes($element) {
+  // The #type checkboxes element itself does not need validation.
+  // @todo Fix handling of values for checkboxes in programmed form submissions.
+  unset($element['#needs_validation']);
+
   $value = is_array($element['#value']) ? $element['#value'] : array();
   $element['#tree'] = TRUE;
   if (count($element['#options']) > 0) {
diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc
index 32ce838..adb810f 100644
--- a/core/includes/install.core.inc
+++ b/core/includes/install.core.inc
@@ -240,11 +240,10 @@ function install_begin_request(&$install_state) {
   if (!$install_state['interactive']) {
     drupal_override_server_variables($install_state['server']);
   }
-
   // The user agent header is used to pass a database prefix in the request when
   // running tests. However, for security reasons, it is imperative that no
   // installation be permitted using such a prefix.
-  if (isset($_SERVER['HTTP_USER_AGENT']) && strpos($_SERVER['HTTP_USER_AGENT'], "simpletest") !== FALSE) {
+  elseif (isset($_SERVER['HTTP_USER_AGENT']) && strpos($_SERVER['HTTP_USER_AGENT'], "simpletest") !== FALSE) {
     header($_SERVER['SERVER_PROTOCOL'] . ' 403 Forbidden');
     exit;
   }
@@ -1331,7 +1330,7 @@ function install_select_language(&$install_state) {
       }
       // One language, but not an interactive installation. Assume the user
       // knows what he is doing.
-      $langcode = current($files);
+      $file = current($files);
       $install_state['parameters']['langcode'] = $file->langcode;
       return;
     }
@@ -1887,10 +1886,10 @@ function _install_configure_form($form, &$form_state, &$install_state) {
   $form['update_notifications']['update_status_module'] = array(
     '#type' => 'checkboxes',
     '#options' => array(
-      1 => st('Check for updates automatically'),
-      2 => st('Receive e-mail notifications'),
+      'enable' => st('Check for updates automatically'),
+      'notify' => st('Receive e-mail notifications'),
     ),
-    '#default_value' => array(1, 2),
+    '#default_value' => array('enable', 'notify'),
     '#description' => st('The system will notify you when updates and important security releases are available for installed components. Anonymous information about your site is sent to <a href="@drupal">Drupal.org</a>.', array('@drupal' => 'http://drupal.org')),
     '#weight' => 15,
   );
@@ -1929,12 +1928,12 @@ function install_configure_form_submit($form, &$form_state) {
   variable_set('site_default_country', $form_state['values']['site_default_country']);
 
   // Enable update.module if this option was selected.
-  if ($form_state['values']['update_status_module'][1]) {
+  if ($form_state['values']['update_status_module']['enable']) {
     module_enable(array('update'), FALSE);
 
     // Add the site maintenance account's email address to the list of
     // addresses to be notified when updates are available, if selected.
-    if ($form_state['values']['update_status_module'][2]) {
+    if ($form_state['values']['update_status_module']['notify']) {
       variable_set('update_notify_emails', array($form_state['values']['account']['mail']));
     }
   }
diff --git a/core/includes/install.inc b/core/includes/install.inc
index d203db4..71e5f45 100644
--- a/core/includes/install.inc
+++ b/core/includes/install.inc
@@ -94,10 +94,10 @@ function drupal_load_updates() {
  * @see install_profile_info()
  */
 function drupal_install_profile_distribution_name() {
+  global $install_state;
   // During installation, the profile information is stored in the global
   // installation state (it might not be saved anywhere yet).
-  if (drupal_installation_attempted()) {
-    global $install_state;
+  if (isset($install_state['profile_info']['distribution_name'])) {
     return $install_state['profile_info']['distribution_name'];
   }
   // At all other times, we load the profile via standard methods.
diff --git a/core/modules/node/node.module b/core/modules/node/node.module
index b0c7126..202dc76 100644
--- a/core/modules/node/node.module
+++ b/core/modules/node/node.module
@@ -3978,6 +3978,9 @@ function node_unpublish_by_keyword_action(Node $node, $context) {
  */
 function node_requirements($phase) {
   $requirements = array();
+  if ($phase !== 'runtime') {
+    return $requirements;
+  }
   // Ensure translations don't break at install time
   $t = get_t();
   // Only show rebuild button if there are either 0, or 2 or more, rows
diff --git a/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php
index 5725ed8..e54c116 100644
--- a/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php
+++ b/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php
@@ -593,6 +593,14 @@ abstract class TestBase {
       );
     }
     Database::addConnectionInfo('default', 'default', $connection_info['default']);
+
+    // Additionally override global $databases, since the installer does not use
+    // the Database connection info.
+    // @see install_verify_database_settings()
+    // @see install_database_errors()
+    // @todo Fix installer to use Database connection info.
+    global $databases;
+    $databases['default']['default'] = $connection_info['default'];
   }
 
   /**
@@ -623,6 +631,7 @@ abstract class TestBase {
     $this->originalFileDirectory = variable_get('file_public_path', conf_path() . '/files');
     $this->originalProfile = drupal_get_profile();
     $this->originalUser = $user;
+    $this->originalSession = isset($_SESSION) ? $_SESSION : NULL;
 
     // Save and clean the shutdown callbacks array because it is static cached
     // and will be changed by the test run. Otherwise it will contain callbacks
@@ -714,6 +723,7 @@ abstract class TestBase {
 
     // Restore original user session.
     $user = $this->originalUser;
+    $_SESSION = $this->originalSession;
     drupal_save_session(TRUE);
   }
 
diff --git a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php
index 0856611..b18fb07 100644
--- a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php
+++ b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php
@@ -602,13 +602,58 @@ abstract class WebTestBase extends TestBase {
     // the test's profile as a module. Without this, the installation profile of
     // the parent site (executing the test) is registered, and the test
     // profile's hook_install() and other hook implementations are never invoked.
-    $conf['install_profile'] = $this->profile;
+    // @todo Double-check this.
+//    $conf['install_profile'] = $this->profile;
 
-    // Perform the actual Drupal installation.
-    include_once DRUPAL_ROOT . '/core/includes/install.inc';
-    drupal_install_system();
+    // Set the 'simpletest_parent_profile' variable to add the parent profile's
+    // search path to the child site's search paths.
+    // @see drupal_system_listing()
+    $conf['simpletest_parent_profile'] = $this->originalProfile;
 
-    $this->preloadRegistry();
+    // Run the Drupal installer non-interactively.
+    // @see install.php, install.core.inc
+    require_once DRUPAL_ROOT . '/core/includes/install.core.inc';
+    $connection_info = Database::getConnectionInfo('default');
+    $this->root_user = (object) array(
+      'name' => 'admin',
+      'mail' => 'admin@example.com',
+      'pass_raw' => $this->randomName(),
+    );
+    $settings = array(
+      'interactive' => FALSE,
+      'parameters' => array(
+        'profile' => $this->profile,
+        'langcode' => 'en',
+      ),
+      'forms' => array(
+        'install_settings_form' => array(
+          'driver' => $connection_info['default']['driver'],
+          'username' => $connection_info['default']['username'],
+          'host' => $connection_info['default']['host'],
+          'port' => $connection_info['default']['port'],
+          'password' => $connection_info['default']['password'],
+          'database' => $connection_info['default']['database'],
+          'prefix' => $connection_info['default']['prefix'],
+        ),
+        'install_configure_form' => array(
+          'site_name' => 'Drupal',
+          'site_mail' => 'simpletest@example.com',
+          'account' => array(
+            'name' => $this->root_user->name,
+            'mail' => $this->root_user->mail,
+            'pass' => array(
+              'pass1' => $this->root_user->pass_raw,
+              'pass2' => $this->root_user->pass_raw,
+            ),
+          ),
+          'update_status_module' => array(
+            'enable' => FALSE,
+            'notify' => FALSE,
+          ),
+        ),
+      ),
+    );
+    install_drupal($settings);
 
     // Set path variables.
     variable_set('file_public_path', $this->public_files_directory);
@@ -618,16 +663,8 @@ abstract class WebTestBase extends TestBase {
     // Set the 'simpletest_parent_profile' variable to add the parent profile's
     // search path to the child site's search paths.
     // @see drupal_system_listing()
-    // @todo This may need to be primed like 'install_profile' above.
     variable_set('simpletest_parent_profile', $this->originalProfile);
 
-    // Include the testing profile.
-    variable_set('install_profile', $this->profile);
-    $profile_details = install_profile_info($this->profile, 'en');
-
-    // Install the modules specified by the testing profile.
-    module_enable($profile_details['dependencies'], FALSE);
-
     // Install modules needed for this test. This could have been passed in as
     // either a single array argument or a variable number of string arguments.
     // @todo Remove this compatibility layer in Drupal 8, and only accept
@@ -641,32 +678,15 @@ abstract class WebTestBase extends TestBase {
       $this->assertTrue($success, t('Enabled modules: %modules', array('%modules' => implode(', ', $modules))));
     }
 
-    // Run the profile tasks.
-    $install_profile_module_exists = db_query("SELECT 1 FROM {system} WHERE type = 'module' AND name = :name", array(
-      ':name' => $this->profile,
-    ))->fetchField();
-    if ($install_profile_module_exists) {
-      module_enable(array($this->profile), FALSE);
-    }
-
     // Reset/rebuild all data structures after enabling the modules.
     $this->resetAll();
 
-    // Run cron once in that environment, as install.php does at the end of
-    // the installation process.
-    drupal_cron_run();
-
     // Ensure that the session is not written to the new environment and replace
     // the global $user session with uid 1 from the new test site.
     drupal_save_session(FALSE);
     // Login as uid 1.
     $user = user_load(1);
 
-    // Restore necessary variables.
-    variable_set('install_task', 'done');
-    config('system.site')->set('mail', 'simpletest@example.com')->save();
-    variable_set('date_default_timezone', date_default_timezone_get());
-
     // Set up English language.
     unset($conf['language_default']);
     $language_interface = language_default();
