'fieldset', '#title' => t('Tests'), '#description' => t('Select the test(s) or test group(s) you would like to run, and click Run tests.'), ); $form['tests']['table'] = array( '#theme' => 'simpletest_test_table', ); // Generate the list of tests arranged by group. $groups = simpletest_test_get_all(); foreach ($groups as $group => $tests) { $form['tests']['table'][$group] = array( '#collapsed' => TRUE, ); foreach ($tests as $class => $info) { $form['tests']['table'][$group][$class] = array( '#type' => 'checkbox', '#title' => $info['name'], '#description' => $info['description'], ); } } // Operation buttons. $form['tests']['op'] = array( '#type' => 'submit', '#value' => t('Run tests'), ); $form['clean'] = array( '#type' => 'fieldset', '#collapsible' => FALSE, '#collapsed' => FALSE, '#title' => t('Clean test environment'), '#description' => t('Remove tables with the prefix "simpletest" and temporary directories that are left over from tests that crashed. This is intended for developers when creating tests.'), ); $form['clean']['op'] = array( '#type' => 'submit', '#value' => t('Clean environment'), '#submit' => array('simpletest_clean_environment'), ); return $form; } /** * Theme the test list generated by simpletest_test_form() into a table. * * @param $table Form array that represent a table. * @return HTML output. */ function theme_simpletest_test_table($table) { drupal_add_css(drupal_get_path('module', 'simpletest') . '/simpletest.css'); drupal_add_js(drupal_get_path('module', 'simpletest') . '/simpletest.js'); // Create header for test selection table. $header = array( theme('table_select_header_cell'), array('data' => t('Test'), 'class' => 'simpletest_test'), array('data' => t('Description'), 'class' => 'simpletest_description'), ); // Define the images used to expand/collapse the test groups. $js = array( 'images' => array( theme('image', 'misc/menu-collapsed.png', 'Expand', 'Expand'), theme('image', 'misc/menu-expanded.png', 'Collapsed', 'Collapsed'), ), ); // Cycle through each test group and create a row. $rows = array(); foreach (element_children($table) as $key) { $element = &$table[$key]; $row = array(); // Make the class name safe for output on the page by replacing all // non-word/decimal characters with a dash (-). $test_class = strtolower(trim(preg_replace("/[^\w\d]/", "-", $key))); // Select the right "expand"/"collapse" image, depending on whether the // category is expanded (at least one test selected) or not. $collapsed = !empty($element['#collapsed']); $image_index = $collapsed ? 0 : 1; // Place-holder for checkboxes to select group of tests. $row[] = array('id' => $test_class, 'class' => 'simpletest-select-all'); // Expand/collapse image and group title. $row[] = array( 'data' => '
 ' . '', 'style' => 'font-weight: bold;' ); $row[] = ' '; $rows[] = array('data' => $row, 'class' => 'simpletest-group'); // Add individual tests to group. $current_js = array( 'testClass' => $test_class . '-test', 'testNames' => array(), 'imageDirection' => $image_index, 'clickActive' => FALSE, ); // Cycle through each test within the current group. foreach (element_children($element) as $test_name) { $test = $element[$test_name]; $row = array(); $current_js['testNames'][] = 'edit-' . $test_name; // Store test title and description so that checkbox won't render them. $title = $test['#title']; $description = $test['#description']; unset($test['#title']); unset($test['#description']); // Test name is used to determine what tests to run. $test['#name'] = $test_name; $row[] = drupal_render($test); $row[] = theme('indentation', 1) . ''; $row[] = '
