diff --git a/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php
index 560afb1..0cafdd0 100644
--- a/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php
+++ b/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php
@@ -95,10 +95,17 @@
    */
   protected $setup = FALSE;
 
+  /**
+   * Indicates whether or not the database prefix has been set up for the test.
+   *
+   * This is checked in TestBase::tearDown() before deleting the tables of the
+   * test site. In case the database prefix was never set up properly this
+   * ensures that the tables of the parent site are not deleted.
+   *
+   * @var bool
+   */
   protected $setupDatabasePrefix = FALSE;
 
-  protected $setupEnvironment = FALSE;
-
   /**
    * TRUE if verbose debugging is enabled.
    *
@@ -780,31 +787,50 @@ public function run(array $methods = array()) {
       foreach ($class_methods as $method) {
         // If the current method starts with "test", run it - it's a test.
         if (strtolower(substr($method, 0, 4)) == 'test') {
-          // Insert a fail record. This will be deleted on completion to ensure
-          // that testing completed.
-          $method_info = new \ReflectionMethod($class, $method);
-          $caller = array(
-            'file' => $method_info->getFileName(),
-            'line' => $method_info->getStartLine(),
-            'function' => $class . '->' . $method . '()',
-          );
-          $completion_check_id = TestBase::insertAssert($this->testId, $class, FALSE, t('The test did not complete due to a fatal error.'), 'Completion check', $caller);
-          $this->setUp();
-          if ($this->setup) {
-            try {
-              $this->$method();
-              // Finish up.
-            }
-            catch (\Exception $e) {
-              $this->exceptionHandler($e);
+          try {
+            // Insert a fail record. This will be deleted on completion to ensure
+            // that testing completed.
+            $method_info = new \ReflectionMethod($class, $method);
+            $caller = array(
+              'file' => $method_info->getFileName(),
+              'line' => $method_info->getStartLine(),
+              'function' => $class . '->' . $method . '()',
+            );
+            $completion_check_id = TestBase::insertAssert($this->testId, $class, FALSE, t('The test did not complete due to a fatal error.'), 'Completion check', $caller);
+            $this->setUp();
+            if (!$this->setup) {
+              throw new TestSetUpException();
             }
+            $this->$method();
             $this->tearDown();
+            // Remove the completion check record.
+            TestBase::deleteAssert($completion_check_id);
+          }
+          catch (TestSetUpException $e) {
+            // Remove the completion check record.
+            TestBase::deleteAssert($completion_check_id);
+            $caller = array(
+              'file' => $e->getFile(),
+              'line' => $e->getLine(),
+            );
+            $message = $e->getMessage() ?: t("The test cannot be executed because it has not been set up properly.");
+            TestBase::insertAssert($this->testId, $class, FALSE, $message, 'Setup', $caller);
           }
-          else {
-            $this->fail(t("The test cannot be executed because it has not been set up properly."));
+          catch (TestTearDownException $e) {
+            // Remove the completion check record.
+            TestBase::deleteAssert($completion_check_id);
+            $caller = array(
+              'file' => $e->getFile(),
+              'line' => $e->getLine(),
+            );
+            $message = $e->getMessage() ?: t("The test could not be teared down properly.");
+            TestBase::insertAssert($this->testId, $class, FALSE, $message, 'Tear down', $caller);
+          }
+          catch (\Exception $e) {
+            // Remove the completion check record.
+            TestBase::deleteAssert($completion_check_id);
+            $this->exceptionHandler($e);
           }
-          // Remove the completion check record.
-          TestBase::deleteAssert($completion_check_id);
         }
       }
     }
@@ -856,12 +882,6 @@ protected function prepareDatabasePrefix() {
   protected function changeDatabasePrefix() {
     if (empty($this->databasePrefix)) {
       $this->prepareDatabasePrefix();
-      // If $this->prepareDatabasePrefix() failed to work, return without
-      // setting $this->setupDatabasePrefix to TRUE, so setUp() methods will
-      // know to bail out.
-      if (empty($this->databasePrefix)) {
-        return;
-      }
     }
 
     // Clone the current connection and replace the current prefix.
@@ -953,10 +973,18 @@ protected function prepareEnvironment() {
     $this->translation_files_directory = $this->public_files_directory . '/translations';
 
     // Create the directories
-    file_prepare_directory($this->public_files_directory, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS);
-    file_prepare_directory($this->private_files_directory, FILE_CREATE_DIRECTORY);
-    file_prepare_directory($this->temp_files_directory, FILE_CREATE_DIRECTORY);
-    file_prepare_directory($this->translation_files_directory, FILE_CREATE_DIRECTORY);
+    if (!file_prepare_directory($this->public_files_directory, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS)) {
+      throw new TestSetUpException('Could not prepare the public files directory of the test site.');
+    };
+    if (!file_prepare_directory($this->private_files_directory, FILE_CREATE_DIRECTORY)) {
+      throw new TestSetUpException('Could not prepare the private files directory of the test site.');
+    }
+    if (!file_prepare_directory($this->temp_files_directory, FILE_CREATE_DIRECTORY)) {
+      throw new TestSetUpException('Could not prepare the temporary files directory of the test site.');
+    }
+    if (!file_prepare_directory($this->translation_files_directory, FILE_CREATE_DIRECTORY)) {
+      throw new TestSetUpException('Could not prepare the translation files directory of the test site.');
+    }
     $this->generatedTestFiles = FALSE;
 
     // Create and set new configuration directories.
@@ -993,9 +1021,6 @@ protected function prepareEnvironment() {
     $test_info = &$GLOBALS['drupal_test_info'];
     $test_info['test_run_id'] = $this->databasePrefix;
     $test_info['in_child_site'] = FALSE;
-
-    // Indicate the environment was set up correctly.
-    $this->setupEnvironment = TRUE;
   }
 
   /**
@@ -1017,7 +1042,7 @@ protected function prepareConfigDirectories() {
       $GLOBALS['config_directories'][$type] = $path;
       // Ensure the directory can be created and is writeable.
       if (!install_ensure_config_directory($type)) {
-        return FALSE;
+        throw new TestSetUpException("Could not prepare the $type configuration directory of the test site.");
       }
       // Provide the already resolved path for tests.
       $this->configDirectories[$type] = $path;
diff --git a/core/modules/simpletest/lib/Drupal/simpletest/TestSetUpException.php b/core/modules/simpletest/lib/Drupal/simpletest/TestSetUpException.php
new file mode 100644
index 0000000..3b1dfb9
--- /dev/null
+++ b/core/modules/simpletest/lib/Drupal/simpletest/TestSetUpException.php
@@ -0,0 +1,14 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\simpletest\TestSetUpException.
+ */
+
+namespace Drupal\simpletest;
+
+/**
+ * An exception class for exceptions thrown during the set up of tests.
+ */
+class TestSetUpException extends \RuntimeException {
+}
diff --git a/core/modules/simpletest/lib/Drupal/simpletest/TestTearDownException.php b/core/modules/simpletest/lib/Drupal/simpletest/TestTearDownException.php
new file mode 100644
index 0000000..6a6c187
--- /dev/null
+++ b/core/modules/simpletest/lib/Drupal/simpletest/TestTearDownException.php
@@ -0,0 +1,14 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\simpletest\TestTearDownException.
+ */
+
+namespace Drupal\simpletest;
+
+/**
+ * An exception class for exceptions thrown during the set up of tests.
+ */
+class TestTearDownException extends \RuntimeException {
+}
diff --git a/core/modules/simpletest/lib/Drupal/simpletest/UnitTestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/UnitTestBase.php
index 5510aa4..b55f3db 100644
--- a/core/modules/simpletest/lib/Drupal/simpletest/UnitTestBase.php
+++ b/core/modules/simpletest/lib/Drupal/simpletest/UnitTestBase.php
@@ -48,9 +48,6 @@ protected function setUp() {
 
     // Prepare the environment for running tests.
     $this->prepareEnvironment();
-    if (!$this->setupEnvironment) {
-      return FALSE;
-    }
 
     // Reset all statics and variables to perform tests in a clean environment.
     $conf = array();
@@ -64,7 +61,7 @@ protected function setUp() {
     // write back to persistent caches when they are destructed.
     $this->changeDatabasePrefix();
     if (!$this->setupDatabasePrefix) {
-      return FALSE;
+      throw new TestSetUpException('The database prefix could not be changed for the test site.');
     }
 
     $this->setup = TRUE;
diff --git a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php
index 265012e..730b7ac 100644
--- a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php
+++ b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php
@@ -731,9 +731,6 @@ protected function setUp() {
 
     // Prepare the environment for running tests.
     $this->prepareEnvironment();
-    if (!$this->setupEnvironment) {
-      return FALSE;
-    }
 
     // Reset all statics and variables to perform tests in a clean environment.
     $conf = array();
@@ -745,7 +742,7 @@ protected function setUp() {
     // write back to persistent caches when they are destructed.
     $this->changeDatabasePrefix();
     if (!$this->setupDatabasePrefix) {
-      return FALSE;
+      throw new TestSetUpException('The database prefix could not be changed for the test site.');
     }
 
     // Set the 'simpletest_parent_profile' variable to add the parent profile's
diff --git a/core/modules/system/lib/Drupal/system/Tests/Installer/InstallerTranslationTest.php b/core/modules/system/lib/Drupal/system/Tests/Installer/InstallerTranslationTest.php
index 69b3352..f2f879e 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Installer/InstallerTranslationTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Installer/InstallerTranslationTest.php
@@ -8,6 +8,7 @@
 namespace Drupal\system\Tests\Installer;
 
 use Drupal\Component\Utility\NestedArray;
+use Drupal\simpletest\TestSetUpException;
 use Drupal\system\Tests\InstallerTest;
 
 /**
@@ -43,9 +44,6 @@ protected function setUp() {
 
     // Prepare the environment for running tests.
     $this->prepareEnvironment();
-    if (!$this->setupEnvironment) {
-      return FALSE;
-    }
 
     // Reset all statics and variables to perform tests in a clean environment.
     $conf = array();
@@ -57,8 +55,9 @@ protected function setUp() {
     // write back to persistent caches when they are destructed.
     $this->changeDatabasePrefix();
     if (!$this->setupDatabasePrefix) {
-      return FALSE;
+      throw new TestSetUpException('The database prefix could not be changed for the test site.');
     }
+
     $variable_groups = array(
       'system.file' => array(
         'path.private' =>  $this->private_files_directory,
diff --git a/core/modules/system/lib/Drupal/system/Tests/InstallerTest.php b/core/modules/system/lib/Drupal/system/Tests/InstallerTest.php
index 5bbaab8..f068125 100644
--- a/core/modules/system/lib/Drupal/system/Tests/InstallerTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/InstallerTest.php
@@ -8,6 +8,7 @@
 namespace Drupal\system\Tests;
 
 use Drupal\Component\Utility\NestedArray;
+use Drupal\simpletest\TestSetUpException;
 use Drupal\simpletest\WebTestBase;
 
 /**
@@ -38,9 +39,6 @@ protected function setUp() {
 
     // Prepare the environment for running tests.
     $this->prepareEnvironment();
-    if (!$this->setupEnvironment) {
-      return FALSE;
-    }
 
     // Reset all statics and variables to perform tests in a clean environment.
     $conf = array();
@@ -52,7 +50,7 @@ protected function setUp() {
     // write back to persistent caches when they are destructed.
     $this->changeDatabasePrefix();
     if (!$this->setupDatabasePrefix) {
-      return FALSE;
+      throw new TestSetUpException('The database prefix could not be changed for the test site.');
     }
     $variable_groups = array(
       'system.file' => array(
