Fix simpletest reporting.

From: Damien Tournoud <damien@tournoud.net>


---

 includes/common.inc                         |    8 ++-
 modules/simpletest/drupal_web_test_case.php |    8 +--
 modules/simpletest/tests/common.test        |   78 ++++++++++++++++++++++++++-
 modules/simpletest/tests/system_test.module |   17 +++++-
 4 files changed, 98 insertions(+), 13 deletions(-)


diff --git includes/common.inc includes/common.inc
index fc8dd18..b9efee2 100644
--- includes/common.inc
+++ includes/common.inc
@@ -731,12 +731,16 @@ function _drupal_log_error($error, $fatal = FALSE) {
 
   // When running inside the testing framework, we relay the errors
   // to the tested site by the way of HTTP headers.
-  if (preg_match("/^simpletest\d+/", $_SERVER['HTTP_USER_AGENT']) && !headers_sent() && !defined('SIMPLETEST_DONT_COLLECT_ERRORS')) {
+  if (preg_match("/^simpletest\d+/", $_SERVER['HTTP_USER_AGENT']) && !headers_sent() && (!defined('SIMPLETEST_COLLECT_ERRORS') || SIMPLETEST_COLLECT_ERRORS)) {
     static $number = 0;
     $assertion = array(
       $error['%message'],
       $error['%type'],
-      $error['%function'],
+      array(
+        'function' => $error['%function'],
+        'file' => $error['%file'],
+        'line' => $error['%line'],
+      ),
     );
     header('X-Drupal-Assertion-' . $number . ': ' . rawurlencode(serialize($assertion)));
     $number++;
diff --git modules/simpletest/drupal_web_test_case.php modules/simpletest/drupal_web_test_case.php
index e818328..e90410f 100644
--- modules/simpletest/drupal_web_test_case.php
+++ modules/simpletest/drupal_web_test_case.php
@@ -128,15 +128,15 @@ class DrupalWebTestCase {
    * @param $message
    *   The message string.
    * @param $group
-   *   WHich group this assert belongs to.
+   *   Which group this assert belongs to.
    * @param $caller
-   *   By default, the assert comes from a function which names start with
+   *   By default, the assert comes from a function whose name start with
    *   'test'. Instead, you can specify where this assert originates from
    *   by passing in an associative array as $caller. Key 'file' is
    *   the name of the source file, 'line' is the line number and 'function'
    *   is the caller function itself.
    */
-  private function assert($status, $message = '', $group = 'Other', $caller = NULL) {
+  private function assert($status, $message = '', $group = 'Other', Array $caller = NULL) {
     global $db_prefix;
 
     // Convert boolean status to string status.
@@ -374,7 +374,7 @@ class DrupalWebTestCase {
    * @return
    *   FALSE.
    */
-  protected function error($message = '', $group = 'Other', $caller = NULL) {
+  protected function error($message = '', $group = 'Other', Array $caller = NULL) {
     return $this->assert('exception', $message, $group, $caller);
   }
 
diff --git modules/simpletest/tests/common.test modules/simpletest/tests/common.test
index 016049d..3dedf63 100644
--- modules/simpletest/tests/common.test
+++ modules/simpletest/tests/common.test
@@ -287,7 +287,7 @@ class DrupalSetContentTestCase extends DrupalWebTestCase {
   function getInfo() {
     return array(
       'name' => t('Drupal set/get content'),
-      'description' => t("Performs tests on setting and retrieiving content from theme regions."),
+      'description' => t('Performs tests on setting and retrieiving content from theme regions.'),
       'group' => t('System')
     );
   }
@@ -338,7 +338,7 @@ class JavaScriptTestCase extends DrupalWebTestCase {
   function getInfo() {
     return array(
       'name' => t('JavaScript'),
-      'description' => t("Tests the JavaScript system."),
+      'description' => t('Tests the JavaScript system.'),
       'group' => t('System')
     );
   }
@@ -479,7 +479,7 @@ class DrupalErrorHandlerUnitTest extends DrupalWebTestCase {
   function getInfo() {
     return array(
       'name' => t('Drupal error handlers'),
-      'description' => t("Performs tests on the Drupal error and exception handler."),
+      'description' => t('Performs tests on the Drupal error and exception handler.'),
       'group' => t('System'),
     );
   }
@@ -521,3 +521,75 @@ class DrupalErrorHandlerUnitTest extends DrupalWebTestCase {
     $this->assertText($message, t("Found '%message' in error page.", array('%message' => $message)));
   }
 }
+
+/**
+ * Tests Simpletest error and exception collecter.
+ */
+class DrupalErrorCollectionUnitTest extends DrupalWebTestCase {
+
+  /**
+   * Errors triggered during the test.
+   *
+   * Errors are intercepted by the overriden implementation
+   * of DrupalWebTestCase::error below.
+   *
+   * @var Array
+   */
+  protected $collectedErrors = array();
+
+  function getInfo() {
+    return array(
+      'name' => t('SimpleTest error collecter'),
+      'description' => t('Performs tests on the Simpletest error and exception collecter.'),
+      'group' => t('SimpleTest'),
+    );
+  }
+
+  function setUp() {
+    parent::setUp('system_test');
+  }
+
+  /**
+   * Test that simpletest collects errors from the tested site.
+   */
+  function testErrorCollect() {
+    $this->collectedErrors = array();
+    $this->drupalGet('system-test/generate-warnings-with-report');
+
+    $this->assertEqual(count($this->collectedErrors), 3, t('Two errors were collected'));
+
+    if (count($this->collectedErrors) == 3) {
+      $this->assertError($this->collectedErrors[0], 'Notice', 'system_test_generate_warnings()', 'system_test.module', 'Undefined variable: bananas');
+      $this->assertError($this->collectedErrors[1], 'Warning', 'system_test_generate_warnings()', 'system_test.module', 'Division by zero');
+      $this->assertError($this->collectedErrors[2], 'User notice', 'system_test_generate_warnings()', 'system_test.module', 'Drupal is awesome');
+    }
+    else {
+      // Give back the errors to the log report.
+      foreach ($this->collectedErrors as $error) {
+        parent::error($error['message'], $error['group'], $error['caller']);
+      }
+    }
+  }
+
+  protected function error($message = '', $group = 'Other', Array $caller = NULL) {
+    // This function overiddes DrupalWebTestCase::error(). We collect an error...
+    $this->collectedErrors[] = array(
+      'message' => $message,
+      'group' => $group,
+      'caller' => $caller
+    );
+    // ... and ignore it.
+  }
+
+  /**
+   * Assert that a collected error matches what we are expecting.
+   */
+  function assertError($error, $group, $function, $file, $message = NULL) {
+    $this->assertEqual($error['group'], $group, t("Group was %group", array('%group' => $group)));
+    $this->assertEqual($error['caller']['function'], $function, t("Function was %function", array('%function' => $function)));
+    $this->assertEqual(basename($error['caller']['file']), $file, t("File was %file", array('%file' => $file)));
+    if (isset($message)) {
+      $this->assertEqual($error['message'], $message, t("Message was %message", array('%message' => $message)));
+    }
+  }
+}
\ No newline at end of file
diff --git modules/simpletest/tests/system_test.module modules/simpletest/tests/system_test.module
index 19fab32..75fd384 100644
--- modules/simpletest/tests/system_test.module
+++ modules/simpletest/tests/system_test.module
@@ -55,6 +55,14 @@ function system_test_menu() {
     'type' => MENU_CALLBACK,
   );
 
+  $items['system-test/generate-warnings-with-report'] = array(
+    'title' => 'Generate warnings with Simpletest reporting',
+    'page callback' => 'system_test_generate_warnings',
+    'page arguments' => array(TRUE),
+    'access callback' => TRUE,
+    'type' => MENU_CALLBACK,
+  );
+
   $items['system-test/trigger-exception'] = array(
     'title' => 'Trigger an exception',
     'page callback' => 'system_test_trigger_exception',
@@ -159,8 +167,9 @@ function system_test_exit() {
 /**
  * Menu callback; generate warnings to test the error handler.
  */
-function system_test_generate_warnings() {
-  define('SIMPLETEST_DONT_COLLECT_ERRORS', TRUE);
+function system_test_generate_warnings($collect_errors = FALSE) {
+  // Tell Drupal error reporter to send errors to Simpletest or not.
+  define('SIMPLETEST_COLLECT_ERRORS', $collect_errors);
   // This will generate a notice.
   $monkey_love = $bananas;
   // This will generate a warning.
@@ -174,7 +183,7 @@ function system_test_generate_warnings() {
  * Menu callback; trigger an exception to test the exception handler.
  */
 function system_test_trigger_exception() {
-  define('SIMPLETEST_DONT_COLLECT_ERRORS', TRUE);
+  define('SIMPLETEST_COLLECT_ERRORS', FALSE);
   throw new Exception("Drupal is awesome");
 }
 
@@ -182,6 +191,6 @@ function system_test_trigger_exception() {
  * Menu callback; trigger an exception to test the exception handler.
  */
 function system_test_trigger_pdo_exception() {
-  define('SIMPLETEST_DONT_COLLECT_ERRORS', TRUE);
+  define('SIMPLETEST_COLLECT_ERRORS', FALSE);
   db_query("SELECT * FROM bananas_are_awesome");
 }