' . $description . '
'; $rows[] = array('data' => $row, 'class' => $test_class . '-test' . ($collapsed ? ' js-hide' : '')); } $js['simpletest-test-group-' . $test_class] = $current_js; unset($table[$key]); } // Add js array of settings. drupal_add_js(array('simpleTest' => $js), 'setting'); if (empty($rows)) { return '' . t('No tests to display.') . ''; } else { return theme('table', $header, $rows, array('id' => 'simpletest-form-table')); } } /** * Run selected tests. */ function simpletest_test_form_submit($form, &$form_state) { // Get list of tests. $tests_list = array(); foreach ($form_state['values'] as $class_name => $value) { if (class_exists($class_name) && $value === 1) { $tests_list[] = $class_name; } } if (count($tests_list) > 0 ) { simpletest_run_tests($tests_list, 'drupal'); } else { drupal_set_message(t('No test(s) selected.'), 'error'); } } /** * Test results form for $test_id. */ function simpletest_result_form(&$form_state, $test_id) { $form = array(); // Make sure there are test results to display and a re-run is not being performed. $results = array(); if (is_numeric($test_id) && !$results = simpletest_result_get($test_id)) { drupal_set_message(t('No test results to display.'), 'error'); drupal_goto('admin/development/testing'); return $form; } // Load all classes and include CSS. drupal_add_css(drupal_get_path('module', 'simpletest') . '/simpletest.css'); // Keep track of which test cases passed or failed. $filter = array( 'pass' => array(), 'fail' => array(), ); // Summary result fieldset. $form['result'] = array( '#type' => 'fieldset', '#title' => t('Results'), ); $form['result']['summary'] = $summary = array( '#theme' => 'simpletest_result_summary', '#pass' => 0, '#fail' => 0, '#exception' => 0, ); // Cycle through each test group. $header = array(t('Message'), t('Group'), t('Filename'), t('Line'), t('Function'), array('colspan' => 2, 'data' => t('Status'))); $form['result']['results'] = array(); foreach ($results as $group => $assertions) { // Create group fieldset with summary information. $info = call_user_func(array($group, 'getInfo')); $form['result']['results'][$group] = array( '#type' => 'fieldset', '#title' => $info['name'], '#description' => $info['description'], '#collapsible' => TRUE, ); $form['result']['results'][$group]['summary'] = $summary; $group_summary = &$form['result']['results'][$group]['summary']; // Create table of assertions for the group. $rows = array(); foreach ($assertions as $assertion) { $row = array(); $row[] = $assertion->message; $row[] = $assertion->message_group; $row[] = basename($assertion->file); $row[] = $assertion->line; $row[] = $assertion->function; $row[] = simpletest_result_status_image($assertion->status); $rows[] = array('data' => $row, 'class' => 'simpletest-' . $assertion->status); $group_summary['#' . $assertion->status]++; $form['result']['summary']['#' . $assertion->status]++; } $form['result']['results'][$group]['table'] = array( '#markup' => theme('table', $header, $rows), ); // Set summary information. $group_summary['#ok'] = $group_summary['#fail'] + $group_summary['#exception'] == 0; $form['result']['results'][$group]['#collapsed'] = $group_summary['#ok']; // Store test group (class) as for use in filter. $filter[$group_summary['#ok'] ? 'pass' : 'fail'][] = $group; } // Overal summary status. $form['result']['summary']['#ok'] = $form['result']['summary']['#fail'] + $form['result']['summary']['#exception'] == 0; // Actions. $form['#action'] = url('admin/development/testing/results/re-run'); $form['action'] = array( '#type' => 'fieldset', '#title' => t('Actions'), '#attributes' => array('class' => 'container-inline'), '#weight' => -11, ); $form['action']['filter'] = array( '#type' => 'select', '#title' => 'Filter', '#options' => array( 'all' => t('All (@count)', array('@count' => count($filter['pass']) + count($filter['fail']))), 'pass' => t('Pass (@count)', array('@count' => count($filter['pass']))), 'fail' => t('Fail (@count)', array('@count' => count($filter['fail']))), ), ); $form['action']['filter']['#default_value'] = ($filter['fail'] ? 'fail' : 'all'); // Catagorized test classes for to be used with selected filter value. $form['action']['filter_pass'] = array( '#type' => 'hidden', '#default_value' => implode(',', $filter['pass']), ); $form['action']['filter_fail'] = array( '#type' => 'hidden', '#default_value' => implode(',', $filter['fail']), ); $form['action']['op'] = array( '#type' => 'submit', '#value' => t('Run tests'), ); $form['action']['return'] = array( '#markup' => l(t('Return to list'), 'admin/development/testing'), ); if (is_numeric($test_id)) { simpletest_clean_results_table($test_id); } return $form; } /** * Re-run the tests that match the filter. */ function simpletest_result_form_submit($form, &$form_state) { $pass = $form_state['values']['filter_pass'] ? explode(',', $form_state['values']['filter_pass']) : array(); $fail = $form_state['values']['filter_fail'] ? explode(',', $form_state['values']['filter_fail']) : array(); if ($form_state['values']['filter'] == 'all') { $classes = array_merge($pass, $fail); } else if ($form_state['values']['filter'] == 'pass') { $classes = $pass; } else { $classes = $fail; } if (!$classes) { $form_state['redirect'] = 'admin/development/testing'; return; } $form_state_execute = array('values' => array()); foreach ($classes as $class) { $form_state_execute['values'][$class] = 1; } simpletest_test_form_submit(array(), $form_state_execute); } /** * Add wrapper div with class based on summary status. * * @return HTML output. */ function theme_simpletest_result_summary($form) { return '
' . _simpletest_format_summary_line($form) . '
'; } /** * Get test results for $test_id. * * @param $test_id The test_id to retrieve results of. * @return Array of results grouped by test_class. */ function simpletest_result_get($test_id) { $results = db_select('simpletest') ->fields('simpletest') ->condition('test_id', $test_id) ->orderBy('test_class') ->orderBy('message_id') ->execute(); $test_results = array(); foreach ($results as $result) { if (!isset($test_results[$result->test_class])) { $test_results[$result->test_class] = array(); } $test_results[$result->test_class][] = $result; } return $test_results; } /** * Get the appropriate image for the status. * * @param $status Status string, either: pass, fail, exception. * @return HTML image or false. */ function simpletest_result_status_image($status) { static $map; if (!isset($map)) { $map = array( 'pass' => theme('image', 'misc/watchdog-ok.png'), 'fail' => theme('image', 'misc/watchdog-error.png'), 'exception' => theme('image', 'misc/watchdog-warning.png'), ); } if (isset($map[$status])) { return $map[$status]; } return FALSE; }