diff --git a/core/modules/simpletest/drupal_web_test_case.php b/core/modules/simpletest/drupal_web_test_case.php index ca66143..2818578 100644 --- a/core/modules/simpletest/drupal_web_test_case.php +++ b/core/modules/simpletest/drupal_web_test_case.php @@ -74,6 +74,18 @@ abstract class DrupalTestCase { protected $skipClasses = array(__CLASS__ => TRUE); /** + * Flag to indicate whether the test has been set up. + * + * The setUp() method isolates the test from the parent Drupal site by + * creating a random prefix for the database and setting up a clean file + * storage directory. The tearDown() method then cleans up this test + * environment. We must ensure that setUp() has been run. Otherwise, + * tearDown() will act on the parent Drupal site rather than the test + * environment, destroying live data. + */ + protected $setup = FALSE; + + /** * Constructor for DrupalTestCase. * * @param $test_id @@ -127,7 +139,15 @@ abstract class DrupalTestCase { ); // Store assertion for display after the test has completed. - Database::getConnection('default', 'simpletest_original_default') + try { + $connection = Database::getConnection('default', 'simpletest_original_default'); + } + catch (DatabaseConnectionNotDefinedException $e) { + // If the test was not set up, the simpletest_original_default + // connection does not exist. + $connection = Database::getConnection('default', 'default'); + } + $connection ->insert('simpletest') ->fields($assertion) ->execute(); @@ -474,14 +494,19 @@ abstract class DrupalTestCase { ); $completion_check_id = DrupalTestCase::insertAssert($this->testId, $class, FALSE, t('The test did not complete due to a fatal error.'), 'Completion check', $caller); $this->setUp(); - try { - $this->$method(); - // Finish up. + if ($this->setup) { + try { + $this->$method(); + // Finish up. + } + catch (Exception $e) { + $this->exceptionHandler($e); + } + $this->tearDown(); } - catch (Exception $e) { - $this->exceptionHandler($e); + else { + $this->fail(t("The test cannot be executed because it has not been set up properly.")); } - $this->tearDown(); // Remove the completion check record. DrupalTestCase::deleteAssert($completion_check_id); } @@ -691,6 +716,7 @@ class DrupalUnitTestCase extends DrupalTestCase { unset($module_list['locale']); module_list(TRUE, FALSE, FALSE, $module_list); } + $this->setup = TRUE; } protected function tearDown() { @@ -1357,6 +1383,7 @@ class DrupalWebTestCase extends DrupalTestCase { variable_set('mail_system', array('default-system' => 'TestingMailSystem')); drupal_set_time_limit($this->timeLimit); + $this->setup = TRUE; } /** diff --git a/core/modules/simpletest/simpletest.test b/core/modules/simpletest/simpletest.test index 7a02aa1..a4bf08c 100644 --- a/core/modules/simpletest/simpletest.test +++ b/core/modules/simpletest/simpletest.test @@ -503,3 +503,70 @@ class SimpleTestMissingDependentModuleUnitTest extends DrupalUnitTestCase { $this->fail(t('Running test with missing required module.')); } } + +/** + * Tests a test case that does not run parent::setUp() in its setUp() method. + * + * If a test case does not call parent::setUp(), running + * DrupalTestCase::tearDown() would destroy the main site's database tables. + * Therefore, we ensure that tests which are not set up properly are skipped. + * + * @see DrupalTestCase + */ +class SimpleTestBrokenSetUp extends DrupalWebTestCase { + public static function getInfo() { + return array( + 'name' => 'Broken SimpleTest method', + 'description' => 'Tests a test case that does not call parent::setUp().', + 'group' => 'SimpleTest' + ); + } + + function setUp() { + // If the test is being run from the main site, set up normally. + if (!drupal_valid_test_ua()) { + parent::setUp('simpletest'); + // Create and log in user. + $admin_user = $this->drupalCreateUser(array('administer unit tests')); + $this->drupalLogin($admin_user); + } + // If the test is being run from within simpletest, set up the broken test. + else { + $this->pass(t('The test setUp() method has been run.')); + // Don't call parent::setUp(). This should trigger an error message. + } + } + + function tearDown() { + // If the test is being run from the main site, tear down normally. + if (!drupal_valid_test_ua()) { + parent::tearDown(); + } + else { + // If the test is being run from within simpletest, output a message. + $this->pass(t('The tearDown() method has run.')); + } + } + + /** + * Runs this test case from within the simpletest child site. + */ + function testBreakSetUp() { + // If the test is being run from the main site, run it again from the web + // interface within the simpletest child site. + if (!drupal_valid_test_ua()) { + $edit['SimpleTestBrokenSetUp'] = TRUE; + $this->drupalPost('admin/config/development/testing', $edit, t('Run tests')); + + // Verify that the broken test and its tearDown() method are skipped. + $this->assertRaw(t('The test setUp() method has been run.')); + $this->assertRaw(t('The test cannot be executed because it has not been set up properly.')); + $this->assertNoRaw(t('The test method has run.')); + $this->assertNoRaw(t('The tearDown() method has run.')); + } + // If the test is being run from within simpletest, output a message. + else { + $this->pass(t('The test method has run.')); + } + } +} diff --git a/core/modules/simpletest/tests/upgrade/upgrade.test b/core/modules/simpletest/tests/upgrade/upgrade.test index 69a5384..c53050e 100644 --- a/core/modules/simpletest/tests/upgrade/upgrade.test +++ b/core/modules/simpletest/tests/upgrade/upgrade.test @@ -136,6 +136,7 @@ abstract class UpgradePathTestCase extends DrupalWebTestCase { $this->variable_set('site_mail', 'simpletest@example.com'); drupal_set_time_limit($this->timeLimit); + $this->setup = TRUE; } /**