/** * Test the complete Drupal migration. */ public function testDrupal() { $dumps = $this->getDumps(); $this->loadDumps($dumps); $classes = $this->getTestClassesList(); foreach ($classes as $class) { if (is_subclass_of($class, '\\Drupal\\migrate\\Tests\\MigrateDumpAlterInterface')) { $class::migrateDumpAlter($this); } } // Run every migration in the order specified by the storage controller. foreach (entity_load_multiple('migration', static::$migrations) as $migration) { (new MigrateExecutable($migration, $this))->import(); } foreach ($classes as $class) { $test_object = new $class($this->testId); $test_object->databasePrefix = $this->databasePrefix; $test_object->container = $this->container; // run() does a lot of setup and tear down work which we don't need: // it would setup a new database connection and wouldn't find the // Drupal dump. Also by skipping the setUp() methods there are no id // mappings or entities prepared. The tests run against solely migrated // data. foreach (get_class_methods($test_object) as $method) { if (strtolower(substr($method, 0, 4)) == 'test') { // 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 . '()'); $completion_check_id = TestBase::insertAssert($this->testId, $class, FALSE, 'The test did not complete due to a fatal error.', 'Completion check', $caller); // Run the test method. try { $test_object->{$method}(); } catch (\Exception $e) { $this->exceptionHandler($e); } // Remove the completion check record. TestBase::deleteAssert($completion_check_id); } } // Add the pass/fail/exception/debug results. foreach ($this->results as $key => &$value) { $value += $test_object->results[$key]; } } }
/** * 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(); }
/** * Test the complete Drupal migration. */ public function testDrupal() { $dumps = $this->getDumps(); $this->loadDumps($dumps); $classes = $this->getTestClassesList(); $extension_install_storage = new ExtensionInstallStorage(\Drupal::service('config.storage'), InstallStorage::CONFIG_OPTIONAL_DIRECTORY, StorageInterface::DEFAULT_COLLECTION, TRUE); foreach ($classes as $class) { if (is_subclass_of($class, '\\Drupal\\migrate\\Tests\\MigrateDumpAlterInterface')) { $class::migrateDumpAlter($this); } } // Run every migration in the order specified by the storage controller. foreach (entity_load_multiple('migration', static::$migrations) as $migration) { (new MigrateExecutable($migration, $this))->import(); // Ensure that the default migration has the correct dependencies. list($base_name, ) = explode(':', $migration->id(), 2); $default_configuration = $extension_install_storage->read('migrate.migration.' . $base_name); $default_dependencies = isset($default_configuration['dependencies']) ? $default_configuration['dependencies'] : []; $this->assertEqual($default_dependencies, $migration->getDependencies(), SafeMarkup::format('Dependencies in @id match after installing. Default configuration @first is equal to active configuration @second.', array('@id' => $migration->id(), '@first' => var_export($default_dependencies, TRUE), '@second' => var_export($migration->getDependencies(), TRUE)))); } foreach ($classes as $class) { $test_object = new $class($this->testId); $test_object->databasePrefix = $this->databasePrefix; $test_object->container = $this->container; // run() does a lot of setup and tear down work which we don't need: // it would setup a new database connection and wouldn't find the // Drupal dump. Also by skipping the setUp() methods there are no id // mappings or entities prepared. The tests run against solely migrated // data. foreach (get_class_methods($test_object) as $method) { if (strtolower(substr($method, 0, 4)) == 'test') { // 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 . '()'); $completion_check_id = TestBase::insertAssert($this->testId, $class, FALSE, 'The test did not complete due to a fatal error.', 'Completion check', $caller); // Run the test method. try { $test_object->{$method}(); } catch (\Exception $e) { $this->exceptionHandler($e); } // Remove the completion check record. TestBase::deleteAssert($completion_check_id); } } // Add the pass/fail/exception/debug results. foreach ($this->results as $key => &$value) { $value += $test_object->results[$key]; } } }