Spike PHPCoverage Details: simpletest.module

Line #FrequencySource Line
1 <?php
2 // $Id: simpletest.module,v 1.41 2008/04/03 19:57:15 boombatower Exp $
3 
4 /**
5  * Implementation of hook_help().
6  */
7 function simpletest_help($path, $arg) {
8   switch ($path) {
9     case 'admin/help#simpletest':
10       $output  = '<p>'. t('The SimpleTest module is a framework for running automated unit tests in Drupal. It can be used to verify a working state of Drupal before and after any code changes, or as a means for developers to write and execute tests for their modules. It integrates with the <a href="@simpletest-official">SimpleTest PHP library</a>.', array('@simpletest-official' => 'http://www.simpletest.org/')) .'</p>';
11       $output .= '<p>'. t('Visit <a href="@admin-simpletest">Administer >> Site building >> SimpleTest</a> to display a list of available tests. For comprehensive testing, select <em>all</em> tests, or individually select tests for more targeted testing. (Note: Selecting <em>all</em> tests may take several minutes to complete.)', array('@admin-simpletest' => url('admin/build/simpletest'))) .'</p>';
12       $output .= '<p>'. t('After the tests have run, a message will be displayed next to each test group indicating whether tests within it passed, failed, or had exceptions. A pass means that a test returned the expected results, while fail means that it did not. An exception normally indicates an error outside of the test, such as a PHP warning or notice. If there were fails or exceptions, the results are expanded, and the tests that had issues will be indicated in red or pink rows. Use these results to refine your code and tests until all tests return a pass.') .'</p>';
13       $output .= '<p>'. t('For more information on creating and modifying your own tests, see the <a href="@simpletest-api">SimpleTest API Documentation</a> in the Drupal handbook.', array('@simpletest-api' => 'http://drupal.org/simpletest')) .'</p>';
14       $output .= '<p>'. t('For more information, see the online handbook entry for <a href="@simpletest">SimpleTest module</a>.', array('@simpletest' => 'http://drupal.org/handbook/modules/simpletest')) .'</p>';
15       return $output;
16   }
17 }
18 
19 /**
20  * Implementation of hook_menu().
21  */
22 function simpletest_menu() {
23   $items['admin/build/simpletest'] = array(
24     'title' => 'Simpletest',
25     'page callback' => 'simpletest_entrypoint',
26     'description' => 'Run tests against Drupal core and your active modules. These tests help assure that your site code is working as designed.',
27     'access arguments' => array('administer unit tests'),
28   );
29   $items['admin/settings/simpletest'] = array(
30     'title' => 'Simpletest settings',
31     'description' => 'Configure unit testing framework.',
32     'page callback' => 'drupal_get_form',
33     'page arguments' => array('simpletest_settings'),
34     'access arguments' => array('access administration pages'),
35   );
36   return $items;
37 }
38 
39 /**
40  * Implementation of hook_perm().
41  */
42 function simpletest_perm() {
43   return array('administer unit tests');
44 }
45 
46 /**
47  * Try to load the simepletest
48  * @return boolean TRUE if the load succeeded
49  */
50 function simpletest_load() {
511  static $loaded;
521  if ($loaded) {
531    return true;
54   }
55   global $user;
56   if ($user->uid != 1) {
57     drupal_set_message(t('It is strongly suggested to run the tests with the first user!'));
58   }
59   $loaded = true;
60   if (!defined('SIMPLE_TEST')) {
61     define('SIMPLE_TEST', drupal_get_path('module', 'simpletest') .'/simpletest');
62   }
63   if (!is_dir(SIMPLE_TEST)) {
64     return simpletest_trigger_error('not available');
65   }
66 
67   // We currently use only the web tester that DrupalTestCase is built upon
68   require_once(SIMPLE_TEST .'/unit_tester.php');
69   require_once(SIMPLE_TEST .'/reporter.php');
70   require_once('drupal_reporter.php');
71 
72   if (version_compare(SimpleTest::getVersion(), '1.0.1beta2') < 0) {
73     return simpletest_trigger_error('stale version');
74   }
75 
76   $path = drupal_get_path('module', 'simpletest') .'/';
77   require_once($path .'drupal_test_case.php');
78   require_once($path .'drupal_unit_tests.php');
79   return true;
80 }
81 
82 /**
83  * Menu callback for both running tests and listing possible tests
84  */
85 function simpletest_entrypoint() {
86   global $simpletest_ua_key;
87   if (!simpletest_load()) {
88      // @TODO - Find a better way for this return.  It is currently needed to show error,
89      // and returning true leads to page not found
90     return '&nbsp;';
91   }
92   if (!$simpletest_ua_key) {
93     $output = t('Please add the following code to the bottom of settings.php');
94     $output .=
95 '<p><code><pre>$GLOBALS["simpletest_ua_key"] = '. mt_rand(1000, 1000000) .';
96 if (preg_match("/^(simpletest\d+),(\d+)/", $_SERVER["HTTP_USER_AGENT"], $matches) && $GLOBALS["simpletest_ua_key"] == $matches[2]) {
97   $db_prefix = $matches[1];
98 }</pre></code></p>';
99     return $output;
100   }
101   drupal_add_js(drupal_get_path('module', 'simpletest') .'/simpletest.js', 'module');
102   $output = drupal_get_form('simpletest_overview_form');
103 
104   if (simpletest_running_output()) {
105     return simpletest_running_output() . $output;
106   }
107   else {
108     return $output;
109   }
110 }
111 
112 function simpletest_running_output($output = NULL) {
113   static $o;
114   if ($output != NULL) {
115     $o = $output;
116   }
117   return $o;
118 }
119 
120 /**
121  * FAPI form submit for simpletest_overview_form
122  *
123  * @param $form
124  * @param $form_state
125  */
126 function simpletest_overview_form_submit($form, &$form_state) {
127   $form_state['redirect'] = FALSE;
128   $output = '';
129   switch ($form_state['values']['running_options']) {
130     case 'all_tests':
131       $output = simpletest_run_tests();
132       break;
133     case 'selected_tests':
134       $tests_list = array();
135       foreach ($form_state['values'] as $item => $value) {
136         if ($value === 1 && strpos($item, 'selectall') === FALSE) {
137           $tests_list[] = $item;
138         }
139       }
140       if (count($tests_list) > 0 ) {
141         $output = simpletest_run_tests($tests_list);
142         break;
143       }
144       // Fall through
145     default:
146       simpletest_trigger_error('no tests selected');
147   }
148 
149   simpletest_running_output($output);
150   return FALSE;
151 }
152 
153 /**
154  * Form callback;  make the form to run tests
155  */
156 function simpletest_overview_form() {
157   $output = array();
158 
159   $total_test = &simpletest_get_total_test();
160 
161   $test_instances = $total_test->getTestInstances();
162   foreach ($test_instances as $group_test) {
163     $group = array();
164     $tests = $group_test->getTestInstances();
165     $group_class = str_replace(' ', '-', strtolower($group_test->getLabel()));
166     $group['tests'] = array(
167       '#type' => 'fieldset',
168       '#collapsible' => TRUE,
169       '#collapsed' => TRUE,
170       '#title' => 'Tests',
171       '#attributes' => array('class' => $group_class),
172     );
173     foreach ($tests as $test) {
174       $test_info = $test->getInfo();
175       $group['tests'][get_class($test)] = array(
176         '#type' => 'checkbox',
177         '#title' => $test_info['name'],
178         '#default_value' => 0,
179         '#description' => $test_info['description'],
180       );
181     }
182     $output[] = $group + array(
183       '#type' => 'fieldset',
184       '#collapsible' => FALSE,
185       '#title' => $group_test->getLabel(),
186       '#attributes' => array('class' => 'select_all'),
187     );
188   }
189 
190   $submit['running_options'] = array(
191     '#type' => 'radios',
192     '#default_value' => 'selected_tests',
193     '#options' => array(
194       'all_tests' => t('Run all tests (WARNING, this may take a long time)'),
195       'selected_tests' => t('Run selected tests'),
196     ),
197   );
198   $submit['op'] = array(
199     '#type' => 'submit',
200     '#value' => t('Begin'),
201   );
202 
203   $output[] = $submit + array(
204     '#type' => 'fieldset',
205     '#collapsible' => FALSE,
206     '#collapsed' => FALSE,
207     '#title' => 'Run tests',
208   );
209   return $output;
210 }
211 
212 /**
213  * Actually runs tests
214  * @param array $testlist list of tests to run or DEFAULT NULL run all tests
215  * @param boolean $html_reporter true if you want results in simple html, FALSE for full drupal page
216  */
217 function simpletest_run_tests($testlist = NULL, $reporter = 'drupal') {
218   static $test_running;
219   if (!$test_running) {
220     $file = drupal_get_path('module', 'simpletest') .'/spikephpcoverage';
221     $coverage = (file_exists($file) && is_dir($file));
222     if ($coverage) {
223       if (!defined('PHPCOVERAGE_HOME')) {
224         define('PHPCOVERAGE_HOME', $file .'/src'); 
225       }
226 
227       require_once PHPCOVERAGE_HOME .'/CoverageRecorder.php';
228       require_once PHPCOVERAGE_HOME .'/reporter/HtmlCoverageReporter.php';
229 
230       $coverage_reporter = new HtmlCoverageReporter("Code Coverage Report", '', drupal_get_path('module', 'simpletest') .'/coverage_results/'. time());
231 
232       $includePaths = array('.');
233       $excludePaths = array();
234       $cov = new CoverageRecorder($includePaths, $excludePaths, $coverage_reporter);
235 
236       $cov->startInstrumentation();
237     }
2381    $test_running = TRUE;
2391    $test = simpletest_get_total_test($testlist);
240     switch ($reporter) {
2411      case 'text':
242         $reporter = &new TextReporter();
243         break;
2441      case 'xml':
245         $reporter = &new XMLReporter();
246         break;
2471      case 'html':
248         $reporter = &new HtmlReporter();
249         break;
2501      case 'drupal':
2511        $reporter = &new DrupalReporter();
2521        break;
253     }
254 
2551    cache_clear_all();
2561    $results = $test->run($reporter);
2571    $test_running = FALSE;
258 
2591    if ($coverage) {
2601      $cov->stopInstrumentation();
261       $cov->generateReport();
262       $coverage_reporter->printTextSummary();
263     }
264 
265     switch (get_class($reporter)) {
266       case 'TextReporter':
267       case 'XMLReporter':
268       case 'HtmlReporter':
269         return $results;
270       case 'DrupalReporter':
271         return $reporter->getOutput();
272     }
273   }
274 }
275 
276 /**
277  * This function makes sure no unnecessary copies of the DrupalUnitTests object are instantiated
278  * @param  array $classes list of all classes the test should concern or
279  *                        DEFAULT NULL
280  * @return DrupalUnitTests object
281  */
282 function &simpletest_get_total_test($classes = NULL) {
2831  static $total_test;
2841  if (!$total_test) {
2851    if (!simpletest_load()) {
286       return FALSE;
287     }
2881    $total_test = &new DrupalUnitTests();
289   }
2901  if (!is_null($classes)) {
2911    $dut = new DrupalUnitTests($classes);
2921    return $dut;
293   }
294   return $total_test;
295 }
296 
297 function simpletest_settings() {
298   $form = array();
299 
300   $form['http_auth'] = array(
301     '#type' => 'fieldset',
302     '#title' => t('HTTP authentication'),
303     '#description' => t('If needed, enter a username and password for reaching your web site. This is not a drupal username/password.') .
304                       t('This is a login presented by your web server. Most sites may leave this section empty.'),
305   );
306   $form['http_auth']['simpletest_httpauth'] = array(
307     '#type' => 'checkbox',
308     '#title' => t('Use http authentication'),
309     '#default_value' => variable_get('simpletest_httpauth', false),
310   );
311   $form['http_auth']['simpletest_httpauth_username'] = array(
312     '#type' => 'textfield',
313     '#title' => t('Username'),
314     '#default_value' => variable_get('simpletest_httpauth_username', ''),
315   );
316   $form['http_auth']['simpletest_httpauth_pass'] = array(
317     '#title' => t('Password'),
318     '#type' => 'password',
319     '#default_value' => variable_get('simpletest_httpauth_pass', ''),
320   );
321   $form['devel'] = array(
322     '#type' => 'fieldset',
323     '#title' => t('Devel module settings'),
324     '#description' => t('Devel module can cause problems if you have query log enabled. It will output a few thousand queries and crash your browser'),
325   );
326   $form['devel']['simpletest_devel'] = array(
327     '#type' => 'checkbox',
328     '#title' => t('Use devel query log on test result pages'),
329     '#default_value' => variable_get('simpletest_devel', false),
330   );
331 
332   return system_settings_form($form);
333 
334 }
335 
336 function simpletest_trigger_error($type) {
337   switch ($type) {
338     case 'not available':
339       $output = t('The simpletest framework cannot be found in the current installation. Please note that simpletest.module needs Simpletest framework to be installed. ');
340       $output .= t('Please download it from !simpletest_link and place it into the same directory as simpletest.module: %simpletest_directory', array('!simpletest_link' => l('Simpletest on SourceForge', 'https://sourceforge.net/project/showfiles.php?group_id=76550'), '%simpletest_directory' => SIMPLE_TEST));
341       drupal_set_message($output, 'error');
342       break;
343     case 'stale version':
344       $output = t('Due to a lot of refactoring done on simpletest library side. Simpletest module is not compatible with Simpletest versions lower than 1.0.1 beta2. ');
345       $output .= t('Please download the latest version from !simpletest_link and place it into the same directory as simpletest.module: %simpletest_directory', array('!simpletest_link' => l('Simpletest on SourceForge', 'https://sourceforge.net/project/showfiles.php?group_id=76550'), '%simpletest_directory' => SIMPLE_TEST));
346       drupal_set_message($output, 'error');
347       break;
348     case 'no tests selected':
349       drupal_set_message(t('No test has been selected.'), 'error');
350   }
351   return false;
352 }