run-tests.sh File Reference

Backport of Drupal 7 run-tests.sh with modifications, see BACKPORT.txt. More...

Go to the source code of this file.

Enumerations

enum  SIMPLETEST_SCRIPT_COLOR_PASS
enum  SIMPLETEST_SCRIPT_COLOR_FAIL
enum  SIMPLETEST_SCRIPT_COLOR_EXCEPTION

Functions

 simpletest_script_help ()
 Print help text.
 simpletest_script_parse_args ()
 Parse execution argument and ensure that all are valid.
 simpletest_script_init ()
 Initialize script variables and perform general setup requirements.
 simpletest_script_execute_batch ()
 Execute a batch of tests.
 simpletest_script_run_one_test ($test_id, $test_class)
 Run a single test (assume a Drupal bootstrapped environment).
 simpletest_script_command ($concurrency, $test_id, $tests)
 Execute a command to run batch of tests in separate process.
 simpletest_script_get_test_list ()
 Get list of tests based on arguments.
 simpletest_script_reporter_init ()
 Initialize the reporter.
 simpletest_script_reporter_display_results ()
 Display test results.
 simpletest_script_format_result ($result)
 Format the result so that it fits within the default 80 character terminal size.
 simpletest_script_print_error ($message)
 Print error message prefixed with " ERROR: " and displayed in fail color if color output is enabled.
 simpletest_script_print ($message, $color_code)
 Print a message to the console, if color is enabled then the specified color code will be used.
 simpletest_script_color_code ($status)
 Get the color code associated with the specified status.

Variables

if(!module_exists('simpletest'))
if($args['clean']) 
$all_tests = simpletest_get_all_tests()
 $groups = simpletest_categorize_tests($all_tests)
 $test_list = array()
 $test_id = db_last_insert_id('simpletest_test_id', 'test_id')


Detailed Description

Backport of Drupal 7 run-tests.sh with modifications, see BACKPORT.txt.

This file must be placed in the Drupal scripts folder in order for it to work properly.

