.../Core/Test/RunTests/RunTestsResultsBuilder.php | 245 --------------------- core/modules/simpletest/simpletest.module | 18 +- .../simpletest/src/Form/SimpletestResultsForm.php | 133 ++++++++++- core/scripts/run-tests.sh | 12 +- 4 files changed, 147 insertions(+), 261 deletions(-) diff --git a/core/lib/Drupal/Core/Test/RunTests/RunTestsResultsBuilder.php b/core/lib/Drupal/Core/Test/RunTests/RunTestsResultsBuilder.php deleted file mode 100644 index b5685edae5..0000000000 --- a/core/lib/Drupal/Core/Test/RunTests/RunTestsResultsBuilder.php +++ /dev/null @@ -1,245 +0,0 @@ - - {{ label }} {{ items|join(', ') }} - -TWIG; - - /** - * Builds the status image map. - * - * @return string[] - * Render array of icons for status displays. - */ - public static function buildStatusImageMap() { - $image_pass = [ - '#theme' => 'image', - '#uri' => 'core/misc/icons/73b355/check.svg', - '#width' => 18, - '#height' => 18, - '#alt' => 'Pass', - ]; - $image_fail = [ - '#theme' => 'image', - '#uri' => 'core/misc/icons/e32700/error.svg', - '#width' => 18, - '#height' => 18, - '#alt' => 'Fail', - ]; - $image_exception = [ - '#theme' => 'image', - '#uri' => 'core/misc/icons/e29700/warning.svg', - '#width' => 18, - '#height' => 18, - '#alt' => 'Exception', - ]; - $image_debug = [ - '#theme' => 'image', - '#uri' => 'core/misc/icons/e29700/warning.svg', - '#width' => 18, - '#height' => 18, - '#alt' => 'Debug', - ]; - return [ - 'pass' => $image_pass, - 'fail' => $image_fail, - 'exception' => $image_exception, - 'debug' => $image_debug, - ]; - } - - /** - * Adds the result form to a $form. - * - * This is a static method so that run-tests.sh can use it to generate a - * results page completely external to Drupal. This is why the UI strings are - * not wrapped in t(). - * - * @param array $form - * The form to attach the results to. - * @param array $results - * The simpletest results. - * - * @return array - * A list of tests the passed and failed. The array has two keys, 'pass' and - * 'fail'. Each contains a list of test classes. - * - * @see simpletest_script_open_browser() - * @see run-tests.sh - * @see \Drupal\simpletest\Form\SimpletestResultsForm - */ - public static function addResultForm(array &$form, array $results) { - // Transform the test results to be grouped by test class. - $test_results = []; - foreach ($results as $result) { - if (!isset($test_results[$result->test_class])) { - $test_results[$result->test_class] = []; - } - $test_results[$result->test_class][] = $result; - } - - $image_status_map = static::buildStatusImageMap(); - - // Keep track of which test cases passed or failed. - $filter = [ - 'pass' => [], - 'fail' => [], - ]; - - // Summary result widget. - $form['result'] = [ - '#type' => 'fieldset', - '#title' => 'Results', - // Because this is used in a theme-less situation need to provide a - // default. - '#attributes' => [], - ]; - - // Add summary line. - $form['result']['summary'] = $summary = [ - '#type' => 'inline_template', - '#template' => static::$summaryTemplate, - // Fill in the context for the template after we've tallied results in - // #pass, #fail, etc. - '#context' => [], - '#pass' => 0, - '#fail' => 0, - '#exception' => 0, - '#debug' => 0, - ]; - - \Drupal::service('test_discovery')->registerTestNamespaces(); - - // Cycle through each test group. - $header = [ - 'Message', - 'Group', - 'Filename', - 'Line', - 'Function', - ['colspan' => 2, 'data' => 'Status'], - ]; - $form['result']['results'] = []; - foreach ($test_results as $group => $assertions) { - // Create group details with summary information. - $info = TestDiscovery::getTestInfo($group); - $form['result']['results'][$group] = [ - '#type' => 'details', - '#title' => $info['name'], - '#open' => TRUE, - '#description' => $info['description'], - ]; - $form['result']['results'][$group]['summary'] = $summary; - $group_summary = & $form['result']['results'][$group]['summary']; - - // Create table of assertions for the group. - $rows = []; - foreach ($assertions as $assertion) { - $row = []; - $row[] = ['data' => ['#markup' => $assertion->message]]; - $row[] = $assertion->message_group; - $row[] = \Drupal::service('file_system')->basename(($assertion->file)); - $row[] = $assertion->line; - $row[] = $assertion->function; - $row[] = ['data' => $image_status_map[$assertion->status]]; - - $class = 'simpletest-' . $assertion->status; - if ($assertion->message_group == 'Debug') { - $class = 'simpletest-debug'; - } - $rows[] = ['data' => $row, 'class' => [$class]]; - - $group_summary['#' . $assertion->status]++; - $form['result']['summary']['#' . $assertion->status]++; - } - $form['result']['results'][$group]['table'] = [ - '#type' => 'table', - '#header' => $header, - '#rows' => $rows, - ]; - - $group_summary['#context'] = static::buildSummaryContext( - $group_summary['#pass'], - $group_summary['#fail'], - $group_summary['#exception'], - $group_summary['#debug'] - ); - - // Set summary information. - $group_summary['#ok'] = $group_summary['#fail'] + $group_summary['#exception'] == 0; - $form['result']['results'][$group]['#open'] = !$group_summary['#ok']; - - // Store test group (class) as for use in filter. - $filter[$group_summary['#ok'] ? 'pass' : 'fail'][] = $group; - } - - // Now that we've tallied all the results, we can compute the context for - // the results summary template. - - $form['result']['summary']['#context'] = static::buildSummaryContext( - $form['result']['summary']['#pass'], - $form['result']['summary']['#fail'], - $form['result']['summary']['#exception'], - $form['result']['summary']['#debug'] - ); - - // Overall summary status. - $form['result']['summary']['#ok'] = $form['result']['summary']['#fail'] + $form['result']['summary']['#exception'] == 0; - - return $filter; - } - - /** - * Assemble the context for the twig template in static::$summaryTemplate. - * - * @param int $pass - * The count of passing tests. - * @param int $fail - * The count of failing tests. - * @param int $exception - * The count of tests that threw an exception. - * @param int $debug - * The count of debug messages present. - * @param string $label - * An optional label for the summary line. - * - * @return string[] - * The context for the twig template in static::$summaryTemplate. - */ - protected static function buildSummaryContext($pass, $fail, $exception, $debug, $label = NULL) { - $context = []; - $translation = \Drupal::translation(); - - $context['label'] = $label; - $context['pass'] = $pass; - $context['fail'] = $fail; - $context['exception'] = $exception; - $context['debug'] = $debug; - - $context['items']['pass'] = $translation->formatPlural($pass, '1 pass', '@count passes'); - $context['items']['fail'] = $translation->formatPlural($fail, '1 fail', '@count fails'); - $context['items']['exception'] = $translation->formatPlural($exception, '1 exception', '@count exceptions'); - if ($debug) { - $context['items']['debug'] = $translation->formatPlural($debug, '1 debug message', '@count debug messages'); - } - return $context; - } - -} diff --git a/core/modules/simpletest/simpletest.module b/core/modules/simpletest/simpletest.module index 3c6f0feeb6..5775c1d83d 100644 --- a/core/modules/simpletest/simpletest.module +++ b/core/modules/simpletest/simpletest.module @@ -41,10 +41,6 @@ function simpletest_help($route_name, RouteMatchInterface $route_match) { /** * Implements hook_theme(). - * - * @todo Replace this theming system with - * Drupal\Core\Test\RunTests\RunTestsResultsBuilder in - * https://www.drupal.org/project/drupal/issues/3075490 */ function simpletest_theme() { return [ @@ -104,6 +100,20 @@ function _simpletest_build_summary_line($summary) { return $items; } +/** + * Formats test result summaries into a comma separated string for run-tests.sh. + * + * @param array $summary + * A summary of the test results. + * + * @return string + * A concatenated string of the formatted test results. + */ +function _simpletest_format_summary_line($summary) { + $parts = _simpletest_build_summary_line($summary); + return implode(', ', $parts); +} + /** * Runs tests. * diff --git a/core/modules/simpletest/src/Form/SimpletestResultsForm.php b/core/modules/simpletest/src/Form/SimpletestResultsForm.php index 5de37fcbbe..adc1d4a5bb 100644 --- a/core/modules/simpletest/src/Form/SimpletestResultsForm.php +++ b/core/modules/simpletest/src/Form/SimpletestResultsForm.php @@ -7,8 +7,8 @@ use Drupal\Core\Form\FormState; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Test\EnvironmentCleanerInterface; -use Drupal\Core\Test\RunTests\RunTestsResultsBuilder; use Drupal\Core\Url; +use Drupal\simpletest\TestDiscovery; use Symfony\Component\DependencyInjection\ContainerInterface; /** @@ -70,7 +70,40 @@ public function __construct(Connection $database, EnvironmentCleanerInterface $c * Builds the status image map. */ protected static function buildStatusImageMap() { - return RunTestsResultsBuilder::buildStatusImageMap(); + $image_pass = [ + '#theme' => 'image', + '#uri' => 'core/misc/icons/73b355/check.svg', + '#width' => 18, + '#height' => 18, + '#alt' => 'Pass', + ]; + $image_fail = [ + '#theme' => 'image', + '#uri' => 'core/misc/icons/e32700/error.svg', + '#width' => 18, + '#height' => 18, + '#alt' => 'Fail', + ]; + $image_exception = [ + '#theme' => 'image', + '#uri' => 'core/misc/icons/e29700/warning.svg', + '#width' => 18, + '#height' => 18, + '#alt' => 'Exception', + ]; + $image_debug = [ + '#theme' => 'image', + '#uri' => 'core/misc/icons/e29700/warning.svg', + '#width' => 18, + '#height' => 18, + '#alt' => 'Debug', + ]; + return [ + 'pass' => $image_pass, + 'fail' => $image_fail, + 'exception' => $image_exception, + 'debug' => $image_debug, + ]; } /** @@ -224,7 +257,101 @@ protected function getResults($test_id) { * @see run-tests.sh */ public static function addResultForm(array &$form, array $results) { - return RunTestsResultsBuilder::addResultForm($form, $results); + // Transform the test results to be grouped by test class. + $test_results = []; + foreach ($results as $result) { + if (!isset($test_results[$result->test_class])) { + $test_results[$result->test_class] = []; + } + $test_results[$result->test_class][] = $result; + } + + $image_status_map = static::buildStatusImageMap(); + + // Keep track of which test cases passed or failed. + $filter = [ + 'pass' => [], + 'fail' => [], + ]; + + // Summary result widget. + $form['result'] = [ + '#type' => 'fieldset', + '#title' => 'Results', + // Because this is used in a theme-less situation need to provide a + // default. + '#attributes' => [], + ]; + $form['result']['summary'] = $summary = [ + '#theme' => 'simpletest_result_summary', + '#pass' => 0, + '#fail' => 0, + '#exception' => 0, + '#debug' => 0, + ]; + + \Drupal::service('test_discovery')->registerTestNamespaces(); + + // Cycle through each test group. + $header = [ + 'Message', + 'Group', + 'Filename', + 'Line', + 'Function', + ['colspan' => 2, 'data' => 'Status'], + ]; + $form['result']['results'] = []; + foreach ($test_results as $group => $assertions) { + // Create group details with summary information. + $info = TestDiscovery::getTestInfo($group); + $form['result']['results'][$group] = [ + '#type' => 'details', + '#title' => $info['name'], + '#open' => TRUE, + '#description' => $info['description'], + ]; + $form['result']['results'][$group]['summary'] = $summary; + $group_summary =& $form['result']['results'][$group]['summary']; + + // Create table of assertions for the group. + $rows = []; + foreach ($assertions as $assertion) { + $row = []; + $row[] = ['data' => ['#markup' => $assertion->message]]; + $row[] = $assertion->message_group; + $row[] = \Drupal::service('file_system')->basename(($assertion->file)); + $row[] = $assertion->line; + $row[] = $assertion->function; + $row[] = ['data' => $image_status_map[$assertion->status]]; + + $class = 'simpletest-' . $assertion->status; + if ($assertion->message_group == 'Debug') { + $class = 'simpletest-debug'; + } + $rows[] = ['data' => $row, 'class' => [$class]]; + + $group_summary['#' . $assertion->status]++; + $form['result']['summary']['#' . $assertion->status]++; + } + $form['result']['results'][$group]['table'] = [ + '#type' => 'table', + '#header' => $header, + '#rows' => $rows, + ]; + + // Set summary information. + $group_summary['#ok'] = $group_summary['#fail'] + $group_summary['#exception'] == 0; + $form['result']['results'][$group]['#open'] = !$group_summary['#ok']; + + // Store test group (class) as for use in filter. + $filter[$group_summary['#ok'] ? 'pass' : 'fail'][] = $group; + } + + // Overall summary status. + $form['result']['summary']['#ok'] = $form['result']['summary']['#fail'] + $form['result']['summary']['#exception'] == 0; + + return $filter; } } diff --git a/core/scripts/run-tests.sh b/core/scripts/run-tests.sh index 0b40f51e3f..9d3f3894eb 100755 --- a/core/scripts/run-tests.sh +++ b/core/scripts/run-tests.sh @@ -16,10 +16,10 @@ use Drupal\Core\StreamWrapper\PublicStream; use Drupal\Core\Test\EnvironmentCleaner; use Drupal\Core\Test\PhpUnitTestRunner; -use Drupal\Core\Test\RunTests\RunTestsResultsBuilder; use Drupal\Core\Test\RunTests\TestFileParser; use Drupal\Core\Test\TestDatabase; use Drupal\Core\Test\TestRunnerKernel; +use Drupal\simpletest\Form\SimpletestResultsForm; use Drupal\Core\Test\TestDiscovery; use PHPUnit\Framework\TestCase; use Symfony\Component\Console\Output\ConsoleOutput; @@ -815,9 +815,6 @@ function simpletest_script_run_one_test($test_id, $test_class) { global $args; try { - // Default to status = success. This could mean that we didn't discover any - // tests and that none ran. - $status = SIMPLETEST_SCRIPT_EXIT_SUCCESS; if (strpos($test_class, '::') > 0) { list($class_name, $method) = explode('::', $test_class, 2); $methods = [$method]; @@ -834,10 +831,7 @@ function simpletest_script_run_one_test($test_id, $test_class) { if (is_subclass_of($test_class, TestCase::class)) { $status = simpletest_script_run_phpunit($test_id, $test_class); } - // If we aren't running a PHPUnit-based test, then we might have a - // Simpletest-based one. Ensure that: 1) The simpletest framework exists, - // and 2) That our test belongs to that framework. - elseif (class_exists('\Drupal\simpletest\TestBase') && is_subclass_of($test_class, '\Drupal\simpletest\TestBase')) { + else { $test->dieOnFail = (bool) $args['die-on-fail']; $test->verbose = (bool) $args['verbose']; $test->run($methods); @@ -1521,7 +1515,7 @@ function simpletest_script_open_browser() { // Get the results form. $form = []; - RunTestsResultsBuilder::addResultForm($form, $results); + SimpletestResultsForm::addResultForm($form, $results); // Get the assets to make the details element collapsible and theme the result // form.