Merge branch 'MDL-39444_23' of git://github.com/timhunt/moodle into MOODLE_23_STABLE
[moodle.git] / lib / simpletestlib / simpletest.php
blob425c869a8253dd7b768b7bbf65b3ae2f78a940ec
1 <?php
2 /**
3 * Global state for SimpleTest and kicker script in future versions.
4 * @package SimpleTest
5 * @subpackage UnitTester
6 * @version $Id: simpletest.php 2011 2011-04-29 08:22:48Z pp11 $
7 */
9 /**#@+
10 * include SimpleTest files
12 require_once(dirname(__FILE__) . '/reflection_php5.php');
13 require_once(dirname(__FILE__) . '/default_reporter.php');
14 require_once(dirname(__FILE__) . '/compatibility.php');
15 /**#@-*/
17 /**
18 * Registry and test context. Includes a few
19 * global options that I'm slowly getting rid of.
20 * @package SimpleTest
21 * @subpackage UnitTester
23 class SimpleTest {
25 /**
26 * Reads the SimpleTest version from the release file.
27 * @return string Version string.
29 static function getVersion() {
30 $content = file(dirname(__FILE__) . '/VERSION');
31 return trim($content[0]);
34 /**
35 * Sets the name of a test case to ignore, usually
36 * because the class is an abstract case that should
37 * @param string $class Add a class to ignore.
39 static function ignore($class) {
40 $registry = &SimpleTest::getRegistry();
41 $registry['IgnoreList'][strtolower($class)] = true;
44 /**
45 * Scans the now complete ignore list, and adds
46 * all parent classes to the list. If a class
47 * is not a runnable test case, then it's parents
48 * wouldn't be either. This is syntactic sugar
49 * to cut down on ommissions of ignore()'s or
50 * missing abstract declarations. This cannot
51 * be done whilst loading classes wiithout forcing
52 * a particular order on the class declarations and
53 * the ignore() calls. It's just nice to have the ignore()
54 * calls at the top of the file before the actual declarations.
55 * @param array $classes Class names of interest.
57 static function ignoreParentsIfIgnored($classes) {
58 $registry = &SimpleTest::getRegistry();
59 foreach ($classes as $class) {
60 if (SimpleTest::isIgnored($class)) {
61 $reflection = new SimpleReflection($class);
62 if ($parent = $reflection->getParent()) {
63 SimpleTest::ignore($parent);
69 /**
70 * Puts the object to the global pool of 'preferred' objects
71 * which can be retrieved with SimpleTest :: preferred() method.
72 * Instances of the same class are overwritten.
73 * @param object $object Preferred object
74 * @see preferred()
76 static function prefer($object) {
77 $registry = &SimpleTest::getRegistry();
78 $registry['Preferred'][] = $object;
81 /**
82 * Retrieves 'preferred' objects from global pool. Class filter
83 * can be applied in order to retrieve the object of the specific
84 * class
85 * @param array|string $classes Allowed classes or interfaces.
86 * @return array|object|null
87 * @see prefer()
89 static function preferred($classes) {
90 if (! is_array($classes)) {
91 $classes = array($classes);
93 $registry = &SimpleTest::getRegistry();
94 for ($i = count($registry['Preferred']) - 1; $i >= 0; $i--) {
95 foreach ($classes as $class) {
96 if (SimpleTestCompatibility::isA($registry['Preferred'][$i], $class)) {
97 return $registry['Preferred'][$i];
101 return null;
105 * Test to see if a test case is in the ignore
106 * list. Quite obviously the ignore list should
107 * be a separate object and will be one day.
108 * This method is internal to SimpleTest. Don't
109 * use it.
110 * @param string $class Class name to test.
111 * @return boolean True if should not be run.
113 static function isIgnored($class) {
114 $registry = &SimpleTest::getRegistry();
115 return isset($registry['IgnoreList'][strtolower($class)]);
119 * Sets proxy to use on all requests for when
120 * testing from behind a firewall. Set host
121 * to false to disable. This will take effect
122 * if there are no other proxy settings.
123 * @param string $proxy Proxy host as URL.
124 * @param string $username Proxy username for authentication.
125 * @param string $password Proxy password for authentication.
127 static function useProxy($proxy, $username = false, $password = false) {
128 $registry = &SimpleTest::getRegistry();
129 $registry['DefaultProxy'] = $proxy;
130 $registry['DefaultProxyUsername'] = $username;
131 $registry['DefaultProxyPassword'] = $password;
135 * Accessor for default proxy host.
136 * @return string Proxy URL.
138 static function getDefaultProxy() {
139 $registry = &SimpleTest::getRegistry();
140 return $registry['DefaultProxy'];
144 * Accessor for default proxy username.
145 * @return string Proxy username for authentication.
147 static function getDefaultProxyUsername() {
148 $registry = &SimpleTest::getRegistry();
149 return $registry['DefaultProxyUsername'];
153 * Accessor for default proxy password.
154 * @return string Proxy password for authentication.
156 static function getDefaultProxyPassword() {
157 $registry = &SimpleTest::getRegistry();
158 return $registry['DefaultProxyPassword'];
162 * Accessor for default HTML parsers.
163 * @return array List of parsers to try in
164 * order until one responds true
165 * to can().
167 static function getParsers() {
168 $registry = &SimpleTest::getRegistry();
169 return $registry['Parsers'];
173 * Set the list of HTML parsers to attempt to use by default.
174 * @param array $parsers List of parsers to try in
175 * order until one responds true
176 * to can().
178 static function setParsers($parsers) {
179 $registry = &SimpleTest::getRegistry();
180 $registry['Parsers'] = $parsers;
184 * Accessor for global registry of options.
185 * @return hash All stored values.
187 protected static function &getRegistry() {
188 static $registry = false;
189 if (! $registry) {
190 $registry = SimpleTest::getDefaults();
192 return $registry;
196 * Accessor for the context of the current
197 * test run.
198 * @return SimpleTestContext Current test run.
200 static function getContext() {
201 static $context = false;
202 if (! $context) {
203 $context = new SimpleTestContext();
205 return $context;
209 * Constant default values.
210 * @return hash All registry defaults.
212 protected static function getDefaults() {
213 return array(
214 'Parsers' => false,
215 'MockBaseClass' => 'SimpleMock',
216 'IgnoreList' => array(),
217 'DefaultProxy' => false,
218 'DefaultProxyUsername' => false,
219 'DefaultProxyPassword' => false,
220 'Preferred' => array(new HtmlReporter(), new TextReporter(), new XmlReporter()));
224 * @deprecated
226 static function setMockBaseClass($mock_base) {
227 $registry = &SimpleTest::getRegistry();
228 $registry['MockBaseClass'] = $mock_base;
232 * @deprecated
234 static function getMockBaseClass() {
235 $registry = &SimpleTest::getRegistry();
236 return $registry['MockBaseClass'];
241 * Container for all components for a specific
242 * test run. Makes things like error queues
243 * available to PHP event handlers, and also
244 * gets around some nasty reference issues in
245 * the mocks.
246 * @package SimpleTest
248 class SimpleTestContext {
249 private $test;
250 private $reporter;
251 private $resources;
254 * Clears down the current context.
255 * @access public
257 function clear() {
258 $this->resources = array();
262 * Sets the current test case instance. This
263 * global instance can be used by the mock objects
264 * to send message to the test cases.
265 * @param SimpleTestCase $test Test case to register.
267 function setTest($test) {
268 $this->clear();
269 $this->test = $test;
273 * Accessor for currently running test case.
274 * @return SimpleTestCase Current test.
276 function getTest() {
277 return $this->test;
281 * Sets the current reporter. This
282 * global instance can be used by the mock objects
283 * to send messages.
284 * @param SimpleReporter $reporter Reporter to register.
286 function setReporter($reporter) {
287 $this->clear();
288 $this->reporter = $reporter;
292 * Accessor for current reporter.
293 * @return SimpleReporter Current reporter.
295 function getReporter() {
296 return $this->reporter;
300 * Accessor for the Singleton resource.
301 * @return object Global resource.
303 function get($resource) {
304 if (! isset($this->resources[$resource])) {
305 $this->resources[$resource] = new $resource();
307 return $this->resources[$resource];
312 * Interrogates the stack trace to recover the
313 * failure point.
314 * @package SimpleTest
315 * @subpackage UnitTester
317 class SimpleStackTrace {
318 private $prefixes;
321 * Stashes the list of target prefixes.
322 * @param array $prefixes List of method prefixes
323 * to search for.
325 function __construct($prefixes) {
326 $this->prefixes = $prefixes;
330 * Extracts the last method name that was not within
331 * Simpletest itself. Captures a stack trace if none given.
332 * @param array $stack List of stack frames.
333 * @return string Snippet of test report with line
334 * number and file.
336 function traceMethod($stack = false) {
337 $stack = $stack ? $stack : $this->captureTrace();
338 foreach ($stack as $frame) {
339 if ($this->frameLiesWithinSimpleTestFolder($frame)) {
340 continue;
342 if ($this->frameMatchesPrefix($frame)) {
343 return ' at [' . $frame['file'] . ' line ' . $frame['line'] . ']';
346 return '';
350 * Test to see if error is generated by SimpleTest itself.
351 * @param array $frame PHP stack frame.
352 * @return boolean True if a SimpleTest file.
354 protected function frameLiesWithinSimpleTestFolder($frame) {
355 if (isset($frame['file'])) {
356 $path = substr(SIMPLE_TEST, 0, -1);
357 if (strpos($frame['file'], $path) === 0) {
358 if (dirname($frame['file']) == $path) {
359 return true;
363 return false;
367 * Tries to determine if the method call is an assert, etc.
368 * @param array $frame PHP stack frame.
369 * @return boolean True if matches a target.
371 protected function frameMatchesPrefix($frame) {
372 foreach ($this->prefixes as $prefix) {
373 if (strncmp($frame['function'], $prefix, strlen($prefix)) == 0) {
374 return true;
377 return false;
381 * Grabs a current stack trace.
382 * @return array Fulle trace.
384 protected function captureTrace() {
385 if (function_exists('debug_backtrace')) {
386 return array_reverse(debug_backtrace());
388 return array();