diff --git a/scripts/run-tests.sh b/scripts/run-tests.sh
index db7600b2073b2c6e34454e27f1665139d5ec6d44..22615c1a966a3d0c81dcff69443c35ef633452e8 100755
--- a/scripts/run-tests.sh
+++ b/scripts/run-tests.sh
@@ -1,28 +1,103 @@
 <?php
 // $Id$
-
 /**
  * @file
  * This script runs Drupal tests from command line.
- * You can provide groups or class names of the tests you wish to run.
- * For example: php scripts/run-functional-tests.sh Profile
- * If no arguments are provided, the help text will print.
  */
 
-$test_names = array();
-$host = 'localhost';
-$path = '';
-$script = basename(array_shift($_SERVER['argv']));
-// XXX: is there a way to get the interpreter path dynamically?
-$php = "/usr/bin/php";
+define('SIMPLETEST_SCRIPT_COLOR_PASS', 32); // Green.
+define('SIMPLETEST_SCRIPT_COLOR_FAIL', 31); // Red.
+define('SIMPLETEST_SCRIPT_COLOR_EXCEPTION', 33); // Brown.
+
+// Set defaults and get overrides.
+list($args, $count) = simpletest_script_parse_args();
+
+simpletest_script_init();
+
+if ($args['help'] || $count == 0) {
+  simpletest_script_help();
+  exit;
+}
+
+if ($args['execute-batch']) {
+  simpletest_script_execute_batch();
+}
+
+// Bootstrap to perform initial validation or other opperations.
+drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
+if (!module_exists('simpletest')) {
+  simpletest_script_print_error("The simpletest module must be enabled before this script can run.");
+  exit;
+}
+
+if ($args['clean']) {
+  // Clean up left-over times and directories.
+  simpletest_clean_environment();
+  echo "\nEnvironment cleaned.\n";
+
+  // Get the status messages and print them.
+  $messages = array_pop(drupal_get_messages('status'));
+  foreach($messages as $text) {
+    echo " - " . $text . "\n";
+  }
+  exit;
+}
+
+// Load SimpleTest files.
+$all_tests = simpletest_get_all_tests();
+$groups = simpletest_categorize_tests($all_tests);
+$test_list = array();
+
+if ($args['list']) {
+  // Display all availabe tests.
+  echo "\nAvailable test groups & classes\n";
+  echo   "-------------------------------\n\n";
+  foreach ($groups as $group => $tests) {
+    echo $group . "\n";
+    foreach ($tests as $class_name => $instance) {
+      $info = $instance->getInfo();
+      echo " - " . $info['name'] . ' (' . $class_name . ')' . "\n";
+    }
+  }
+  exit;
+}
+
+$test_list = simpletest_script_get_test_list();
+
+// If not in 'safe mode', increase the maximum execution time.
+if (!ini_get('safe_mode')) {
+  set_time_limit(0);
+}
+
+simpletest_script_reporter_init();
+
+// Setup database for test results.
+db_query('INSERT INTO {simpletest_test_id} VALUES (default)');
+$test_id = db_last_insert_id('simpletest_test_id', 'test_id');
+
+// Execute tests.
+simpletest_script_command($args['concurrency'], $test_id, implode(",", $test_list));
+
+// Display results before database is cleared.
+simpletest_script_reporter_display_results();
+
+// Cleanup our test results.
+db_query("DELETE FROM {simpletest} WHERE test_id = %d", $test_id);
+
+
+
+/**
+ * Print help text.
+ */
+function simpletest_script_help() {
+  global $args;
 
-if (in_array('--help', $_SERVER['argv']) || empty($_SERVER['argv'])) {
   echo <<<EOF
 
 Run Drupal tests from the shell.
 
-Usage:        {$script} [OPTIONS] <tests>
-Example:      {$script} Profile
+Usage:        {$args['script']} [OPTIONS] <tests>
+Example:      {$args['script']} Profile
 
 All arguments are long options.
 
@@ -46,6 +121,10 @@
 
   --class     Run tests identified by specific class names, instead of group names.
 
+  --color     Output the rusults with color highlighting.
+
+  --verbose   Output detailed assertion messages in addition to summary.
+
   <test1>[,<test2>[,<test3> ...]]
 
               One or more tests to be run.  By default, these are interpreted
@@ -57,124 +136,159 @@
               be separated by commas.  Ignored if --all is specified.
 
 To run this script you will normally invoke it from the root directory of your
-Drupal installation as
+Drupal installation as the webserver user, or root, with
 
-php  ./scripts/{$script}
+php  ./scripts/{$args['script']}
 \n
 EOF;
-  exit;
 }
 
-$list = FALSE;
-$clean = FALSE;
-$all = FALSE;
-$concurrency = 1;
-$class_names = FALSE;
-$test_names = array();
-$execute_batch = FALSE;
-$test_id = NULL;
-
-while ($param = array_shift($_SERVER['argv'])) {
-  switch ($param) {
-    case '--list':
-      $list = TRUE;
-      break;
-    case '--url':
-      $url = array_shift($_SERVER['argv']);
-      $parsed = parse_url($url);
-      $host = $parsed['host'];
-      $path = $parsed['path'];
-      break;
-    case '--all':
-      $all = TRUE;
-      break;
-    case '--class':
-      $class_names = TRUE;
-      break;
-    case '--clean':
-      $clean = TRUE;
-      break;
-    case '--concurrency':
-      $concurrency = array_shift($_SERVER['argv']);
-      break;
-    case '--test-id':
-      $test_id = array_shift($_SERVER['argv']);
-      break;
-    case '--execute-batch':
-      $execute_batch = TRUE;
-      break;
-    default:
-      $test_names += explode(',', $param);
-      break;
+/**
+ * Parse execution argument and ensure that all are valid.
+ *
+ * @return The list of arguments.
+ */
+function simpletest_script_parse_args() {
+  // Set default values.
+  $args = array(
+    'script' => '',
+    'help' => FALSE,
+    'list' => FALSE,
+    'clean' => FALSE,
+    'url' => '',
+    'concurrency' => 1,
+    'all' => FALSE,
+    'class' => FALSE,
+    'color' => FALSE,
+    'verbose' => FALSE,
+    'test_names' => array(),
+    // Used internally.
+    'test-id' => NULL,
+    'execute-batch' => FALSE
+  );
+
+  // Override with set values.
+  $args['script'] = basename(array_shift($_SERVER['argv']));
+
+  $count = 0;
+  while ($arg = array_shift($_SERVER['argv'])) {
+    if (preg_match('/--(\S+)/', $arg, $matches)) {
+      // Argument found.
+      if (array_key_exists($matches[1], $args)) {
+        // Argument found in list.
+        $previous_arg = $matches[1];
+        if (is_bool($args[$previous_arg])) {
+          $args[$matches[1]] = TRUE;
+        }
+        else {
+          $args[$matches[1]] = array_shift($_SERVER['argv']);
+        }
+        // Clear an extrenious values.
+        $args['test_names'] = array();
+        $count++;
+      }
+      else {
+        // Argument not found in list.
+        simpletest_script_print_error("Unknown argument '$arg'.");
+        exit;
+      }
+    }
+    else {
+      // Values found without an argument should be test names.
+      $args['test_names'] += explode(',', $arg);
+    }
   }
+  return array($args, $count);
 }
 
-$_SERVER['HTTP_HOST'] = $host;
-$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
-$_SERVER['SERVER_ADDR'] = '127.0.0.1';
-$_SERVER['SERVER_SOFTWARE'] = 'Apache';
-$_SERVER['SERVER_NAME'] = 'localhost';
-$_SERVER['REQUEST_URI'] = $path .'/';
-$_SERVER['SCRIPT_NAME'] = $path .'/index.php';
-$_SERVER['PHP_SELF'] = $path .'/index.php';
-$_SERVER['HTTP_USER_AGENT'] = 'Drupal command line';
-
-chdir(realpath(dirname(__FILE__) . '/..'));
-require_once './includes/bootstrap.inc';
-
-if ($execute_batch) {
-  if (is_null($test_id)) {
-    echo "ERROR: --execute-batch should not be called interactively.\n";
+/**
+ * Initialize script variables and perform general setup requirements.
+ */
+function simpletest_script_init() {
+  global $args, $php;
+
+  $host = 'localhost';
+  $path = '';
+  $php = "/usr/bin/php"; // TODO Get dynamically if possible.
+
+  // Get url from arguments.
+  if (!empty($args['url'])) {
+    $parsed_url = parse_url($args['url']);
+    $host = $parsed_url['host'];
+    $path = $parsed_url['path'];
+  }
+
+  $_SERVER['HTTP_HOST'] = $host;
+  $_SERVER['REMOTE_ADDR'] = '127.0.0.1';
+  $_SERVER['SERVER_ADDR'] = '127.0.0.1';
+  $_SERVER['SERVER_SOFTWARE'] = 'Apache';
+  $_SERVER['SERVER_NAME'] = 'localhost';
+  $_SERVER['REQUEST_URI'] = $path .'/';
+  $_SERVER['SCRIPT_NAME'] = $path .'/index.php';
+  $_SERVER['PHP_SELF'] = $path .'/index.php';
+  $_SERVER['HTTP_USER_AGENT'] = 'Drupal command line';
+
+  chdir(realpath(dirname(__FILE__) . '/..'));
+  require_once './includes/bootstrap.inc';
+}
+
+/**
+ * Execute a batch of tests.
+ */
+function simpletest_script_execute_batch() {
+  global $args;
+
+  if (is_null($args['test-id'])) {
+    simpletest_script_print_error("--execute-batch should not be called interactively.");
     exit;
   }
-  if ($concurrency == 1 || !function_exists('pcntl_fork')) {
-    // Fallback to mono-threaded execution
-    if (count($test_names) > 1) {
-      foreach($test_names as $test_class) {
-        // Note: we still need to execute each test in its separate Drupal environment
-        passthru($php . " ./scripts/run-tests.sh --url $url --concurrency 1 --test-id $test_id --execute-batch $test_class");
+  if ($args['concurrency'] == 1 || !function_exists('pcntl_fork')) {
+    // Fallback to mono-threaded execution.
+    if (count($args['test_names']) > 1) {
+      foreach ($args['test_names'] as $test_class) {
+        // Execute each test in its separate Drupal environment.
+        simpletest_script_command(1, $args['test-id'], $test_class);
       }
       exit;
     }
     else {
-      // Execute an individual test
-      $test_class = array_shift($test_names);
+      // Execute an individual test.
+      $test_class = array_shift($args['test_names']);
       drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
-      simpletest_run_one_test($test_id, $test_class);
+      simpletest_script_run_one_test($args['test-id'], $test_class);
       exit;
     }
   }
   else {
-    // Multi-threaded execution
+    // Multi-threaded execution.
     $children = array();
-    while (!empty($test_names) || !empty($children)) {
-      // Fork children
-      // Note: we can safely fork here, because Drupal is not bootstrapped yet
-      while(count($children) < $concurrency) {
-        if (empty($test_names)) break;
+    while (!empty($args['test_names']) || !empty($children)) {
+      // Fork children safely since Drupal is not bootstrapped yet.
+      while (count($children) < $concurrency) {
+        if (empty($args['test_names'])) break;
 
         $child = array();
-        $child['test_class'] = $test_class = array_shift($test_names);
+        $child['test_class'] = $test_class = array_shift($args['test_names']);
         $child['pid'] = pcntl_fork();
         if (!$child['pid']) {
-          // This is the child process, bootstrap and execute the test
+          // This is the child process, bootstrap and execute the test.
           drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
-          simpletest_run_one_test($test_id, $test_class);
+          simpletest_script_run_one_test($test_id, $test_class);
           exit;
         }
         else {
-          // Register our new child
+          // Register our new child.
           $children[] = $child;
         }
       }
 
-      // Wait for children every 200ms
+      // Wait for children every 200ms.
       usleep(200000);
 
-      // Check if some children finished
-      foreach($children as $cid => $child) {
+      // Check if some children finished.
+      foreach ($children as $cid => $child) {
         if (pcntl_waitpid($child['pid'], $status, WUNTRACED | WNOHANG)) {
-          // This particular child exited
+          // This particular child exited.
           unset($children[$cid]);
         }
       }
@@ -183,153 +297,208 @@
   }
 }
 
-drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
-
-if (!module_exists('simpletest')) {
-  echo("ERROR: The simpletest module must be enabled before this script can run.\n");
-  exit;
-}
+/**
+ * Run a single test (assume a Drupal bootstrapped environnement).
+ */
+function simpletest_script_run_one_test($test_id, $test_class) {
+  simpletest_get_all_tests();
+  $test = new $test_class($test_id);
+  $test->run();
+  $info = $test->getInfo();
 
-if ($clean) {
-  // Clean up left-over times and directories.
-  simpletest_clean_environment();
-  // Get the status messages and print them.
-  $messages = array_pop(drupal_get_messages('status'));
-  foreach($messages as $text) {
-    echo(" - " . $text . "\n");
-  }
-  exit;
+  $status = ((isset($test->_results['#fail']) && $test->_results['#fail'] > 0)
+           || (isset($test->_results['#exception']) && $test->_results['#exception'] > 0) ? 'fail' : 'pass');
+  simpletest_script_print($info['name'] . ' ' . _simpletest_format_summary_line($test->_results) . "\n", simpletest_script_color_code($status));
 }
 
-// Run tests as user #1.
-$GLOBALS['user'] = user_load(1);
-
-// Load simpletest files
-$all_tests = simpletest_get_all_tests();
-$groups = simpletest_categorize_tests($all_tests);
-$test_list = array();
+/**
+ * Execute a command to run batch of tests in separate process.
+ */
+function simpletest_script_command($concurrency, $test_id, $tests) {
+  global $args, $php;
 
-if ($list) {
-  // Display all availabe tests.
-  echo("\nAvailable test groups\n---------------------\n\n");
-  foreach ($groups as $group => $tests) {
-    echo($group . "\n");
-    foreach ($tests as $class_name => $instance) {
-      $info = $instance->getInfo();
-      echo " - " . $info['name'] . ' (' . $class_name . ')' . "\n";
-    }
+  $command = "$php ./scripts/{$args['script']} --url {$args['url']}";
+  if ($args['color']) {
+    $command .= ' --color';
   }
-  exit;
+  $command .= " --concurrency $concurrency --test-id $test_id --execute-batch $tests";
+  passthru($command);
 }
 
-if ($all) {
-  $test_list = array_keys($all_tests);
-}
-else {
-  if ($class_names) {
-    // Use only valid class names
-    foreach ($test_names as $class_name) {
-      if (isset($all_tests[$class_name])) {
-        $test_list[] = $class_name;
-      }
-    }
+/**
+ * Get list of tests based on arguments. If --all specfied then
+ * returns all available tests, otherwise reads list of tests.
+ *
+ * Will print error and exit if no valid tests were found.
+ *
+ * @return List of tests.
+ */
+function simpletest_script_get_test_list() {
+  global $args, $all_tests, $groups;
+
+  $test_list = array();
+  if ($args['all']) {
+    $test_list = array_keys($all_tests);
   }
   else {
-    // Resolve group names
-    foreach ($test_names as $group_name) {
-      if (isset($groups[$group_name])) {
-        foreach($groups[$group_name] as $class_name => $instance) {
+    if ($args['class_names']) {
+      // Check for valid class names.
+      foreach ($args['test_names'] as $class_name) {
+        if (isset($all_tests[$class_name])) {
           $test_list[] = $class_name;
         }
       }
     }
+    else {
+      // Check for valid group names and get all valid classes in group.
+      foreach ($args['test_names'] as $group_name) {
+        if (isset($groups[$group_name])) {
+          foreach($groups[$group_name] as $class_name => $instance) {
+            $test_list[] = $class_name;
+          }
+        }
+      }
+    }
   }
-}
 
-if (empty($test_list) && !$all) {
-  echo("ERROR: No valid tests were specified.\n");
-  exit;
+  if (empty($test_list)) {
+    simpletest_script_print_error('No valid tests were specified.');
+    exit;
+  }
+  return $test_list;
 }
 
-// If not in 'safe mode', increase the maximum execution time:
-if (!ini_get('safe_mode')) {
-  set_time_limit(0);
-}
+/**
+ * Initialize the reporter.
+ */
+function simpletest_script_reporter_init() {
+  global $args, $all_tests, $test_list;
 
-echo "\n";
-echo "Drupal test run\n";
-echo "---------------\n";
-echo "\n";
+  echo "\n";
+  echo "Drupal test run\n";
+  echo "---------------\n";
+  echo "\n";
 
-// Tell the user about what tests are to be run.
-if ($all) {
-  echo "All tests will run.\n\n";
-}
-else {
-  echo "Tests to be run:\n";
-  foreach ($test_list as $class_name) {
-    $info = $all_tests[$class_name]->getInfo();
-    echo " - " . $info['name'] . ' (' . $class_name . ')' . "\n";
+  // Tell the user about what tests are to be run.
+  if ($args['all']) {
+    echo "All tests will run.\n\n";
+  }
+  else {
+    echo "Tests to be run:\n";
+    foreach ($test_list as $class_name) {
+      $info = $all_tests[$class_name]->getInfo();
+      echo " - " . $info['name'] . ' (' . $class_name . ')' . "\n";
+    }
+    echo "\n";
   }
+
+  echo "Test run started: " . format_date(time(), 'long') . "\n";
+  echo "\n";
+
+  echo "Test summary:\n";
+  echo "-------------\n";
   echo "\n";
 }
 
-echo "Test run started: " . format_date(time(), 'long') . "\n";
-echo "\n";
+/**
+ * Display test results.
+ */
+function simpletest_script_reporter_display_results() {
+  global $args, $test_id, $results_map;
 
-db_query('INSERT INTO {simpletest_test_id} VALUES (default)');
-$test_id = db_last_insert_id('simpletest_test_id', 'test_id');
+  echo "\n";
+  echo "Test run ended: " . format_date(time(), 'long') . "\n";
+  echo "\n";
 
-echo "Test summary:\n";
-echo "-------------\n";
-echo "\n";
-
-// Now execute tests
-passthru($php . " ./scripts/run-tests.sh --url $url --test-id $test_id --concurrency $concurrency --execute-batch " . implode(",", $test_list));
-
-echo "\n";
-echo "Test run ended: " . format_date(time(), 'long') . "\n";
-echo "\n";
-
-// Report results
-echo "Detailed test results:\n";
-echo "----------------------\n";
-echo "\n";
-
-$results_map = array(
-  'pass' => 'Pass',
-  'fail' => 'Fail',
-  'exception' => 'Exception'
-);
-
-$results = db_query("SELECT * FROM {simpletest} WHERE test_id = %d ORDER BY test_class, message_id", $test_id);
-while($result = db_fetch_object($results)) {
-  if (isset($results_map[$result->status])) {
-    $data = array(
-      '[' . $results_map[$result->status] . ']',
-      $result->message,
-      $result->message_group,
-      basename($result->file),
-      $result->line,
-      $result->caller,
+  if ($args['verbose']) {
+    // Report results.
+    echo "Detailed test results:\n";
+    echo "----------------------\n";
+    echo "\n";
+
+    $results_map = array(
+      'pass' => 'Pass',
+      'fail' => 'Fail',
+      'exception' => 'Exception'
     );
-    echo implode("\t", $data) . "\n";
+
+    $results = db_query("SELECT * FROM {simpletest} WHERE test_id = %d ORDER BY test_class, message_id", $test_id);
+    $test_class = '';
+    while($result = db_fetch_object($results)) {
+      if (isset($results_map[$result->status])) {
+        if ($result->test_class != $test_class) {
+          // Display test class every time results are for new test class.
+          echo "\n\n---- $result->test_class ----\n\n\n";
+          $test_class = $result->test_class;
+        }
+
+        simpletest_script_format_result($result);
+      }
+    }
   }
 }
 
-// Cleanup our test results
-db_query("DELETE FROM {simpletest} WHERE test_id = %d", $test_id);
+/**
+ * Format the result so that it fits within the default 80 character
+ * terminal size.
+ *
+ * @param $result The result object to format.
+ */
+function simpletest_script_format_result($result) {
+  global $results_map, $color;
+
+  $summary = sprintf("%-10.10s %-10.10s %-30.30s %-5.5s %-20.20s\n",
+    $results_map[$result->status], $result->message_group, basename($result->file), $result->line, $result->caller);
+
+  simpletest_script_print($summary, simpletest_script_color_code($result->status));
 
-// Support function:
+  $lines = explode("\n", wordwrap(trim(strip_tags($result->message)), 76));
+  foreach ($lines as $line) {
+    echo "    $line\n";
+  }
+}
 
 /**
- * Run a single test (assume a Drupal bootstrapped environnement).
+ * Print error message prefixed with "  ERROR: " and displayed in fail color
+ * if color output is enabled.
+ *
+ * @param $message The message to print.
  */
-function simpletest_run_one_test($test_id, $test_class) {
-  simpletest_get_all_tests();
-  $test = new $test_class($test_id);
-  $test->run();
-  $info = $test->getInfo();
-  echo $info['name'] . ' ' . _simpletest_format_summary_line($test->_results) . "\n";
+function simpletest_script_print_error($message) {
+  simpletest_script_print("  ERROR: $message\n", SIMPLETEST_SCRIPT_COLOR_FAIL);
 }
 
+/**
+ * Print a message to the console, if color is enabled then the specified
+ * color code will be used.
+ *
+ * @param $message The message to print.
+ * @param $color_code The color code to use for coloring.
+ */
+function simpletest_script_print($message, $color_code) {
+  global $args;
+  if ($args['color']) {
+    echo "\033[" . $color_code . "m" . $message . "\033[0m";
+  }
+  else {
+    echo $message;
+  }
+}
+
+/**
+ * Get the color code associated with the specified status.
+ *
+ * @param $status The status string to get code for.
+ * @return Color code.
+ */
+function simpletest_script_color_code($status) {
+  switch ($status) {
+    case 'pass':
+      return SIMPLETEST_SCRIPT_COLOR_PASS;
+    case 'fail':
+      return SIMPLETEST_SCRIPT_COLOR_FAIL;
+    case 'exception':
+      return SIMPLETEST_SCRIPT_COLOR_EXCEPTION;
+  }
+  return 0; // Default formatting.
+}