* * The Drupal project primarily uses runtime assertions to enforce the * expectations of the API by failing when incorrect calls are made by code * under development. * * @see http://php.net/assert * @see https://www.drupal.org/node/2492225 * * If you are using PHP 7.0 it is strongly recommended that you set * zend.assertions=1 in the PHP.ini file (It cannot be changed from .htaccess * or runtime) on development machines and to 0 in production. * * @see https://wiki.php.net/rfc/expectations */ assert_options(ASSERT_ACTIVE, TRUE); \Drupal\Component\Assertion\Handle::register(); /** * Enable local development services. */ $settings['container_yamls'][] = DRUPAL_ROOT . '/sites/development.services.yml'; $settings['container_yamls'][] = DRUPAL_ROOT . '/sites/default/services.yml'; /** * Show all error messages, with backtrace information. * * In case the error level could not be fetched from the database, as for * example the database connection failed, we rely only on this value. */ $config['system.logging']['error_level'] = 'verbose'; /** * Disable CSS and JS aggregation. */
/** * Run all tests in this class. * * Regardless of whether $methods are passed or not, only method names * starting with "test" are executed. * * @param $methods * (optional) A list of method names in the test case class to run; e.g., * array('testFoo', 'testBar'). By default, all methods of the class are * taken into account, but it can be useful to only run a few selected test * methods during debugging. */ public function run(array $methods = array()) { $class = get_class($this); if ($missing_requirements = $this->checkRequirements()) { $object_info = new \ReflectionObject($this); $caller = array('file' => $object_info->getFileName()); foreach ($missing_requirements as $missing_requirement) { TestBase::insertAssert($this->testId, $class, FALSE, $missing_requirement, 'Requirements check', $caller); } return; } TestServiceProvider::$currentTest = $this; $simpletest_config = $this->config('simpletest.settings'); // Unless preset from run-tests.sh, retrieve the current verbose setting. if (!isset($this->verbose)) { $this->verbose = $simpletest_config->get('verbose'); } if ($this->verbose) { // Initialize verbose debugging. $this->verbose = TRUE; $this->verboseDirectory = PublicStream::basePath() . '/simpletest/verbose'; $this->verboseDirectoryUrl = file_create_url($this->verboseDirectory); if (file_prepare_directory($this->verboseDirectory, FILE_CREATE_DIRECTORY) && !file_exists($this->verboseDirectory . '/.htaccess')) { file_put_contents($this->verboseDirectory . '/.htaccess', "<IfModule mod_expires.c>\nExpiresActive Off\n</IfModule>\n"); } $this->verboseClassName = str_replace("\\", "_", $class); } // HTTP auth settings (<username>:<password>) for the simpletest browser // when sending requests to the test site. $this->httpAuthMethod = (int) $simpletest_config->get('httpauth.method'); $username = $simpletest_config->get('httpauth.username'); $password = $simpletest_config->get('httpauth.password'); if (!empty($username) && !empty($password)) { $this->httpAuthCredentials = $username . ':' . $password; } // Force assertion failures to be thrown as AssertionError for PHP 5 & 7 // compatibility. \Drupal\Component\Assertion\Handle::register(); set_error_handler(array($this, 'errorHandler')); // Iterate through all the methods in this class, unless a specific list of // methods to run was passed. $test_methods = array_filter(get_class_methods($class), function ($method) { return strpos($method, 'test') === 0; }); if (empty($test_methods)) { // Call $this->assert() here because we need to pass along custom caller // information, lest the wrong originating code file/line be identified. $this->assert(FALSE, 'No test methods found.', 'Requirements', array('function' => __METHOD__ . '()', 'file' => __FILE__, 'line' => __LINE__)); } if ($methods) { $test_methods = array_intersect($test_methods, $methods); } foreach ($test_methods as $method) { // Insert a fail record. This will be deleted on completion to ensure // that testing completed. $method_info = new \ReflectionMethod($class, $method); $caller = array('file' => $method_info->getFileName(), 'line' => $method_info->getStartLine(), 'function' => $class . '->' . $method . '()'); $test_completion_check_id = TestBase::insertAssert($this->testId, $class, FALSE, 'The test did not complete due to a fatal error.', 'Completion check', $caller); try { $this->prepareEnvironment(); } catch (\Exception $e) { $this->exceptionHandler($e); // The prepareEnvironment() method isolates the test from the parent // Drupal site by creating a random database prefix and test site // directory. If this fails, a test would possibly operate in the // parent site. Therefore, the entire test run for this test class // has to be aborted. // restoreEnvironment() cannot be called, because we do not know // where exactly the environment setup failed. break; } try { $this->setUp(); } catch (\Exception $e) { $this->exceptionHandler($e); // Abort if setUp() fails, since all test methods will fail. // But ensure to clean up and restore the environment, since // prepareEnvironment() succeeded. $this->restoreEnvironment(); break; } try { $this->{$method}(); } catch (\Exception $e) { $this->exceptionHandler($e); } try { $this->tearDown(); } catch (\Exception $e) { $this->exceptionHandler($e); // If a test fails to tear down, abort the entire test class, since // it is likely that all tests will fail in the same way and a // failure here only results in additional test artifacts that have // to be manually deleted. $this->restoreEnvironment(); break; } $this->restoreEnvironment(); // Remove the test method completion check record. TestBase::deleteAssert($test_completion_check_id); } TestServiceProvider::$currentTest = NULL; // Clear out the error messages and restore error handler. drupal_get_messages(); restore_error_handler(); }
/** * Setup a consistent PHP environment. * * This method sets PHP environment options we want to be sure are set * correctly for security or just saneness. */ public static function bootEnvironment() { if (static::$isEnvironmentInitialized) { return; } // Include our bootstrap file. $core_root = dirname(dirname(dirname(__DIR__))); require_once $core_root . '/includes/bootstrap.inc'; // Enforce E_STRICT, but allow users to set levels not part of E_STRICT. error_reporting(E_STRICT | E_ALL); // Override PHP settings required for Drupal to work properly. // sites/default/default.settings.php contains more runtime settings. // The .htaccess file contains settings that cannot be changed at runtime. // Use session cookies, not transparent sessions that puts the session id in // the query string. ini_set('session.use_cookies', '1'); ini_set('session.use_only_cookies', '1'); ini_set('session.use_trans_sid', '0'); // Don't send HTTP headers using PHP's session handler. // Send an empty string to disable the cache limiter. ini_set('session.cache_limiter', ''); // Use httponly session cookies. ini_set('session.cookie_httponly', '1'); // Set sane locale settings, to ensure consistent string, dates, times and // numbers handling. setlocale(LC_ALL, 'C'); // Detect string handling method. Unicode::check(); // Indicate that code is operating in a test child site. if (!defined('DRUPAL_TEST_IN_CHILD_SITE')) { if ($test_prefix = drupal_valid_test_ua()) { // Only code that interfaces directly with tests should rely on this // constant; e.g., the error/exception handler conditionally adds further // error information into HTTP response headers that are consumed by // Simpletest's internal browser. define('DRUPAL_TEST_IN_CHILD_SITE', TRUE); // Web tests are to be conducted with runtime assertions active. assert_options(ASSERT_ACTIVE, TRUE); // Now synchronize PHP 5 and 7's handling of assertions as much as // possible. Handle::register(); // Log fatal errors to the test site directory. ini_set('log_errors', 1); ini_set('error_log', DRUPAL_ROOT . '/sites/simpletest/' . substr($test_prefix, 10) . '/error.log'); // Ensure that a rewritten settings.php is used if opcache is on. ini_set('opcache.validate_timestamps', 'on'); ini_set('opcache.revalidate_freq', 0); } else { // Ensure that no other code defines this. define('DRUPAL_TEST_IN_CHILD_SITE', FALSE); } } // Set the Drupal custom error handler. set_error_handler('_drupal_error_handler'); set_exception_handler('_drupal_exception_handler'); static::$isEnvironmentInitialized = TRUE; }
$loader->add('Drupal\\FunctionalJavascriptTests', __DIR__); if (!isset($GLOBALS['namespaces'])) { // Scan for arbitrary extension namespaces from core and contrib. $extension_roots = drupal_phpunit_contrib_extension_directory_roots(); $dirs = array_map('drupal_phpunit_find_extension_directories', $extension_roots); $dirs = array_reduce($dirs, 'array_merge', array()); $GLOBALS['namespaces'] = drupal_phpunit_get_extension_namespaces($dirs); } foreach ($GLOBALS['namespaces'] as $prefix => $paths) { $loader->addPsr4($prefix, $paths); } return $loader; } // Do class loader population. drupal_phpunit_populate_class_loader(); // Set sane locale settings, to ensure consistent string, dates, times and // numbers handling. // @see \Drupal\Core\DrupalKernel::bootEnvironment() setlocale(LC_ALL, 'C'); // Set the default timezone. While this doesn't cause any tests to fail, PHP // complains if 'date.timezone' is not set in php.ini. The Australia/Sydney // timezone is chosen so all tests are run using an edge case scenario (UTC+10 // and DST). This choice is made to prevent timezone related regressions and // reduce the fragility of the testing system in general. date_default_timezone_set('Australia/Sydney'); // Runtime assertions. PHPUnit follows the php.ini assert.active setting for // runtime assertions. By default this setting is on. Here we make a call to // make PHP 5 and 7 handle assertion failures the same way, but this call does // not turn runtime assertions on if they weren't on already. Handle::register();