diff --git a/code_coverage.install b/code_coverage.install
index b92acc6..8c3f558 100644
--- a/code_coverage.install
+++ b/code_coverage.install
@@ -31,22 +31,21 @@ function code_coverage_uninstall() {
  * Implements hook_requirements().
  */
 function code_coverage_requirements($phase) {
-  global $code_coverage_installed;
   $requirements = array();
   $t = get_t();
 
   $xdebug = function_exists('xdebug_start_code_coverage');
-  $requirements['code_coverage_xdebug'] = array(
-    'title' => $t('Xdebug'),
-    'value' => $xdebug ? $t('Installed') : $t('Missing'),
+  $requirements['php_xdebug'] = array(
+    'title' => $t('PHP Xdebug extension'),
+    'value' => $xdebug ? $t('Enabled') : $t('Missing'),
     'severity' => $xdebug ? REQUIREMENT_OK : REQUIREMENT_ERROR,
   );
 
-  $installed = !empty($code_coverage_installed) && $code_coverage_installed;
-  $requirements['code_coverage_xdebug'] = array(
-    'title' => $t('Xdebug patch'),
+  $installed = !empty($GLOBALS['code_coverage_installed']);
+  $requirements['code_coverage_xdebug_patch'] = array(
+    'title' => $t('Xdebug code coverage patch'),
     'value' => $installed ? $t('Installed') : $t('Missing'),
-    'severity' => $installed ? REQUIREMENT_OK : REQUIREMENT_ERROR,
+    'severity' => $installed ? REQUIREMENT_OK : REQUIREMENT_WARNING,
   );
 
   return $requirements;
diff --git a/code_coverage.module b/code_coverage.module
index 6eb1838..23ac475 100644
--- a/code_coverage.module
+++ b/code_coverage.module
@@ -25,15 +25,12 @@ define('CODE_COVERAGE_LINE_EXECUTED', 2);
  * Implementation of hook_menu().
  */
 function code_coverage_menu() {
-  $items = array();
-
   $items['coverage/%'] = array(
     'title' => 'Code coverage',
     'page callback' => 'code_coverage_report_view',
     'page arguments' => array(1),
     'access arguments' => array('view code_coverage reports'),
     'file' => 'code_coverage.report.inc',
-    'type' => MENU_CALLBACK,
   );
   $items['coverage/%/%'] = array(
     'title' => 'Code coverage',
@@ -41,7 +38,6 @@ function code_coverage_menu() {
     'page arguments' => array(1, 2),
     'access arguments' => array('view code_coverage reports'),
     'file' => 'code_coverage.report.inc',
-    'type' => MENU_CALLBACK,
   );
   $items['admin/config/development/code_coverage'] = array(
     'title' => 'Code coverage',
@@ -135,3 +131,11 @@ function code_coverage_result_clear() {
   // Display message containing total number of records cleared.
   drupal_set_message(t('Cleared @count record(s).', array('@count' => number_format($total))));
 }
+
+function code_coverage_form_simpletest_result_form_alter(&$form, &$form_state) {
+  // @todo: Find better way to get test_id.
+  $test_id = arg(5);
+  module_load_include('process.inc', 'code_coverage');
+  code_coverage_process($test_id);
+  drupal_set_message(t('View the !coverage_report_link for the test run.', array('!coverage_report_link' => l(t('code coverage report'), 'coverage/' . $test_id))));
+}
diff --git a/code_coverage.process.inc b/code_coverage.process.inc
index a23c42b..71f9a62 100644
--- a/code_coverage.process.inc
+++ b/code_coverage.process.inc
@@ -9,10 +9,13 @@
 
 /**
  * Process log table and store summed information in line table.
+ *
+ * @param $db_options
+ *   Database connection options, as prepared by code_coverage_record().
  */
-function code_coverage_process($coverage_set) {
+function code_coverage_process($coverage_set, array $db_options = array()) {
   // Group and sum all logged data.
-  $query = db_select('code_coverage_log', 'l')
+  $query = db_select('code_coverage_log', 'l', $db_options)
     ->fields('l')
     ->condition('f.coverage_set', $coverage_set)
     ->groupBy('l.file_id')
@@ -24,17 +27,24 @@ function code_coverage_process($coverage_set) {
   $file_ids = array();
   $executed = array();
   foreach ($lines as $line) {
-    $line->type = CODE_COVERAGE_LINE_EXECUTED;
-    drupal_write_record('code_coverage_line', $line);
+    db_merge('code_coverage_line', $db_options)
+      ->key(array(
+        'file_id' => $line->file_id,
+        'line' => $line->line,
+      ))
+      ->fields(array(
+        'type' => CODE_COVERAGE_LINE_EXECUTED,
+      ))
+      ->execute();
 
     // Keep track of all the files and executed lines.
     $executed[$line->file_id][] = $line->line;
   }
 
   // Empty log table.
-  db_delete('code_coverage_log')->execute();
+  db_truncate('code_coverage_log', $db_options)->execute();
 
-  $paths = db_select('code_coverage_file', 'f')
+  $paths = db_select('code_coverage_file', 'f', $db_options)
     ->fields('f', array('file_id', 'path'))
     ->condition('coverage_set', $coverage_set)
     ->execute()
@@ -48,17 +58,18 @@ function code_coverage_process($coverage_set) {
     foreach ($lines as $line) {
       // If the line is not marked as executed then insert a record.
       if (!in_array($line, $executed[$file_id])) {
-        $line = array(
-          'file_id' => $file_id,
-          'line' => $line,
-          'type' => CODE_COVERAGE_LINE_EXECUTABLE,
-        );
-        drupal_write_record('code_coverage_line', $line);
+        db_insert('code_coverage_line', $db_options)
+          ->fields(array(
+            'file_id' => $file_id,
+            'line' => $line,
+            'type' => CODE_COVERAGE_LINE_EXECUTABLE,
+          ))
+          ->execute();
       }
     }
 
     // Calculate total number of executed and executable lines.
-    db_update('code_coverage_file')
+    db_update('code_coverage_file', $db_options)
       ->fields(array(
         'executed' => count($executed[$file_id]),
         'executable' => count($lines),
diff --git a/code_coverage.xdebug.inc b/code_coverage.xdebug.inc
index e8f63bd..397c93a 100644
--- a/code_coverage.xdebug.inc
+++ b/code_coverage.xdebug.inc
@@ -7,32 +7,25 @@
  * @author Jimmy Berry ("boombatower", http://drupal.org/user/214218)
  */
 
+/**
+ * Global flag indicating that this file was loaded from bootstrap.inc.
+ */
+$code_coverage_installed = TRUE;
+
 // When running tests track code coverage.
-if (!empty($_GET['code_coverage']) || strpos($_SERVER['HTTP_USER_AGENT'], 'simpletest') !== FALSE) {
+if (!empty($_GET['code_coverage']) || strstr($_SERVER['HTTP_USER_AGENT'], 'simpletest')) {
   if (!empty($_GET['code_coverage'])) {
     // Generage coverage set ID and provide link to results.
-    $coverage_set = mt_rand(100000, 1000000000);
-    drupal_set_message('View the <a href="coverage/' . $coverage_set . '">code coverage report</a> for the page run.');
+    $coverage_set = mt_rand(1000000, 1000000000);
   }
   else {
-    global $db_prefix;
-    $db_prefix_testing = $db_prefix;
-    $db_prefix = preg_replace('/s\d+$/m', '', $db_prefix);
-
-    // Use the current test_id as the coverage set ID.
-    $coverage_set = db_select('simpletest_test_id', 's')
-      ->fields('s', 'test_id')
-      ->orderBy('test_id', 'DESC')
-      ->range(0, 1)
-      ->execute()
-      ->fetchField();
-
-    $db_prefix = $db_prefix_testing;
+    // Take over the random database prefix as coverage set.
+    $coverage_set = $_SERVER['HTTP_USER_AGENT'];
   }
 
   // Start Xdebug code coverage and register shutdown function to collect the
   // results and place them in the log table.
-  xdebug_start_code_coverage();
+  xdebug_start_code_coverage(XDEBUG_CC_DEAD_CODE | XDEBUG_CC_UNUSED);
   drupal_register_shutdown_function('code_coverage_record', $coverage_set, !empty($_GET['code_coverage']));
 }
 
@@ -42,62 +35,91 @@ if (!empty($_GET['code_coverage']) || strpos($_SERVER['HTTP_USER_AGENT'], 'simpl
  * @param $coverage_set
  *   Coverage set ID.
  * @param $process
- *   If TRUE then process the log immediately, otherwise no not process.
+ *   If TRUE then process the log immediately.
  */
 function code_coverage_record($coverage_set, $process) {
-  global $db_prefix;
-  $db_prefix_testing = $db_prefix;
-  $db_prefix = preg_replace('/s\d+$/m', '', $db_prefix);
-  $info = drupal_parse_info_file(DRUPAL_ROOT . '/' . drupal_get_path('module', 'code_coverage') . '/code_coverage.info');
-
-  // Cycle through the code coverage for each file.
-  $coverage = xdebug_get_code_coverage();
-  foreach ($coverage as $file => $lines) {
-    // Use the relative file path and ensure that the file is not part of the
-    // code_coverage module.
-    $relative = str_replace(DRUPAL_ROOT . '/', '', $file); // TODO Deal with symbolic links.
-    $base = basename($relative);
-    if (!in_array($base, $info['files']) && code_coverage_record_check($relative)) {
-      // Determine the file_id if it has already been created.
-      $file_id = db_select('code_coverage_file', 'f')
-        ->fields('f', array('file_id'))
-        ->condition('coverage_set', $coverage_set)
-        ->condition('path', $relative)
-        ->execute()
-        ->fetchField();
-
-      // Create a file record if not already done.
-      if (!$file_id) {
-        $file = array(
-          'coverage_set' => $coverage_set,
-          'path' => $relative,
-        );
-        drupal_write_record('code_coverage_file', $file);
-        $file_id = $file['file_id'];
+  try {
+    $db_options = array();
+
+    // Check whether coverage set maps to a simpletest database prefix, and if
+    // it does, replace it with the test_id.
+    if (preg_match('@^(simpletest\d+)@', $coverage_set, $matches)) {
+      $connection_info = Database::getConnectionInfo('default');
+      unset($connection_info['default']['prefix']);
+      Database::addConnectionInfo('default', 'code_coverage_original', $connection_info['default']);
+      $db_options['target'] = 'code_coverage_original';
+
+      $coverage_set = $matches[1];
+
+      $test_id = db_query('SELECT test_id FROM {simpletest_test_id} WHERE last_prefix = :prefix', array(
+        ':prefix' => $coverage_set,
+      ), $db_options)->fetchField();
+      if ($test_id) {
+        $coverage_set = $test_id;
+      }
+      // If there is no matching test ID, we cannot record.
+      else {
+        return;
       }
+    }
+
+    // Cycle through the code coverage for each file.
+    $coverage = xdebug_get_code_coverage();
+    $code_coverage_dir = dirname(__FILE__);
+    foreach ($coverage as $file => $lines) {
+      // Record the relative file path only, and normalize file path on Windows.
+      // @todo Deal with symbolic links.
+      $relative = strtr($file, array(
+        DRUPAL_ROOT . DIRECTORY_SEPARATOR => '',
+        DIRECTORY_SEPARATOR => '/',
+      ));
+
+      // Ensure the file is not part of the Code Coverage module.
+      if (dirname($file) != $code_coverage_dir && code_coverage_record_check($relative, $db_options)) {
+        // Determine the file_id if it has already been created.
+        $file_id = db_query('SELECT file_id FROM {code_coverage_file} WHERE coverage_set = :set AND path = :path', array(
+          ':set' => $coverage_set,
+          ':path' => $relative,
+        ), $db_options)->fetchField();
+
+        // Create a file record if not already done.
+        if (!$file_id) {
+          $file_id = db_insert('code_coverage_file', $db_options)
+            ->fields(array(
+              'coverage_set' => $coverage_set,
+              'path' => $relative,
+            ))
+            ->execute();
+        }
 
-      // Insert all line information into log table.
-      $insert = db_insert('code_coverage_log')->fields(array('file_id', 'line'));
-      foreach ($lines as $line => $count) {
-        // Ignore line 0.
-        if ($line) {
-          $insert->values(array(
-            'file_id' => $file_id,
-            'line' => $line,
-          ));
+        // Insert all line information into log table.
+        $insert = db_insert('code_coverage_log', $db_options)->fields(array('file_id', 'line'));
+        foreach ($lines as $line => $count) {
+          // Ignore line 0.
+          if ($line) {
+            $insert->values(array(
+              'file_id' => $file_id,
+              'line' => $line,
+            ));
+          }
         }
+        $insert->execute();
       }
-      $insert->execute();
     }
-  }
 
-  // Process log immediately.
-  if ($process) {
-    module_load_include('process.inc', 'code_coverage');
-    code_coverage_process($coverage_set);
+    // Process log immediately.
+    if ($process) {
+      module_load_include('process.inc', 'code_coverage');
+      code_coverage_process($coverage_set, $db_options);
+      echo 'View the <a href="coverage/' . $coverage_set . '">code coverage report</a> for the page run.';
+    }
+  }
+  catch (Exception $e) {
+    if (error_displayable()) {
+      print '<h1>Uncaught exception thrown in shutdown function.</h1>';
+      print '<p>' . _drupal_render_exception_safe($e) . '</p><hr />';
+    }
   }
-
-  $db_prefix = $db_prefix_testing;
 }
 
 /**
@@ -105,16 +127,21 @@ function code_coverage_record($coverage_set, $process) {
  *
  * @param $path
  *   Relative file path.
+ * @param $db_options
+ *   Database connection options, as prepared by code_coverage_record().
+ *
  * @return
  *   TRUE if path passes, otherwise FALSE.
  */
-function code_coverage_record_check($path) {
+function code_coverage_record_check($path, array $db_options = array()) {
   static $variables;
 
   // Manually load variables from database to ensure the variables are loaded
   // from the current prefix and not cached.
   if (!isset($variables)) {
-    $variables = db_query('SELECT name, value FROM {variable}')->fetchAllKeyed();
+    $variables = db_query('SELECT name, value FROM {variable} WHERE name LIKE :name', array(
+      ':name' => 'code_coverage_filter%',
+    ), $db_options)->fetchAllKeyed();
     $variables = array(
       'code_coverage_modules' => unserialize($variables['code_coverage_filter_modules']),
       'code_coverage_files' => unserialize($variables['code_coverage_filter_files']),
