diff --git a/core/modules/contextual/lib/Drupal/contextual/Tests/ContextualUnitTest.php b/core/modules/contextual/lib/Drupal/contextual/Tests/ContextualUnitTest.php index 738f047022d12974f1716bb3b653c056aaa76d9f..fcb3a03cc69653bd153cba67a7e4d2010be825ed 100644 --- a/core/modules/contextual/lib/Drupal/contextual/Tests/ContextualUnitTest.php +++ b/core/modules/contextual/lib/Drupal/contextual/Tests/ContextualUnitTest.php @@ -13,6 +13,14 @@ * Tests _contextual_links_to_id() & _contextual_id_to_links(). */ class ContextualUnitTest extends DrupalUnitTestBase { + + /** + * Modules to enable. + * + * @var array + */ + public static $modules = array('contextual'); + public static function getInfo() { return array( 'name' => 'Conversion to and from "contextual id"s (for placeholders)', diff --git a/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php index 441c2439ece5ade3a24ce871e66ab10bc19fab18..1ab979f9f7d10ca0973a974da1285e00170269de 100644 --- a/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php +++ b/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php @@ -371,13 +371,24 @@ public static function deleteAssert($message_id) { * The database connection to use for inserting assertions. */ public static function getDatabaseConnection() { + // Check whether there is a test runner connection. + // @see run-tests.sh + // @todo Convert Simpletest UI runner to create + use this connection, too. try { - $connection = Database::getConnection('default', 'simpletest_original_default'); + $connection = Database::getConnection('default', 'test-runner'); } catch (ConnectionNotDefinedException $e) { - // If the test was not set up, the simpletest_original_default - // connection does not exist. - $connection = Database::getConnection('default', 'default'); + // Check whether there is a backup of the original default connection. + // @see TestBase::prepareEnvironment() + try { + $connection = Database::getConnection('default', 'simpletest_original_default'); + } + catch (ConnectionNotDefinedException $e) { + // If TestBase::prepareEnvironment() or TestBase::restoreEnvironment() + // failed, the test-specific database connection does not exist + // yet/anymore, so fall back to the default of the (UI) test runner. + $connection = Database::getConnection('default', 'default'); + } } return $connection; } @@ -918,7 +929,7 @@ private function prepareDatabasePrefix() { // As soon as the database prefix is set, the test might start to execute. // All assertions as well as the SimpleTest batch operations are associated // with the testId, so the database prefix has to be associated with it. - $affected_rows = db_update('simpletest_test_id') + $affected_rows = self::getDatabaseConnection()->update('simpletest_test_id') ->fields(array('last_prefix' => $this->databasePrefix)) ->condition('test_id', $this->testId) ->execute(); @@ -936,6 +947,13 @@ private function changeDatabasePrefix() { if (empty($this->databasePrefix)) { $this->prepareDatabasePrefix(); } + // If the backup already exists, something went terribly wrong. + // This case is possible, because database connection info is a static + // global state construct on the Database class, which at least persists + // for all test methods executed in one PHP process. + if (Database::getConnectionInfo('simpletest_original_default')) { + throw new \RuntimeException("Bad Database connection state: 'simpletest_original_default' connection key already exists. Broken test?"); + } // Clone the current connection and replace the current prefix. $connection_info = Database::getConnectionInfo('default'); @@ -992,6 +1010,9 @@ private function prepareEnvironment() { $this->originalSite = conf_path(); $this->originalSettings = settings()->getAll(); $this->originalConfig = $GLOBALS['config']; + // @todo Remove all remnants of $GLOBALS['conf']. + // @see https://drupal.org/node/2183323 + $this->originalConf = isset($GLOBALS['conf']) ? $GLOBALS['conf'] : NULL; // Backup statics and globals. $this->originalContainer = clone \Drupal::getContainer(); @@ -1075,6 +1096,8 @@ private function prepareEnvironment() { // Unset globals. unset($GLOBALS['config_directories']); + unset($GLOBALS['config']); + unset($GLOBALS['conf']); unset($GLOBALS['theme_key']); unset($GLOBALS['theme']); @@ -1085,9 +1108,6 @@ private function prepareEnvironment() { // Change the database prefix. $this->changeDatabasePrefix(); - // Remove all configuration overrides. - $GLOBALS['config'] = array(); - // After preparing the environment and changing the database prefix, we are // in a valid test environment. drupal_valid_test_ua($this->databasePrefix); @@ -1214,6 +1234,7 @@ private function restoreEnvironment() { // Restore original in-memory configuration. $GLOBALS['config'] = $this->originalConfig; + $GLOBALS['conf'] = $this->originalConf; new Settings($this->originalSettings); // Restore original statics and globals. diff --git a/core/modules/simpletest/lib/Drupal/simpletest/Tests/SimpleTestTest.php b/core/modules/simpletest/lib/Drupal/simpletest/Tests/SimpleTestTest.php index 488b9a70742228ed562ed042d795932e9f377cd8..d5a4cff93fed42217ce084e06697c9219b100a66 100644 --- a/core/modules/simpletest/lib/Drupal/simpletest/Tests/SimpleTestTest.php +++ b/core/modules/simpletest/lib/Drupal/simpletest/Tests/SimpleTestTest.php @@ -233,7 +233,7 @@ function confirmStubTestResults() { $this->assertAssertion("Debug: 'Foo'", 'Debug', 'Fail', 'SimpleTestTest.php', 'Drupal\simpletest\Tests\SimpleTestTest->stubTest()'); - $this->assertEqual('6 passes, 5 fails, 2 exceptions, 1 debug message', $this->childTestResults['summary'], 'Stub test summary is correct'); + $this->assertEqual('6 passes, 5 fails, 2 exceptions, 1 debug message', $this->childTestResults['summary']); $this->test_ids[] = $test_id = $this->getTestIdFromResults(); $this->assertTrue($test_id, 'Found test ID in results.'); diff --git a/core/modules/simpletest/simpletest.module b/core/modules/simpletest/simpletest.module index 579e85b9a2c26897a1305b49d358baa6fbb2a781..44c6ce1639c04afbd64ee678f6145f5e56d02f11 100644 --- a/core/modules/simpletest/simpletest.module +++ b/core/modules/simpletest/simpletest.module @@ -361,8 +361,16 @@ function _simpletest_batch_finished($success, $results, $operations, $elapsed) { * that ran. */ function simpletest_last_test_get($test_id) { - $last_prefix = db_query_range('SELECT last_prefix FROM {simpletest_test_id} WHERE test_id = :test_id', 0, 1, array(':test_id' => $test_id))->fetchField(); - $last_test_class = db_query_range('SELECT test_class FROM {simpletest} WHERE test_id = :test_id ORDER BY message_id DESC', 0, 1, array(':test_id' => $test_id))->fetchField(); + $last_prefix = TestBase::getDatabaseConnection() + ->queryRange('SELECT last_prefix FROM {simpletest_test_id} WHERE test_id = :test_id', 0, 1, array( + ':test_id' => $test_id, + )) + ->fetchField(); + $last_test_class = TestBase::getDatabaseConnection() + ->queryRange('SELECT test_class FROM {simpletest} WHERE test_id = :test_id ORDER BY message_id DESC', 0, 1, array( + ':test_id' => $test_id, + )) + ->fetchField(); return array($last_prefix, $last_test_class); } @@ -696,22 +704,23 @@ function simpletest_clean_temporary_directories() { */ function simpletest_clean_results_table($test_id = NULL) { if (\Drupal::config('simpletest.settings')->get('clear_results')) { + $connection = TestBase::getDatabaseConnection(); if ($test_id) { - $count = db_query('SELECT COUNT(test_id) FROM {simpletest_test_id} WHERE test_id = :test_id', array(':test_id' => $test_id))->fetchField(); + $count = $connection->query('SELECT COUNT(test_id) FROM {simpletest_test_id} WHERE test_id = :test_id', array(':test_id' => $test_id))->fetchField(); - db_delete('simpletest') + $connection->delete('simpletest') ->condition('test_id', $test_id) ->execute(); - db_delete('simpletest_test_id') + $connection->delete('simpletest_test_id') ->condition('test_id', $test_id) ->execute(); } else { - $count = db_query('SELECT COUNT(test_id) FROM {simpletest_test_id}')->fetchField(); + $count = $connection->query('SELECT COUNT(test_id) FROM {simpletest_test_id}')->fetchField(); // Clear test results. - db_delete('simpletest')->execute(); - db_delete('simpletest_test_id')->execute(); + $connection->delete('simpletest')->execute(); + $connection->delete('simpletest_test_id')->execute(); } return $count; diff --git a/core/scripts/run-tests.sh b/core/scripts/run-tests.sh index 5594dd532504aaab69621f7e06266a1c1217aa68..4f2d27bba754a72181e2adda1906cf15377ec660 100755 --- a/core/scripts/run-tests.sh +++ b/core/scripts/run-tests.sh @@ -1,12 +1,17 @@ <?php + /** * @file * This script runs Drupal tests from command line. */ -require_once __DIR__ . '/../vendor/autoload.php'; - +use Drupal\Component\Utility\Settings; use Drupal\Component\Utility\Timer; +use Drupal\Core\Database\Database; +use Drupal\Core\DrupalKernel; +use Symfony\Component\HttpFoundation\Request; + +require_once __DIR__ . '/../vendor/autoload.php'; const SIMPLETEST_SCRIPT_COLOR_PASS = 32; // Green. const SIMPLETEST_SCRIPT_COLOR_FAIL = 31; // Red. @@ -20,38 +25,26 @@ exit; } +simpletest_script_init(); +simpletest_script_bootstrap(); + if ($args['execute-test']) { - // Masquerade as Apache for running tests. - simpletest_script_init("Apache"); + simpletest_script_setup_database(); simpletest_script_run_one_test($args['test-id'], $args['execute-test']); - // Sub-process script execution ends here. -} -else { - // Run administrative functions as CLI. - simpletest_script_init(NULL); -} - -// Bootstrap to perform initial validation or other operations. -drupal_bootstrap(DRUPAL_BOOTSTRAP_CODE); - -if (!\Drupal::moduleHandler()->moduleExists('simpletest')) { - simpletest_script_print_error("The Testing (simpletest) module must be installed before this script can run."); + // Sub-process exited already; this is just for clarity. exit; } -simpletest_classloader_register(); -// We have to add a Request. -$request = \Symfony\Component\HttpFoundation\Request::createFromGlobals(); -$container = \Drupal::getContainer(); -$container->set('request', $request); + +simpletest_script_setup_database(TRUE); if ($args['clean']) { - // Clean up left-over times and directories. + // Clean up left-over tables and directories. simpletest_clean_environment(); echo "\nEnvironment cleaned.\n"; // Get the status messages and print them. - $messages = array_pop(drupal_get_messages('status')); - foreach ($messages as $text) { + $messages = drupal_get_messages('status'); + foreach ($messages['status'] as $text) { echo " - " . $text . "\n"; } exit; @@ -123,10 +116,26 @@ function simpletest_script_help() { --clean Cleans up database tables or directories from previous, failed, tests and then exits (no tests are run). - --url Immediately precedes a URL to set the host and path. You will - need this parameter if Drupal is in a subdirectory on your - localhost and you have not set \$base_url in settings.php. Tests - can be run under SSL by including https:// in the URL. + --url The base URL of the root directory of this Drupal checkout; e.g.: + http://drupal.test/ + Required unless the Drupal root directory maps exactly to: + http://localhost:80/ + Use a https:// URL to force all tests to be run under SSL. + + --sqlite A pathname to use for the SQLite database of the test runner. + Required unless this script is executed with a working Drupal + installation that has Simpletest module installed. + A relative pathname is interpreted relative to the Drupal root + directory. + Note that ':memory:' cannot be used, because this script spawns + sub-processes. However, you may use e.g. '/tmpfs/test.sqlite' + + --dburl A URI denoting the database driver, credentials, server hostname, + and database name to use in tests. For example: + mysql://username:password@localhost/databasename#table_prefix + Only used if specified. + Required when running tests without a Drupal installation that + contains default database connection info in settings.php. --php The absolute path to the PHP executable. Usually not needed. @@ -185,7 +194,16 @@ function simpletest_script_help() { --url http://example.com/ --all sudo -u [wwwrun|www-data|etc] php ./core/scripts/{$args['script']} --url http://example.com/ --class "Drupal\block\Tests\BlockTest" -\n + +Without a preinstalled Drupal site and enabled Simpletest module, specify a +SQLite database pathname to create and the default database connection info to +use in tests: + +sudo -u [wwwrun|www-data|etc] php ./core/scripts/{$args['script']} + --sqlite /tmpfs/drupal/test.sqlite + --dburl mysql://username:password@localhost/database + --url http://example.com/ --all + EOF; } @@ -202,6 +220,8 @@ function simpletest_script_parse_args() { 'list' => FALSE, 'clean' => FALSE, 'url' => '', + 'sqlite' => NULL, + 'dburl' => NULL, 'php' => '', 'concurrency' => 1, 'all' => FALSE, @@ -265,7 +285,7 @@ function simpletest_script_parse_args() { /** * Initialize script variables and perform general setup requirements. */ -function simpletest_script_init($server_software) { +function simpletest_script_init() { global $args, $php; $host = 'localhost'; @@ -311,7 +331,7 @@ function simpletest_script_init($server_software) { $_SERVER['REMOTE_ADDR'] = '127.0.0.1'; $_SERVER['SERVER_ADDR'] = '127.0.0.1'; $_SERVER['SERVER_PORT'] = $port; - $_SERVER['SERVER_SOFTWARE'] = $server_software; + $_SERVER['SERVER_SOFTWARE'] = NULL; $_SERVER['SERVER_NAME'] = 'localhost'; $_SERVER['REQUEST_URI'] = $path .'/'; $_SERVER['REQUEST_METHOD'] = 'GET'; @@ -331,6 +351,196 @@ function simpletest_script_init($server_software) { require_once dirname(__DIR__) . '/includes/bootstrap.inc'; } +/** + * Bootstraps a minimal Drupal environment. + * + * @see install_begin_request() + */ +function simpletest_script_bootstrap() { + // Load legacy include files. + foreach (glob(DRUPAL_ROOT . '/core/includes/*.inc') as $include) { + require_once $include; + } + + // Replace services with in-memory and null implementations. + $GLOBALS['conf']['container_service_providers']['InstallerServiceProvider'] = 'Drupal\Core\Installer\InstallerServiceProvider'; + + drupal_bootstrap(DRUPAL_BOOTSTRAP_CONFIGURATION); + + // Remove Drupal's error/exception handlers; they are designed for HTML + // and there is no storage nor a (watchdog) logger here. + restore_error_handler(); + restore_exception_handler(); + + // In addition, ensure that PHP errors are not hidden away in logs. + ini_set('display_errors', TRUE); + + // Ensure that required Settings exist. + if (!Settings::getSingleton()->getAll()) { + new Settings(array( + 'hash_salt' => 'run-tests', + )); + } + + $kernel = new DrupalKernel('testing', drupal_classloader(), FALSE); + $kernel->boot(); + + $request = Request::createFromGlobals(); + $container = $kernel->getContainer(); + $container->enterScope('request'); + $container->set('request', $request, 'request'); + + $module_handler = $container->get('module_handler'); + // @todo Remove System module. Only needed because \Drupal\Core\Datetime\Date + // has a (needless) dependency on the 'date_format' entity, so calls to + // format_date()/format_interval() cause a plugin not found exception. + $module_list['system'] = 'core/modules/system/system.module'; + $module_list['simpletest'] = 'core/modules/simpletest/simpletest.module'; + $module_handler->setModuleList($module_list); + $module_handler->loadAll(); + $kernel->updateModules($module_list, $module_list); + + simpletest_classloader_register(); +} + +/** + * Sets up database connection info for running tests. + * + * If this script is executed from within a real Drupal installation, then this + * function essentially performs nothing (unless the --sqlite or --dburl + * parameters were passed). + * + * Otherwise, there are three database connections of concern: + * - --sqlite: The test runner connection, providing access to Simpletest + * database tables for recording test IDs and assertion results. + * - --dburl: A database connection that is used as base connection info for all + * tests; i.e., every test will spawn from this connection. In case this + * connection uses e.g. SQLite, then all tests will run against SQLite. This + * is exposed as $databases['default']['default'] to Drupal. + * - The actual database connection used within a test. This is the same as + * --dburl, but uses an additional database table prefix. This is + * $databases['default']['default'] within a test environment. The original + * connection is retained in + * $databases['simpletest_original_default']['default'] and restored after + * each test. + * + * @param bool $new + * Whether this process is a run-tests.sh master process. If TRUE, the SQLite + * database file specified by --sqlite (if any) is set up. Otherwise, database + * connections are prepared only. + */ +function simpletest_script_setup_database($new = FALSE) { + global $args, $databases; + + // If there is an existing Drupal installation that contains a database + // connection info in settings.php, then $databases['default']['default'] will + // hold the default database connection already. This connection is assumed to + // be valid, and this connection will be used in tests, so that they run + // against e.g. MySQL instead of SQLite. + + // However, in case no Drupal installation exists, this default database + // connection can be set and/or overridden with the --dburl parameter. + if (!empty($args['dburl'])) { + // Remove a possibly existing default connection (from settings.php). + unset($databases['default']); + Database::removeConnection('default'); + + $info = parse_url($args['dburl']); + if (!isset($info['scheme'], $info['host'], $info['path'])) { + simpletest_script_print_error('Invalid --dburl. Minimum requirement: driver://host/database'); + exit(1); + } + $info += array( + 'user' => '', + 'pass' => '', + 'fragment' => '', + ); + $databases['default']['default'] = array( + 'driver' => $info['scheme'], + 'username' => $info['user'], + 'password' => $info['pass'], + 'host' => $info['host'], + 'database' => ltrim($info['path'], '/'), + 'prefix' => array( + 'default' => $info['fragment'], + ), + ); + } + // Otherwise, ensure that database table prefix info is an array. + // @see https://drupal.org/node/2176621 + elseif (isset($databases['default']['default'])) { + if (!is_array($databases['default']['default']['prefix'])) { + $databases['default']['default']['prefix'] = array( + 'default' => $databases['default']['default']['prefix'], + ); + } + } + + // If there is no default database connection for tests, we cannot continue. + if (!isset($databases['default']['default'])) { + simpletest_script_print_error('Missing default database connection for tests. Use --dburl to specify one.'); + exit(1); + } + Database::addConnectionInfo('default', 'default', $databases['default']['default']); + + // If no --sqlite parameter has been passed, then Simpletest module is assumed + // to be installed, so the test runner database connection is the default + // database connection. + if (empty($args['sqlite'])) { + $sqlite = FALSE; + $databases['test-runner']['default'] = $databases['default']['default']; + } + // Otherwise, set up a SQLite connection for the test runner. + else { + if ($args['sqlite'][0] === '/') { + $sqlite = $args['sqlite']; + } + else { + $sqlite = DRUPAL_ROOT . '/' . $args['sqlite']; + } + $databases['test-runner']['default'] = array( + 'driver' => 'sqlite', + 'database' => $sqlite, + 'prefix' => array( + 'default' => '', + ), + ); + // Create the test runner SQLite database, unless it exists already. + if ($new && !file_exists($sqlite)) { + if (!is_dir(dirname($sqlite))) { + mkdir(dirname($sqlite)); + } + touch($sqlite); + } + } + + // Add the test runner database connection. + Database::addConnectionInfo('test-runner', 'default', $databases['test-runner']['default']); + + // Create the Simpletest schema. + try { + $schema = Database::getConnection('default', 'test-runner')->schema(); + } + catch (\PDOException $e) { + simpletest_script_print_error($databases['test-runner']['default']['driver'] . ': ' . $e->getMessage()); + exit(1); + } + if ($new && $sqlite) { + require_once DRUPAL_ROOT . '/' . drupal_get_path('module', 'simpletest') . '/simpletest.install'; + foreach (simpletest_schema() as $name => $table_spec) { + if ($schema->tableExists($name)) { + $schema->dropTable($name); + } + $schema->createTable($name, $table_spec); + } + } + // Verify that the Simpletest database schema exists by checking one table. + if (!$schema->tableExists('simpletest')) { + simpletest_script_print_error('Missing Simpletest database schema. Either install Simpletest module or use the --sqlite parameter.'); + exit(1); + } +} + /** * Get all available tests from simpletest and PHPUnit. * @@ -373,7 +583,8 @@ function simpletest_script_execute_batch($test_classes) { break; } - $test_id = db_insert('simpletest_test_id')->useDefaults(array('test_id'))->execute(); + $test_id = Database::getConnection('default', 'test-runner') + ->insert('simpletest_test_id')->useDefaults(array('test_id'))->execute(); $test_ids[] = $test_id; $test_class = array_shift($test_classes); @@ -471,11 +682,7 @@ function simpletest_script_run_phpunit($test_id, $class) { } foreach ($summaries as $class => $summary) { - $had_fails = $summary['#fail'] > 0; - $had_exceptions = $summary['#exception'] > 0; - $status = ($had_fails || $had_exceptions ? 'fail' : 'pass'); - $info = call_user_func(array($class, 'getInfo')); - simpletest_script_print($info['name'] . ' ' . _simpletest_format_summary_line($summary) . "\n", simpletest_script_color_code($status)); + simpletest_script_reporter_display_summary($class, $summary); } } @@ -486,24 +693,12 @@ function simpletest_script_run_one_test($test_id, $test_class) { global $args; try { - // Bootstrap Drupal. - drupal_bootstrap(DRUPAL_BOOTSTRAP_CODE); - simpletest_classloader_register(); - // We have to add a Request. - $request = \Symfony\Component\HttpFoundation\Request::createFromGlobals(); - $container = \Drupal::getContainer(); - $container->set('request', $request); - $test = new $test_class($test_id); $test->dieOnFail = (bool) $args['die-on-fail']; $test->verbose = (bool) $args['verbose']; $test->run(); - $info = $test->getInfo(); - $had_fails = (isset($test->results['#fail']) && $test->results['#fail'] > 0); - $had_exceptions = (isset($test->results['#exception']) && $test->results['#exception'] > 0); - $status = ($had_fails || $had_exceptions ? 'fail' : 'pass'); - simpletest_script_print($info['name'] . ' ' . _simpletest_format_summary_line($test->results) . "\n", simpletest_script_color_code($status)); + simpletest_script_reporter_display_summary($test_class, $test->results); // Finished, kill this runner. exit(0); @@ -529,6 +724,12 @@ function simpletest_script_command($test_id, $test_class) { $command = escapeshellarg($php) . ' ' . escapeshellarg('./core/scripts/' . $args['script']); $command .= ' --url ' . escapeshellarg($args['url']); + if (!empty($args['sqlite'])) { + $command .= ' --sqlite ' . escapeshellarg($args['sqlite']); + } + if (!empty($args['dburl'])) { + $command .= ' --dburl ' . escapeshellarg($args['dburl']); + } $command .= ' --php ' . escapeshellarg($php); $command .= " --test-id $test_id"; foreach (array('verbose', 'keep-results', 'color', 'die-on-fail') as $arg) { @@ -597,17 +798,18 @@ function simpletest_script_cleanup($test_id, $test_class, $exitcode) { // would also delete file directories of other tests that are potentially // running concurrently. file_unmanaged_delete_recursive($test_directory, array('Drupal\simpletest\TestBase', 'filePreDeleteCallback')); - $messages[] = "- Removed test files directory."; + $messages[] = "- Removed test site directory."; } // Clear out all database tables from the test. + $schema = Database::getConnection('default', 'default')->schema(); $count = 0; - foreach (db_find_tables($db_prefix . '%') as $table) { - db_drop_table($table); + foreach ($schema->findTables($db_prefix . '%') as $table) { + $schema->dropTable($table); $count++; } if ($count) { - $messages[] = "- " . format_plural($count, 'Removed 1 leftover table.', 'Removed @count leftover tables.'); + $messages[] = "- Removed $count leftover tables."; } if ($output) { @@ -710,14 +912,13 @@ function simpletest_script_reporter_init() { else { echo "Tests to be run:\n"; foreach ($test_list as $class_name) { - $info = call_user_func(array($class_name, 'getInfo')); - echo " - " . $info['name'] . ' (' . $class_name . ')' . "\n"; + echo " - $class_name\n"; } echo "\n"; } echo "Test run started:\n"; - echo " " . format_date($_SERVER['REQUEST_TIME'], 'long') . "\n"; + echo " " . date('l, F j, Y - H:i', $_SERVER['REQUEST_TIME']) . "\n"; Timer::start('run-tests'); echo "\n"; @@ -726,13 +927,40 @@ function simpletest_script_reporter_init() { echo "\n"; } +/** + * Displays the assertion result summary for a single test class. + * + * @param string $class + * The test class name that was run. + * @param array $results + * The assertion results using #pass, #fail, #exception, #debug array keys. + */ +function simpletest_script_reporter_display_summary($class, $results) { + // Output all test results vertically aligned. + // Cut off the class name after 60 chars, and pad each group with 3 digits + // by default (more than 999 assertions are rare). + $output = vsprintf('%-60.60s %10s %9s %14s %12s', array( + $class, + $results['#pass'] . ' passes', + !$results['#fail'] ? '' : $results['#fail'] . ' fails', + !$results['#exception'] ? '' : $results['#exception'] . ' exceptions', + !$results['#debug'] ? '' : $results['#debug'] . ' messages', + )); + + $status = ($results['#fail'] || $results['#exception'] ? 'fail' : 'pass'); + simpletest_script_print($output . "\n", simpletest_script_color_code($status)); +} + /** * Display jUnit XML test results. */ function simpletest_script_reporter_write_xml_results() { global $args, $test_ids, $results_map; - $results = db_query("SELECT * FROM {simpletest} WHERE test_id IN (:test_ids) ORDER BY test_class, message_id", array(':test_ids' => $test_ids)); + $results = Database::getConnection('default', 'test-runner') + ->query("SELECT * FROM {simpletest} WHERE test_id IN (:test_ids) ORDER BY test_class, message_id", array( + ':test_ids' => $test_ids, + )); $test_class = ''; $xml_files = array(); @@ -817,7 +1045,10 @@ function simpletest_script_reporter_display_results() { echo "Detailed test results\n"; echo "---------------------\n"; - $results = db_query("SELECT * FROM {simpletest} WHERE test_id IN (:test_ids) ORDER BY test_class, message_id", array(':test_ids' => $test_ids)); + $results = Database::getConnection('default', 'test-runner') + ->query("SELECT * FROM {simpletest} WHERE test_id IN (:test_ids) ORDER BY test_class, message_id", array( + ':test_ids' => $test_ids, + )); $test_class = ''; foreach ($results as $result) { if (isset($results_map[$result->status])) {