/** * 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; } 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(); }
/** * Registers test-specific services. * * Extend this method in your test to register additional services. This * method is called whenever the kernel is rebuilt. * * @param \Drupal\Core\DependencyInjection\ContainerBuilder $container * The service container to enhance. * * @see \Drupal\Tests\KernelTestBase::bootKernel() */ public function register(ContainerBuilder $container) { // Keep the container object around for tests. $this->container = $container; $container->register('flood', 'Drupal\\Core\\Flood\\MemoryBackend')->addArgument(new Reference('request_stack')); $container->register('lock', 'Drupal\\Core\\Lock\\NullLockBackend'); $container->register('cache_factory', 'Drupal\\Core\\Cache\\MemoryBackendFactory'); $container->register('keyvalue.memory', 'Drupal\\Core\\KeyValueStore\\KeyValueMemoryFactory')->addTag('persist'); $container->setAlias('keyvalue', 'keyvalue.memory'); // Set the default language on the minimal container. $container->setParameter('language.default_values', Language::$defaultValues); if ($this->strictConfigSchema) { $container->register('simpletest.config_schema_checker', 'Drupal\\Core\\Config\\Testing\\ConfigSchemaChecker')->addArgument(new Reference('config.typed'))->addArgument($this->getConfigSchemaExclusions())->addTag('event_subscriber'); } if ($container->hasDefinition('path_processor_alias')) { // Prevent the alias-based path processor, which requires a url_alias db // table, from being registered to the path processor manager. We do this // by removing the tags that the compiler pass looks for. This means the // url generator can safely be used within tests. $container->getDefinition('path_processor_alias')->clearTag('path_processor_inbound')->clearTag('path_processor_outbound'); } if ($container->hasDefinition('password')) { $container->getDefinition('password')->setArguments(array(1)); } TestServiceProvider::addRouteProvider($container); }