diff --git a/core/modules/simpletest/simpletest.module b/core/modules/simpletest/simpletest.module
index 1144e9d..462e9ec 100644
--- a/core/modules/simpletest/simpletest.module
+++ b/core/modules/simpletest/simpletest.module
@@ -612,21 +612,17 @@ function simpletest_clean_results_table($test_id = NULL) {
   if (\Drupal::config('simpletest.settings')->get('clear_results')) {
     $connection = TestBase::getDatabaseConnection();
     if ($test_id) {
-      $count = $connection->query('SELECT COUNT(test_id) FROM {simpletest_test_id} WHERE test_id = :test_id', array(':test_id' => $test_id))->fetchField();
-
       $connection->delete('simpletest')
         ->condition('test_id', $test_id)
         ->execute();
-      $connection->delete('simpletest_test_id')
+      $count = $connection->delete('simpletest_test_id', array('return' => Database::RETURN_AFFECTED))
         ->condition('test_id', $test_id)
         ->execute();
     }
     else {
-      $count = $connection->query('SELECT COUNT(test_id) FROM {simpletest_test_id}')->fetchField();
-
       // Clear test results.
       $connection->delete('simpletest')->execute();
-      $connection->delete('simpletest_test_id')->execute();
+      $count = $connection->delete('simpletest_test_id', array('return' => Database::RETURN_AFFECTED))->execute();
     }
 
     return $count;
diff --git a/core/modules/simpletest/src/Form/SimpletestResultsForm.php b/core/modules/simpletest/src/Form/SimpletestResultsForm.php
index 7e82690..fdd5ee3 100644
--- a/core/modules/simpletest/src/Form/SimpletestResultsForm.php
+++ b/core/modules/simpletest/src/Form/SimpletestResultsForm.php
@@ -61,28 +61,28 @@ protected function buildStatusImageMap() {
     // Initialize image mapping property.
     $image_pass = array(
       '#theme' => 'image',
-      '#uri' => 'core/misc/icons/73b355/check.png',
+      '#uri' => 'core/misc/icons/73b355/check.svg',
       '#width' => 18,
       '#height' => 18,
       '#alt' => $this->t('Pass'),
     );
     $image_fail = array(
       '#theme' => 'image',
-      '#uri' => 'core/misc/icons/ea2800/error.png',
+      '#uri' => 'core/misc/icons/ea2800/error.svg',
       '#width' => 18,
       '#height' => 18,
       '#alt' => $this->t('Fail'),
     );
     $image_exception = array(
       '#theme' => 'image',
-      '#uri' => 'core/misc/icons/e29700/warning.png',
+      '#uri' => 'core/misc/icons/e29700/warning.svg',
       '#width' => 18,
       '#height' => 18,
       '#alt' => $this->t('Exception'),
     );
     $image_debug = array(
       '#theme' => 'image',
-      '#uri' => 'core/misc/icons/e29700/warning.png',
+      '#uri' => 'core/misc/icons/e29700/warning.svg',
       '#width' => 18,
       '#height' => 18,
       '#alt' => $this->t('Debug'),
@@ -111,7 +111,14 @@ public function buildForm(array $form, FormStateInterface $form_state, $test_id
     // performed.
     $results = array();
 
-    if (is_numeric($test_id) && !$results = $this->getResults($test_id)) {
+    // Allow multiple test_ids so that run-test.sh can open results in a single
+    // browser window.
+    // @see simpletest_script_open_browser()
+    if (strpos($test_id, '+') !== FALSE) {
+      $test_id = explode('+', $test_id);
+    }
+
+    if ((!is_numeric($test_id) && !is_array($test_id)) || !$results = $this->getResults($test_id)) {
       drupal_set_message($this->t('No test results to display.'), 'error');
       return new RedirectResponse(url('admin/config/development/testing', array('absolute' => TRUE)));
     }
@@ -241,9 +248,7 @@ public function buildForm(array $form, FormStateInterface $form_state, $test_id
       '#href' => 'admin/config/development/testing',
     );
 
-    if (is_numeric($test_id)) {
-      simpletest_clean_results_table($test_id);
-    }
+    simpletest_clean_results_table($test_id);
 
     return $form;
   }
diff --git a/core/modules/simpletest/src/TestBase.php b/core/modules/simpletest/src/TestBase.php
index e57048f..f21a6c6 100644
--- a/core/modules/simpletest/src/TestBase.php
+++ b/core/modules/simpletest/src/TestBase.php
@@ -741,10 +741,10 @@ protected function verbose($message) {
       return;
     }
 
-    $message = '<hr />ID #' . $this->verboseId . ' (<a href="' . $this->verboseClassName . '-' . ($this->verboseId - 1) . '.html">Previous</a> | <a href="' . $this->verboseClassName . '-' . ($this->verboseId + 1) . '.html">Next</a>)<hr />' . $message;
-    $verbose_filename = $this->verboseDirectory . '/' . $this->verboseClassName . '-' . $this->verboseId . '.html';
-    if (file_put_contents($verbose_filename, $message, FILE_APPEND)) {
-      $url = $this->verboseDirectoryUrl . '/' . $this->verboseClassName . '-' . $this->verboseId . '.html';
+    $message = '<hr />ID #' . $this->verboseId . ' (<a href="' . $this->verboseClassName . '-' . ($this->verboseId - 1) . '-' . $this->testId . '.html">Previous</a> | <a href="' . $this->verboseClassName . '-' . ($this->verboseId + 1) . '-' . $this->testId . '.html">Next</a>)<hr />' . $message;
+    $verbose_filename =  $this->verboseClassName . '-' . $this->verboseId . '-' . $this->testId . '.html';
+    if (file_put_contents($this->verboseDirectory . '/' . $verbose_filename, $message)) {
+      $url = $this->verboseDirectoryUrl . '/' . $verbose_filename;
       // Not using l() to avoid invoking the theme system, so that unit tests
       // can use verbose() as well.
       $url = '<a href="' . $url . '" target="_blank">Verbose message</a>';
diff --git a/core/scripts/run-tests.sh b/core/scripts/run-tests.sh
index 70bdf4a..b5cff54 100755
--- a/core/scripts/run-tests.sh
+++ b/core/scripts/run-tests.sh
@@ -6,9 +6,13 @@
  */
 
 use Drupal\Component\Utility\Timer;
+use Drupal\Component\Uuid\Php;
 use Drupal\Core\Database\Database;
+use Drupal\Core\Form\FormState;
 use Drupal\Core\Site\Settings;
+use Drupal\Core\StreamWrapper\PublicStream;
 use Drupal\Core\Test\TestRunnerKernel;
+use Drupal\simpletest\Form\SimpletestResultsForm;
 use Symfony\Component\HttpFoundation\Request;
 
 $autoloader = require_once __DIR__ . '/../vendor/autoload.php';
@@ -86,7 +90,12 @@
 simpletest_script_reporter_timer_stop();
 
 // Display results before database is cleared.
-simpletest_script_reporter_display_results();
+if ($args['browser']) {
+  simpletest_script_open_browser();
+}
+else {
+  simpletest_script_reporter_display_results();
+}
 
 if ($args['xml']) {
   simpletest_script_reporter_write_xml_results();
@@ -184,6 +193,10 @@ function simpletest_script_help() {
               test database and configuration directories. Use in combination
               with --repeat for debugging random test failures.
 
+  --browser   Opens the results in the browser. This enforces --keep-results and
+              if you want to also view any pages rendered in the simpletest
+              browser you need to add --verbose to the command line.
+
   <test1>[,<test2>[,<test3> ...]]
 
               One or more tests to be run. By default, these are interpreted
@@ -242,6 +255,7 @@ function simpletest_script_parse_args() {
     'test_names' => array(),
     'repeat' => 1,
     'die-on-fail' => FALSE,
+    'browser' => FALSE,
     // Used internally.
     'test-id' => 0,
     'execute-test' => '',
@@ -287,6 +301,10 @@ function simpletest_script_parse_args() {
     exit;
   }
 
+  //
+  if ($args['browser']) {
+    $args['keep-results'] = TRUE;
+  }
   return array($args, $count);
 }
 
@@ -1059,3 +1077,43 @@ function simpletest_script_color_code($status) {
   }
   return 0; // Default formatting.
 }
+
+/**
+ * Display test results.
+ */
+function simpletest_script_open_browser() {
+  global $test_ids;
+
+  // Generate html results.
+  $connection = Database::getConnection('default', 'test-runner');
+  $form = new SimpletestResultsForm($connection);
+  $form_array = $form->buildForm(array(), new FormState(), implode('+', $test_ids));
+  unset($form_array['action']);
+  unset($form_array['#action']);
+  $html = drupal_render($form_array);
+  // Unfortunately calling this tries to write config!
+  //$html = drupal_get_css() . $html;
+  $html = '<head><link type="text/css" rel="stylesheet" href="'. file_create_url(drupal_get_path('module', 'simpletest') . '/css/simpletest.module.css') . '" media="all"></head><body>' .$html .'</body>';
+  $uuid = new Php();
+  $filename = PublicStream::basePath() . '/simpletest/verbose/results-'. $uuid->generate() .'.html';
+  file_put_contents($filename, $html);
+  // See if we can find an OS helper to open URLs in default browser.
+  if (shell_exec('which xdg-open')) {
+    $browser = 'xdg-open';
+  }
+  elseif (shell_exec('which open')) {
+    $browser = 'open';
+  }
+  elseif (substr(PHP_OS, 0, 3) == 'WIN') {
+    $browser = 'start';
+  }
+  else {
+    // Can't find a valid browser.
+    // @todo Output some help giving the user the filename of the html to open.
+    $browser = FALSE;
+  }
+
+  if ($browser) {
+    shell_exec($browser . ' ' . escapeshellarg($filename));
+  }
+}
