function setUp() { // Mark test as being run $this->originalIsRunningTest = self::$is_running_test; self::$is_running_test = true; // Remove password validation $this->originalMemberPasswordValidator = Member::password_validator(); $this->originalRequirements = Requirements::backend(); Member::set_password_validator(null); Cookie::set_report_errors(false); $className = get_class($this); $fixtureFile = eval("return {$className}::\$fixture_file;"); // Set up fixture if($fixtureFile) { if(substr(DB::getConn()->currentDatabase(),0,5) != 'tmpdb') { //echo "Re-creating temp database... "; self::create_temp_db(); //echo "done.\n"; } // This code is a bit misplaced; we want some way of the whole session being reinitialised... Versioned::reading_stage(null); singleton('DataObject')->flushCache(); $dbadmin = new DatabaseAdmin(); $dbadmin->clearAllData(); // We have to disable validation while we import the fixtures, as the order in // which they are imported doesnt guarantee valid relations until after the // import is complete. $validationenabled = DataObject::get_validation_enabled(); DataObject::set_validation_enabled(false); $this->fixture = new YamlFixture($fixtureFile); $this->fixture->saveIntoDatabase(); DataObject::set_validation_enabled($validationenabled); } // Set up email $this->originalMailer = Email::mailer(); $this->mailer = new TestMailer(); Email::set_mailer($this->mailer); }
/** * Remove all content from the temporary database. */ static function empty_temp_db() { if (self::using_temp_db()) { $dbadmin = new DatabaseAdmin(); $dbadmin->clearAllData(); // Some DataObjectsDecorators keep a static cache of information that needs to // be reset whenever the database is cleaned out foreach (array_merge(ClassInfo::subclassesFor('DataObjectDecorator'), ClassInfo::subclassesFor('DataObject')) as $class) { $toCall = array($class, 'on_db_reset'); if (is_callable($toCall)) { call_user_func($toCall); } } } }
function runTests($classList, $coverage = false) { global $TESTING_CONFIG; $startTime = microtime(true); Config::inst()->update('Director', 'environment_type', 'dev'); if (isset($TESTING_CONFIG['database']) && $TESTING_CONFIG['database'] != 'silverstripe_testing') { global $databaseConfig; $newConfig = $databaseConfig; $newConfig = array_merge($databaseConfig, $TESTING_CONFIG); $newConfig['memory'] = isset($TESTING_CONFIG['memory']) ? $TESTING_CONFIG['memory'] : true; $type = isset($newConfig['type']) ? $newConfig['type'] : 'MySQL'; Debug::message("Connecting to new database {$type} as defined by testing config"); DB::connect($newConfig); DB::getConn()->selectDatabase($TESTING_CONFIG['database']); $dbadmin = new DatabaseAdmin(); $dbadmin->clearAllData(); if (!(isset($_REQUEST['build']) && $_REQUEST['build'] == 0)) { $dbadmin->doBuild(true); } } // XDEBUG seem to cause problems with test execution :-( if (function_exists('xdebug_disable')) { xdebug_disable(); } ini_set('max_execution_time', 0); $this->setUp(); // Optionally skip certain tests $skipTests = array(); if ($this->request->getVar('SkipTests')) { $skipTests = explode(',', $this->request->getVar('SkipTests')); } $classList = array_diff($classList, $skipTests); // run tests before outputting anything to the client $suite = new PHPUnit_Framework_TestSuite(); natcasesort($classList); foreach ($classList as $className) { // Ensure that the autoloader pulls in the test class, as PHPUnit won't know how to do this. class_exists($className); $suite->addTest(new SapphireTestSuite($className)); } // Remove the error handler so that PHPUnit can add its own restore_error_handler(); // CUSTOMISATION if (Director::is_cli()) { if (isset($TESTING_CONFIG['reporter'])) { $clazz = $TESTING_CONFIG['reporter']; } else { $clazz = "CliTestReporter"; } } else { $clazz = "SapphireTestReporter"; } // END CUSTOMISATION $reporter = new $clazz(); $default = self::$default_reporter; self::$default_reporter->writeHeader("Sapphire Test Runner"); if (count($classList) > 1) { self::$default_reporter->writeInfo("All Tests", "Running test cases: " . implode(",", $classList)); } else { self::$default_reporter->writeInfo($classList[0], ""); } $results = new PHPUnit_Framework_TestResult(); $results->addListener($reporter); if ($coverage === true) { $results->collectCodeCoverageInformation(true); $suite->run($results); if (!file_exists(ASSETS_PATH . '/coverage-report')) { mkdir(ASSETS_PATH . '/coverage-report'); } PHPUnit_Util_Report::render($results, ASSETS_PATH . '/coverage-report/'); $coverageApp = ASSETS_PATH . '/coverage-report/' . preg_replace('/[^A-Za-z0-9]/', '_', preg_replace('/(\\/$)|(^\\/)/', '', Director::baseFolder())) . '.html'; $coverageTemplates = ASSETS_PATH . '/coverage-report/' . preg_replace('/[^A-Za-z0-9]/', '_', preg_replace('/(\\/$)|(^\\/)/', '', realpath(TEMP_FOLDER))) . '.html'; echo "<p>Coverage reports available here:<ul>\n\t\t\t\t<li><a href=\"{$coverageApp}\">Coverage report of the application</a></li>\n\t\t\t\t<li><a href=\"{$coverageTemplates}\">Coverage report of the templates</a></li>\n\t\t\t</ul>"; } else { $suite->run($results); } if (!Director::is_cli()) { echo '<div class="trace">'; } // CUSTOMISATION $outputFile = null; if ($TESTING_CONFIG['logfile']) { $outputFile = BASE_PATH . '/' . $TESTING_CONFIG['logfile']; } $reporter->writeResults($outputFile); // END CUSTOMISATION $endTime = microtime(true); if (Director::is_cli()) { echo "\n\nTotal time: " . round($endTime - $startTime, 3) . " seconds\n"; } else { echo "<p>Total time: " . round($endTime - $startTime, 3) . " seconds</p>\n"; } if (!Director::is_cli()) { echo '</div>'; } // Put the error handlers back Debug::loadErrorHandlers(); if (!Director::is_cli()) { self::$default_reporter->writeFooter(); } $this->tearDown(); // Todo: we should figure out how to pass this data back through Director more cleanly if (Director::is_cli() && $results->failureCount() + $results->errorCount() > 0) { exit(2); } }
/** * * Somewhat messy and god-method, but this override exists because * * a) we want to change the configuration of items from the user-set TESTING_CONFIG * variable if it exists * * b) PhpUnitWrapper is referenced with explicit class settings, rather than allowing us to * override as we like (to change code coverage behaviour). * * @global type TESTING_CONFIG * @global type $TESTING_CONFIG * @global type $databaseConfig * @param type $classList * @param type $coverage * @throws Exception */ function runTests($classList, $coverage = false) { global $TESTING_CONFIG; $startTime = microtime(true); Config::inst()->update('Director', 'environment_type', 'dev'); if (isset($TESTING_CONFIG['database']) && $TESTING_CONFIG['database'] != 'silverstripe_testing') { if (class_exists("Multisites")) { Multisites::inst()->resetCurrentSite(); } global $databaseConfig; $newConfig = $databaseConfig; $newConfig = array_merge($databaseConfig, $TESTING_CONFIG); $newConfig['memory'] = isset($TESTING_CONFIG['memory']) ? $TESTING_CONFIG['memory'] : true; $newDbName = $TESTING_CONFIG['database']; $type = isset($newConfig['type']) ? $newConfig['type'] : 'MySQL'; Debug::message("Connecting to new {$type} database {$TESTING_CONFIG['database']} as defined by testing config"); DB::connect($newConfig); if (!DB::getConn()->databaseExists($newDbName)) { DB::getConn()->createDatabase($newDbName); } if (!DB::getConn()->selectDatabase($newDbName)) { throw new Exception("Could not find database to use for testing"); } if ($newConfig['memory']) { Debug::message("Using in memory database"); } $dbadmin = new DatabaseAdmin(); if (isset($_REQUEST['clear']) && $_REQUEST['clear'] == 0) { } else { $dbadmin->clearAllData(); } if (!(isset($_REQUEST['build']) && $_REQUEST['build'] == 0)) { Debug::message("Executing dev/build as requested"); $dbadmin->doBuild(true); } } // XDEBUG seem to cause problems with test execution :-( if (function_exists('xdebug_disable')) { xdebug_disable(); } ini_set('max_execution_time', 0); $this->setUp(); // Optionally skip certain tests $skipTests = array(); if ($this->request->getVar('SkipTests')) { $skipTests = explode(',', $this->request->getVar('SkipTests')); } $abstractClasses = array(); foreach ($classList as $className) { // Ensure that the autoloader pulls in the test class, as PHPUnit won't know how to do this. class_exists($className); $reflection = new ReflectionClass($className); if ($reflection->isAbstract()) { array_push($abstractClasses, $className); } } $classList = array_diff($classList, $skipTests); // run tests before outputting anything to the client $suite = new PHPUnit_Framework_TestSuite(); natcasesort($classList); foreach ($classList as $className) { // Ensure that the autoloader pulls in the test class, as PHPUnit won't know how to do this. class_exists($className); $suite->addTest(new SapphireTestSuite($className)); } // Remove the error handler so that PHPUnit can add its own restore_error_handler(); // CUSTOMISATION if (Director::is_cli()) { if ($reporterClass = $this->request->requestVar('reporter')) { $clazz = $reporterClass; } else { if (isset($TESTING_CONFIG['reporter'])) { $clazz = $TESTING_CONFIG['reporter']; } else { $clazz = "CliTestReporter"; } } } else { $clazz = "SapphireTestReporter"; } // END CUSTOMISATION // CUSTOMISATION $outputFile = null; if ($TESTING_CONFIG['logfile']) { $outputFile = BASE_PATH . '/' . $TESTING_CONFIG['logfile']; } $reporter = new $clazz($outputFile); $default = self::$default_reporter; self::$default_reporter->writeHeader("Sapphire Test Runner"); if (count($classList) > 1) { self::$default_reporter->writeInfo("All Tests", "Running test cases: " . implode(",", $classList)); } else { self::$default_reporter->writeInfo($classList[0], ""); } $results = new PHPUnit_Framework_TestResult(); $results->addListener($reporter); if ($coverage === true) { $coverer = $this->getCodeCoverage(); $results->setCodeCoverage($coverer); $suite->run($results); $writer = new PHP_CodeCoverage_Report_HTML(); $writer->process($coverer, Director::baseFolder() . '/ssautesting/html/code-coverage-report'); } else { $suite->run($results); } if (!Director::is_cli()) { echo '<div class="trace">'; } if (method_exists($reporter, 'writeResults')) { $reporter->writeResults($outputFile); } else { $reporter->flush(); } // END CUSTOMISATION $endTime = microtime(true); if (Director::is_cli()) { echo "\n\nTotal time: " . round($endTime - $startTime, 3) . " seconds\n"; } else { echo "<p>Total time: " . round($endTime - $startTime, 3) . " seconds</p>\n"; } if (!Director::is_cli()) { echo '</div>'; } // Put the error handlers back Debug::loadErrorHandlers(); if (!Director::is_cli()) { self::$default_reporter->writeFooter(); } $this->tearDown(); // Todo: we should figure out how to pass this data back through Director more cleanly if (Director::is_cli() && $results->failureCount() + $results->errorCount() > 0) { exit(2); } }
function doReset($data, $form, $request) { if (!isset($data['devResetRandNumber'])) { Director::redirectBack(); return false; } // Avoid accidental database resets by checking the posted number to the one in session if (Session::get('devResetRandNumber') != $data['devResetRandNumber']) { Director::redirectBack(); return false; } $da = new DatabaseAdmin(); $da->clearAllData(); // If _ss_environment.php has some constants set for default admin, set these up in the request $_REQUEST['username'] = defined('SS_DEFAULT_ADMIN_USERNAME') ? SS_DEFAULT_ADMIN_USERNAME : null; $_REQUEST['password'] = defined('SS_DEFAULT_ADMIN_PASSWORD') ? SS_DEFAULT_ADMIN_PASSWORD : null; $da->build(); Session::clear('devResetRandNumber'); Director::redirect(Director::absoluteBaseURL() . 'dev/reset?done=1'); }