Copyright 2008-2009 by Jimmy Berry ("boombatower", http://drupal.org/user/214218)

Definition in file run-tests.sh.


Enumeration Type Documentation

Definition at line 15 of file run-tests.sh.

Definition at line 14 of file run-tests.sh.

Definition at line 13 of file run-tests.sh.


Function Documentation

simpletest_script_color_code ( status  ) 

Get the color code associated with the specified status.

Parameters:
$status The status string to get code for.
Returns:
Color code.

Definition at line 559 of file run-tests.sh.

00559                                                {
00560   switch ($status) {
00561     case 'pass':
00562       return SIMPLETEST_SCRIPT_COLOR_PASS;
00563     case 'fail':
00564       return SIMPLETEST_SCRIPT_COLOR_FAIL;
00565     case 'exception':
00566       return SIMPLETEST_SCRIPT_COLOR_EXCEPTION;
00567   }
00568   return 0; // Default formatting.
00569 }

simpletest_script_command ( concurrency,
test_id,
tests 
)

Execute a command to run batch of tests in separate process.

Definition at line 362 of file run-tests.sh.

00362                                                                    {
00363   global $args, $php;
00364 
00365   $command = "$php ./scripts/{$args['script']} --url {$args['url']}";
00366   if ($args['color']) {
00367     $command .= ' --color';
00368   }
00369   $command .= " --php " . escapeshellarg($php) . " --concurrency $concurrency --test-id $test_id --execute-batch $tests";
00370   passthru($command);
00371 }

simpletest_script_execute_batch (  ) 

Execute a batch of tests.

Definition at line 283 of file run-tests.sh.

References simpletest_script_command(), simpletest_script_print_error(), and simpletest_script_run_one_test().

00283                                            {
00284   global $args;
00285 
00286   if (is_null($args['test-id'])) {
00287     simpletest_script_print_error("--execute-batch should not be called interactively.");
00288     exit;
00289   }
00290   if ($args['concurrency'] == 1) {
00291     // Fallback to mono-threaded execution.
00292     if (count($args['test_names']) > 1) {
00293       foreach ($args['test_names'] as $test_class) {
00294         // Execute each test in its separate Drupal environment.
00295         simpletest_script_command(1, $args['test-id'], $test_class);
00296       }
00297       exit;
00298     }
00299     else {
00300       // Execute an individual test.
00301       $test_class = array_shift($args['test_names']);
00302       drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
00303       simpletest_script_run_one_test($args['test-id'], $test_class);
00304       exit;
00305     }
00306   }
00307   else {
00308     // Multi-threaded execution.
00309     $children = array();
00310     while (!empty($args['test_names']) || !empty($children)) {
00311       // Fork children safely since Drupal is not bootstrapped yet.
00312       while (count($children) < $args['concurrency']) {
00313         if (empty($args['test_names'])) break;
00314 
00315         $child = array();
00316         $child['test_class'] = $test_class = array_shift($args['test_names']);
00317         $child['pid'] = pcntl_fork();
00318         if (!$child['pid']) {
00319           // This is the child process, bootstrap and execute the test.
00320           drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
00321           simpletest_script_run_one_test($args['test-id'], $test_class);
00322           exit;
00323         }
00324         else {
00325           // Register our new child.
00326           $children[] = $child;
00327         }
00328       }
00329 
00330       // Wait for children every 200ms.
00331       usleep(200000);
00332 
00333       // Check if some children finished.
00334       foreach ($children as $cid => $child) {
00335         if (pcntl_waitpid($child['pid'], $status, WUNTRACED | WNOHANG)) {
00336           // This particular child exited.
00337           unset($children[$cid]);
00338         }
00339       }
00340     }
00341     exit;
00342   }
00343 }

simpletest_script_format_result ( result  ) 

Format the result so that it fits within the default 80 character terminal size.

Parameters:
$result The result object to format.

Definition at line 512 of file run-tests.sh.

References simpletest_script_color_code(), and simpletest_script_print().

00512                                                   {
00513   global $results_map, $color;
00514 
00515   $summary = sprintf("%-10.10s %-10.10s %-30.30s %-5.5s %-20.20s\n",
00516     $results_map[$result->status], $result->message_group, basename($result->file), $result->line, $result->caller);
00517 
00518   simpletest_script_print($summary, simpletest_script_color_code($result->status));
00519 
00520   $lines = explode("\n", wordwrap(trim(strip_tags($result->message)), 76));
00521   foreach ($lines as $line) {
00522     echo "    $line\n";
00523   }
00524 }

simpletest_script_get_test_list (  ) 

Get list of tests based on arguments.

If --all specified then returns all available tests, otherwise reads list of tests.

Will print error and exit if no valid tests were found.

Returns:
List of tests.

Definition at line 381 of file run-tests.sh.

References $all_tests, $groups, $test_list, and simpletest_script_print_error().

00381                                            {
00382   global $args, $all_tests, $groups;
00383 
00384   $test_list = array();
00385   if ($args['all']) {
00386     $test_list = $all_tests;
00387   }
00388   else {
00389     if ($args['class']) {
00390       // Check for valid class names.
00391       foreach ($args['test_names'] as $class_name) {
00392         if (in_array($class_name, $all_tests)) {
00393           $test_list[] = $class_name;
00394         }
00395       }
00396     }
00397     elseif ($args['file']) {
00398       $files = array();
00399       foreach ($args['test_names'] as $file) {
00400         $files[realpath($file)] = 1;
00401       }
00402 
00403       // Check for valid class names.
00404       foreach ($all_tests as $class_name => $info) {
00405         $refclass = new ReflectionClass($class_name);
00406         $file = $refclass->getFileName();
00407         if (isset($files[$file])) {
00408           $test_list[] = $class_name;
00409         }
00410       }
00411     }
00412     else {
00413       // Check for valid group names and get all valid classes in group.
00414       foreach ($args['test_names'] as $group_name) {
00415         if (isset($groups[$group_name])) {
00416           foreach($groups[$group_name] as $class_name => $info) {
00417             $test_list[] = $class_name;
00418           }
00419         }
00420       }
00421     }
00422   }
00423 
00424   if (empty($test_list)) {
00425     simpletest_script_print_error('No valid tests were specified.');
00426     exit;
00427   }
00428   return $test_list;
00429 }

simpletest_script_help (  ) 

Print help text.

Definition at line 95 of file run-tests.sh.

00095                                   {
00096   global $args;
00097 
00098   echo <<<EOF
00099 
00100 Run Drupal tests from the shell.
00101 
00102 Usage:        {$args['script']} [OPTIONS] <tests>
00103 Example:      {$args['script']} Profile
00104 
00105 All arguments are long options.
00106 
00107   --help      Print this page.
00108 
00109   --list      Display all available test groups.
00110 
00111   --clean     Cleans up database tables or directories from previous, failed,
00112               tests and then exits (no tests are run).
00113 
00114   --url       Immediately preceeds a URL to set the host and path. You will
00115               need this parameter if Drupal is in a subdirectory on your
00116               localhost and you have not set \$base_url in settings.php.
00117 
00118   --php       The absolute path to the PHP executable. Usually not needed.
00119 
00120   --concurrency [num]
00121 
00122               Run tests in parallel, up to [num] tests at a time. This requires
00123               the Process Control Extension (PCNTL) to be compiled in PHP, not
00124               supported under Windows.
00125 
00126   --all       Run all available tests.
00127 
00128   --class     Run tests identified by specific class names, instead of group names.
00129 
00130   --file      Run tests identified by specific file names, instead of group names.
00131               Specify the path and the extension (i.e. 'modules/user/user.test').
00132 
00133   --color     Output the results with color highlighting.
00134 
00135   --verbose   Output detailed assertion messages in addition to summary.
00136 
00137   <test1>[,<test2>[,<test3> ...]]
00138 
00139               One or more tests to be run. By default, these are interpreted
00140               as the names of test groups as shown at ?q=admin/build/testing.
00141               These group names typically correspond to module names like "User"
00142               or "Profile" or "System", but there is also a group "XML-RPC".
00143               If --class is specified then these are interpreted as the names of
00144               specific test classes whose test methods will be run. Tests must
00145               be separated by commas. Ignored if --all is specified.
00146 
00147 To run this script you will normally invoke it from the root directory of your
00148 Drupal installation as the webserver user (differs per configuration), or root:
00149 
00150 sudo -u [wwwrun|www-data|etc] php ./scripts/{$args['script']}
00151   --url http://example.com/ --all
00152 sudo -u [wwwrun|www-data|etc] php ./scripts/{$args['script']}
00153   --url http://example.com/ --class UploadTestCase
00154 \n
00155 EOF;
00156 }

simpletest_script_init (  ) 

Initialize script variables and perform general setup requirements.

Definition at line 233 of file run-tests.sh.

References simpletest_script_help(), and simpletest_script_print_error().

00233                                   {
00234   global $args, $php;
00235 
00236   $host = 'localhost';
00237   $path = '';
00238   // Determine location of php command automatically, unless a command line argument is supplied.
00239   if (!empty($args['php'])) {
00240     $php = $args['php'];
00241   }
00242   elseif (!empty($_ENV['_'])) {
00243     // '_' is an environment variable set by the shell. It contains the command that was executed.
00244     $php = $_ENV['_'];
00245   }
00246   elseif (!empty($_ENV['SUDO_COMMAND'])) {
00247     // 'SUDO_COMMAND' is an environment variable set by the sudo program.
00248     // Extract only the PHP interpreter, not the rest of the command.
00249     list($php, ) = explode(' ', $_ENV['SUDO_COMMAND'], 2);
00250   }
00251   else {
00252     simpletest_script_print_error('Unable to automatically determine the path to the PHP interpreter. Please supply the --php command line argument.');
00253     simpletest_script_help();
00254     exit();
00255   }
00256 
00257   // Get url from arguments.
00258   if (!empty($args['url'])) {
00259     $parsed_url = parse_url($args['url']);
00260     $host = $parsed_url['host'] . (isset($parsed_url['port']) ? ':' . $parsed_url['port'] : '');
00261     $path = $parsed_url['path'];
00262   }
00263 
00264   $_SERVER['HTTP_HOST'] = $host;
00265   $_SERVER['REMOTE_ADDR'] = '127.0.0.1';
00266   $_SERVER['SERVER_ADDR'] = '127.0.0.1';
00267   $_SERVER['SERVER_SOFTWARE'] = 'Apache';
00268   $_SERVER['SERVER_NAME'] = 'localhost';
00269   $_SERVER['REQUEST_URI'] = $path .'/';
00270   $_SERVER['REQUEST_METHOD'] = 'GET';
00271   $_SERVER['SCRIPT_NAME'] = $path .'/index.php';
00272   $_SERVER['PHP_SELF'] = $path .'/index.php';
00273   $_SERVER['HTTP_USER_AGENT'] = 'Drupal command line';
00274 
00275   chdir(realpath(dirname(__FILE__) . '/..'));
00276   define('DRUPAL_ROOT', getcwd());
00277   require_once DRUPAL_ROOT . '/includes/bootstrap.inc';
00278 }

simpletest_script_parse_args (  ) 

Parse execution argument and ensure that all are valid.

Returns:
The list of arguments.

Definition at line 163 of file run-tests.sh.

References simpletest_script_print_error().

00163                                         {
00164   // Set default values.
00165   $args = array(
00166     'script' => '',
00167     'help' => FALSE,
00168     'list' => FALSE,
00169     'clean' => FALSE,
00170     'url' => '',
00171     'php' => '',
00172     'concurrency' => 1,
00173     'all' => FALSE,
00174     'class' => FALSE,
00175     'file' => FALSE,
00176     'color' => FALSE,
00177     'verbose' => FALSE,
00178     'test_names' => array(),
00179     // Used internally.
00180     'test-id' => NULL,
00181     'execute-batch' => FALSE
00182   );
00183 
00184   // Override with set values.
00185   $args['script'] = basename(array_shift($_SERVER['argv']));
00186 
00187   $count = 0;
00188   while ($arg = array_shift($_SERVER['argv'])) {
00189     if (preg_match('/--(\S+)/', $arg, $matches)) {
00190       // Argument found.
00191       if (array_key_exists($matches[1], $args)) {
00192         // Argument found in list.
00193         $previous_arg = $matches[1];
00194         if (is_bool($args[$previous_arg])) {
00195           $args[$matches[1]] = TRUE;
00196         }
00197         else {
00198           $args[$matches[1]] = array_shift($_SERVER['argv']);
00199         }
00200         // Clear extraneous values.
00201         $args['test_names'] = array();
00202         $count++;
00203       }
00204       else {
00205         // Argument not found in list.
00206         simpletest_script_print_error("Unknown argument '$arg'.");
00207         exit;
00208       }
00209     }
00210     else {
00211       // Values found without an argument should be test names.
00212       $args['test_names'] += explode(',', $arg);
00213       $count++;
00214     }
00215   }
00216 
00217   // Validate the concurrency argument
00218   if (!is_numeric($args['concurrency']) || $args['concurrency'] <= 0) {
00219     simpletest_script_print_error("--concurrency must be a strictly positive integer.");
00220     exit;
00221   }
00222   elseif ($args['concurrency'] > 1 && !function_exists('pcntl_fork')) {
00223     simpletest_script_print_error("Parallel test execution requires the Process Control extension to be compiled in PHP. Please see http://php.net/manual/en/intro.pcntl.php for more information.");
00224     exit;
00225   }
00226 
00227   return array($args, $count);
00228 }

simpletest_script_print ( message,
color_code 
)

Print a message to the console, if color is enabled then the specified color code will be used.

Parameters:
$message The message to print.
$color_code The color code to use for coloring.

Definition at line 543 of file run-tests.sh.

00543                                                         {
00544   global $args;
00545   if ($args['color']) {
00546     echo "\033[" . $color_code . "m" . $message . "\033[0m";
00547   }
00548   else {
00549     echo $message;
00550   }
00551 }

simpletest_script_print_error ( message  ) 

Print error message prefixed with " ERROR: " and displayed in fail color if color output is enabled.

Parameters:
$message The message to print.

Definition at line 532 of file run-tests.sh.

References simpletest_script_print().

00532                                                  {
00533   simpletest_script_print("  ERROR: $message\n", SIMPLETEST_SCRIPT_COLOR_FAIL);
00534 }

simpletest_script_reporter_display_results (  ) 

Display test results.

Definition at line 467 of file run-tests.sh.

References $test_id, and simpletest_script_format_result().

00467                                                       {
00468   global $args, $test_id, $results_map;
00469 
00470   echo "\n";
00471   $end = timer_stop('run-tests');
00472   echo "Test run duration: " . format_interval($end['time'] / 1000);
00473   echo "\n";
00474 
00475   if ($args['verbose']) {
00476     // Report results.
00477     echo "Detailed test results:\n";
00478     echo "----------------------\n";
00479     echo "\n";
00480 
00481     $results_map = array(
00482       'pass' => 'Pass',
00483       'fail' => 'Fail',
00484       'exception' => 'Exception'
00485     );
00486 
00487 //    $results = db_query("SELECT * FROM {simpletest} WHERE test_id = :test_id ORDER BY test_class, message_id", array(':test_id' => $test_id));
00488     $results = db_query("SELECT * FROM {simpletest} WHERE test_id = %d ORDER BY test_class, message_id", $test_id);
00489 
00490     $test_class = '';
00491 //    foreach ($results as $result) {
00492     while ($result = db_fetch_object($results)) {
00493       if (isset($results_map[$result->status])) {
00494         if ($result->test_class != $test_class) {
00495           // Display test class every time results are for new test class.
00496           echo "\n\n---- $result->test_class ----\n\n\n";
00497           $test_class = $result->test_class;
00498         }
00499 
00500         simpletest_script_format_result($result);
00501       }
00502     }
00503   }
00504 }

simpletest_script_reporter_init (  ) 

Initialize the reporter.

Definition at line 434 of file run-tests.sh.

References $all_tests, and $test_list.

00434                                            {
00435   global $args, $all_tests, $test_list;
00436 
00437   echo "\n";
00438   echo "Drupal test run\n";
00439   echo "---------------\n";
00440   echo "\n";
00441 
00442   // Tell the user about what tests are to be run.
00443   if ($args['all']) {
00444     echo "All tests will run.\n\n";
00445   }
00446   else {
00447     echo "Tests to be run:\n";
00448     foreach ($test_list as $class_name) {
00449       $info = call_user_func(array($class_name, 'getInfo'));
00450       echo " - " . $info['name'] . ' (' . $class_name . ')' . "\n";
00451     }
00452     echo "\n";
00453   }
00454 
00455   echo "Test run started: " . format_date($_SERVER['REQUEST_TIME'], 'long') . "\n";
00456   timer_start('run-tests');
00457   echo "\n";
00458 
00459   echo "Test summary:\n";
00460   echo "-------------\n";
00461   echo "\n";
00462 }

simpletest_script_run_one_test ( test_id,
test_class 
)

Run a single test (assume a Drupal bootstrapped environment).

Definition at line 348 of file run-tests.sh.

References $test_id, _simpletest_format_summary_line(), simpletest_get_all_tests(), simpletest_script_color_code(), and simpletest_script_print().

00348                                                                {
00349   simpletest_get_all_tests();
00350   $test = new $test_class($test_id);
00351   $test->run();
00352   $info = $test->getInfo();
00353 
00354   $status = ((isset($test->results['#fail']) && $test->results['#fail'] > 0)
00355            || (isset($test->results['#exception']) && $test->results['#exception'] > 0) ? 'fail' : 'pass');
00356   simpletest_script_print($info['name'] . ' ' . _simpletest_format_summary_line($test->results) . "\n", simpletest_script_color_code($status));
00357 }


Variable Documentation

if (!module_exists('simpletest')) if ($args['clean']) $all_tests = simpletest_get_all_tests()

Definition at line 52 of file run-tests.sh.

$groups = simpletest_categorize_tests($all_tests)

Definition at line 53 of file run-tests.sh.

$test_id = db_last_insert_id('simpletest_test_id', 'test_id')

Definition at line 81 of file run-tests.sh.

if ($args['list']) $test_list = array()

Definition at line 54 of file run-tests.sh.


Generated on Thu May 28 14:44:20 2009 for SimpleTest-D6 by  doxygen 1.5.8