blob: 60b046ba036d028fd3989aa60c99049d5cb5ee44 [file] [log] [blame]
Andrey Andreevc5536aa2012-11-01 17:33:58 +02001<?php
Derek Allard2067d1a2008-11-13 22:59:24 +00002/**
3 * CodeIgniter
4 *
Andrey Andreevfe9309d2015-01-09 17:48:58 +02005 * An open source application development framework for PHP
Derek Allard2067d1a2008-11-13 22:59:24 +00006 *
Andrey Andreevbdb96ca2014-10-28 00:13:31 +02007 * This content is released under the MIT License (MIT)
Andrey Andreev2a27d312011-12-25 17:08:24 +02008 *
Andrey Andreevfe9309d2015-01-09 17:48:58 +02009 * Copyright (c) 2014 - 2015, British Columbia Institute of Technology
Andrey Andreev2a27d312011-12-25 17:08:24 +020010 *
Andrey Andreevbdb96ca2014-10-28 00:13:31 +020011 * Permission is hereby granted, free of charge, to any person obtaining a copy
12 * of this software and associated documentation files (the "Software"), to deal
13 * in the Software without restriction, including without limitation the rights
14 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 * copies of the Software, and to permit persons to whom the Software is
16 * furnished to do so, subject to the following conditions:
Derek Jonesf4a4bd82011-10-20 12:18:42 -050017 *
Andrey Andreevbdb96ca2014-10-28 00:13:31 +020018 * The above copyright notice and this permission notice shall be included in
19 * all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27 * THE SOFTWARE.
28 *
29 * @package CodeIgniter
30 * @author EllisLab Dev Team
darwinel871754a2014-02-11 17:34:57 +010031 * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)
Andrey Andreevfe9309d2015-01-09 17:48:58 +020032 * @copyright Copyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)
Andrey Andreevbdb96ca2014-10-28 00:13:31 +020033 * @license http://opensource.org/licenses/MIT MIT License
34 * @link http://codeigniter.com
35 * @since Version 1.3.1
Derek Allard2067d1a2008-11-13 22:59:24 +000036 * @filesource
37 */
Andrey Andreevc5536aa2012-11-01 17:33:58 +020038defined('BASEPATH') OR exit('No direct script access allowed');
Derek Allard2067d1a2008-11-13 22:59:24 +000039
Derek Allard2067d1a2008-11-13 22:59:24 +000040/**
41 * Unit Testing Class
42 *
43 * Simple testing class
44 *
45 * @package CodeIgniter
46 * @subpackage Libraries
47 * @category UnitTesting
Derek Jonesf4a4bd82011-10-20 12:18:42 -050048 * @author EllisLab Dev Team
Gerry33c9c3f2011-09-25 00:32:38 +080049 * @link http://codeigniter.com/user_guide/libraries/unit_testing.html
Derek Allard2067d1a2008-11-13 22:59:24 +000050 */
51class CI_Unit_test {
52
Andrey Andreev597ea272012-11-01 22:56:26 +020053 /**
54 * Active flag
55 *
56 * @var bool
57 */
Andrey Andreev5fd3ae82012-10-24 14:55:35 +030058 public $active = TRUE;
Andrey Andreev597ea272012-11-01 22:56:26 +020059
60 /**
61 * Test results
62 *
63 * @var array
64 */
Andrey Andreev5fd3ae82012-10-24 14:55:35 +030065 public $results = array();
Andrey Andreev597ea272012-11-01 22:56:26 +020066
67 /**
68 * Strict comparison flag
69 *
70 * Whether to use === or == when comparing
71 *
72 * @var bool
73 */
Andrey Andreev5fd3ae82012-10-24 14:55:35 +030074 public $strict = FALSE;
Andrey Andreev597ea272012-11-01 22:56:26 +020075
76 /**
77 * Template
78 *
79 * @var string
80 */
Andrey Andreev5fd3ae82012-10-24 14:55:35 +030081 protected $_template = NULL;
Andrey Andreev597ea272012-11-01 22:56:26 +020082
83 /**
84 * Template rows
85 *
86 * @var string
87 */
Andrey Andreev5fd3ae82012-10-24 14:55:35 +030088 protected $_template_rows = NULL;
Andrey Andreev597ea272012-11-01 22:56:26 +020089
90 /**
91 * List of visible test items
92 *
93 * @var array
94 */
Andrey Andreeva6eae872014-01-03 18:25:20 +020095 protected $_test_items_visible = array(
96 'test_name',
97 'test_datatype',
98 'res_datatype',
99 'result',
100 'file',
101 'line',
102 'notes'
103 );
Derek Allard2067d1a2008-11-13 22:59:24 +0000104
Andrey Andreev597ea272012-11-01 22:56:26 +0200105 // --------------------------------------------------------------------
106
Andrey Andreev5fd3ae82012-10-24 14:55:35 +0300107 /**
108 * Constructor
109 *
110 * @return void
111 */
Greg Akera9263282010-11-10 15:26:43 -0600112 public function __construct()
Derek Allard2067d1a2008-11-13 22:59:24 +0000113 {
Andrey Andreev90726b82015-01-20 12:39:22 +0200114 log_message('info', 'Unit Testing Class Initialized');
Derek Allard0ce73ef2010-01-18 15:48:25 +0000115 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000116
117 // --------------------------------------------------------------------
Derek Allard0ce73ef2010-01-18 15:48:25 +0000118
119 /**
120 * Run the tests
121 *
122 * Runs the supplied tests
123 *
Andrey Andreevcb663672014-01-03 18:45:37 +0200124 * @param array $items
Derek Allard0ce73ef2010-01-18 15:48:25 +0000125 * @return void
126 */
Andrey Andreevcb663672014-01-03 18:45:37 +0200127 public function set_test_items($items)
Derek Allard0ce73ef2010-01-18 15:48:25 +0000128 {
Andrey Andreev1b815532012-04-03 16:06:03 +0300129 if ( ! empty($items) && is_array($items))
Derek Allard0ce73ef2010-01-18 15:48:25 +0000130 {
131 $this->_test_items_visible = $items;
132 }
133 }
134
135 // --------------------------------------------------------------------
136
Derek Allard2067d1a2008-11-13 22:59:24 +0000137 /**
138 * Run the tests
139 *
140 * Runs the supplied tests
141 *
Andrey Andreev5fd3ae82012-10-24 14:55:35 +0300142 * @param mixed $test
Andrey Andreev597ea272012-11-01 22:56:26 +0200143 * @param mixed $expected
144 * @param string $test_name
145 * @param string $notes
Derek Allard2067d1a2008-11-13 22:59:24 +0000146 * @return string
Barry Mienydd671972010-10-04 16:33:58 +0200147 */
Andrey Andreev2a27d312011-12-25 17:08:24 +0200148 public function run($test, $expected = TRUE, $test_name = 'undefined', $notes = '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000149 {
Alex Bilbied261b1e2012-06-02 11:12:16 +0100150 if ($this->active === FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000151 {
152 return FALSE;
153 }
Barry Mienydd671972010-10-04 16:33:58 +0200154
ftwbzhaoa5ea5062015-07-06 13:18:11 +0800155 if (in_array($expected, array('is_object', 'is_string', 'is_bool', 'is_true', 'is_false', 'is_int', 'is_numeric', 'is_float', 'is_double', 'is_array', 'is_null', 'is_resource'), TRUE))
Derek Allard2067d1a2008-11-13 22:59:24 +0000156 {
Andrey Andreev1b815532012-04-03 16:06:03 +0300157 $expected = str_replace('is_double', 'is_float', $expected);
158 $result = $expected($test);
Derek Allard2067d1a2008-11-13 22:59:24 +0000159 $extype = str_replace(array('true', 'false'), 'bool', str_replace('is_', '', $expected));
160 }
161 else
162 {
Andrey Andreev597ea272012-11-01 22:56:26 +0200163 $result = ($this->strict === TRUE) ? ($test === $expected) : ($test == $expected);
Derek Allard2067d1a2008-11-13 22:59:24 +0000164 $extype = gettype($expected);
165 }
Barry Mienydd671972010-10-04 16:33:58 +0200166
Derek Allard2067d1a2008-11-13 22:59:24 +0000167 $back = $this->_backtrace();
Barry Mienydd671972010-10-04 16:33:58 +0200168
Daniel Paul Searlesd2ae1d12012-11-02 17:39:44 -0700169 $report = array (
Derek Allard2067d1a2008-11-13 22:59:24 +0000170 'test_name' => $test_name,
171 'test_datatype' => gettype($test),
172 'res_datatype' => $extype,
173 'result' => ($result === TRUE) ? 'passed' : 'failed',
174 'file' => $back['file'],
Derek Allard0ce73ef2010-01-18 15:48:25 +0000175 'line' => $back['line'],
176 'notes' => $notes
Derek Allard2067d1a2008-11-13 22:59:24 +0000177 );
178
Derek Allard0ce73ef2010-01-18 15:48:25 +0000179 $this->results[] = $report;
180
Daniel Paul Searlesd2ae1d12012-11-02 17:39:44 -0700181 return $this->report($this->result(array($report)));
Derek Allard2067d1a2008-11-13 22:59:24 +0000182 }
183
184 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200185
Derek Allard2067d1a2008-11-13 22:59:24 +0000186 /**
187 * Generate a report
188 *
189 * Displays a table with the test data
190 *
Andrey Andreev597ea272012-11-01 22:56:26 +0200191 * @param array $result
Derek Allard2067d1a2008-11-13 22:59:24 +0000192 * @return string
193 */
Andrey Andreev2a27d312011-12-25 17:08:24 +0200194 public function report($result = array())
Derek Allard2067d1a2008-11-13 22:59:24 +0000195 {
Andrey Andreev2a27d312011-12-25 17:08:24 +0200196 if (count($result) === 0)
Derek Allard2067d1a2008-11-13 22:59:24 +0000197 {
198 $result = $this->result();
199 }
200
201 $CI =& get_instance();
202 $CI->load->language('unit_test');
203
204 $this->_parse_template();
205
206 $r = '';
207 foreach ($result as $res)
208 {
209 $table = '';
210
211 foreach ($res as $key => $val)
212 {
Alex Bilbied261b1e2012-06-02 11:12:16 +0100213 if ($key === $CI->lang->line('ut_result'))
Derek Allard2067d1a2008-11-13 22:59:24 +0000214 {
Alex Bilbied261b1e2012-06-02 11:12:16 +0100215 if ($val === $CI->lang->line('ut_passed'))
Derek Allard2067d1a2008-11-13 22:59:24 +0000216 {
217 $val = '<span style="color: #0C0;">'.$val.'</span>';
218 }
Alex Bilbied261b1e2012-06-02 11:12:16 +0100219 elseif ($val === $CI->lang->line('ut_failed'))
Derek Allard2067d1a2008-11-13 22:59:24 +0000220 {
221 $val = '<span style="color: #C00;">'.$val.'</span>';
222 }
223 }
224
Andrey Andreev2a27d312011-12-25 17:08:24 +0200225 $table .= str_replace(array('{item}', '{result}'), array($key, $val), $this->_template_rows);
Derek Allard2067d1a2008-11-13 22:59:24 +0000226 }
227
228 $r .= str_replace('{rows}', $table, $this->_template);
229 }
230
231 return $r;
232 }
Barry Mienydd671972010-10-04 16:33:58 +0200233
Derek Allard2067d1a2008-11-13 22:59:24 +0000234 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200235
Derek Allard2067d1a2008-11-13 22:59:24 +0000236 /**
237 * Use strict comparison
238 *
239 * Causes the evaluation to use === rather than ==
240 *
Andrey Andreeva6eae872014-01-03 18:25:20 +0200241 * @param bool $state
Andrey Andreev1b815532012-04-03 16:06:03 +0300242 * @return void
Derek Allard2067d1a2008-11-13 22:59:24 +0000243 */
Andrey Andreev2a27d312011-12-25 17:08:24 +0200244 public function use_strict($state = TRUE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000245 {
Andrey Andreev2a27d312011-12-25 17:08:24 +0200246 $this->strict = (bool) $state;
Derek Allard2067d1a2008-11-13 22:59:24 +0000247 }
Barry Mienydd671972010-10-04 16:33:58 +0200248
Derek Allard2067d1a2008-11-13 22:59:24 +0000249 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200250
Derek Allard2067d1a2008-11-13 22:59:24 +0000251 /**
252 * Make Unit testing active
253 *
254 * Enables/disables unit testing
255 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000256 * @param bool
Andrey Andreev1b815532012-04-03 16:06:03 +0300257 * @return void
Derek Allard2067d1a2008-11-13 22:59:24 +0000258 */
Andrey Andreev2a27d312011-12-25 17:08:24 +0200259 public function active($state = TRUE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000260 {
Andrey Andreev2a27d312011-12-25 17:08:24 +0200261 $this->active = (bool) $state;
Derek Allard2067d1a2008-11-13 22:59:24 +0000262 }
Barry Mienydd671972010-10-04 16:33:58 +0200263
Derek Allard2067d1a2008-11-13 22:59:24 +0000264 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200265
Derek Allard2067d1a2008-11-13 22:59:24 +0000266 /**
267 * Result Array
268 *
269 * Returns the raw result data
270 *
Andrey Andreev597ea272012-11-01 22:56:26 +0200271 * @param array $results
Derek Allard2067d1a2008-11-13 22:59:24 +0000272 * @return array
273 */
Andrey Andreev2a27d312011-12-25 17:08:24 +0200274 public function result($results = array())
Barry Mienydd671972010-10-04 16:33:58 +0200275 {
Derek Allard2067d1a2008-11-13 22:59:24 +0000276 $CI =& get_instance();
277 $CI->load->language('unit_test');
Barry Mienydd671972010-10-04 16:33:58 +0200278
Andrey Andreev2a27d312011-12-25 17:08:24 +0200279 if (count($results) === 0)
Derek Allard2067d1a2008-11-13 22:59:24 +0000280 {
281 $results = $this->results;
282 }
Barry Mienydd671972010-10-04 16:33:58 +0200283
Derek Allard2067d1a2008-11-13 22:59:24 +0000284 $retval = array();
285 foreach ($results as $result)
286 {
287 $temp = array();
288 foreach ($result as $key => $val)
289 {
Derek Allard0ce73ef2010-01-18 15:48:25 +0000290 if ( ! in_array($key, $this->_test_items_visible))
291 {
292 continue;
293 }
294
Andrey Andreevce0c9562012-11-22 17:26:29 +0200295 if (FALSE !== ($line = $CI->lang->line(strtolower('ut_'.$val), FALSE)))
Derek Allard2067d1a2008-11-13 22:59:24 +0000296 {
Daniel Paul Searlesd2ae1d12012-11-02 17:39:44 -0700297 $val = $line;
Derek Allard2067d1a2008-11-13 22:59:24 +0000298 }
Andrey Andreeva6eae872014-01-03 18:25:20 +0200299
Andrey Andreevce0c9562012-11-22 17:26:29 +0200300 $temp[$CI->lang->line('ut_'.$key, FALSE)] = $val;
Derek Allard2067d1a2008-11-13 22:59:24 +0000301 }
Barry Mienydd671972010-10-04 16:33:58 +0200302
Derek Allard2067d1a2008-11-13 22:59:24 +0000303 $retval[] = $temp;
304 }
Barry Mienydd671972010-10-04 16:33:58 +0200305
Derek Allard2067d1a2008-11-13 22:59:24 +0000306 return $retval;
307 }
Barry Mienydd671972010-10-04 16:33:58 +0200308
Derek Allard2067d1a2008-11-13 22:59:24 +0000309 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200310
Derek Allard2067d1a2008-11-13 22:59:24 +0000311 /**
312 * Set the template
313 *
314 * This lets us set the template to be used to display results
315 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000316 * @param string
317 * @return void
Barry Mienydd671972010-10-04 16:33:58 +0200318 */
Andrey Andreev2a27d312011-12-25 17:08:24 +0200319 public function set_template($template)
Derek Allard2067d1a2008-11-13 22:59:24 +0000320 {
321 $this->_template = $template;
322 }
Barry Mienydd671972010-10-04 16:33:58 +0200323
Derek Allard2067d1a2008-11-13 22:59:24 +0000324 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200325
Derek Allard2067d1a2008-11-13 22:59:24 +0000326 /**
327 * Generate a backtrace
328 *
329 * This lets us show file names and line numbers
330 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000331 * @return array
332 */
Andrey Andreev114586f2011-12-26 16:27:17 +0200333 protected function _backtrace()
Derek Allard2067d1a2008-11-13 22:59:24 +0000334 {
Andrey Andreevc839d282012-06-07 14:35:27 +0300335 $back = debug_backtrace();
336 return array(
337 'file' => (isset($back[1]['file']) ? $back[1]['file'] : ''),
338 'line' => (isset($back[1]['line']) ? $back[1]['line'] : '')
339 );
Derek Allard2067d1a2008-11-13 22:59:24 +0000340 }
341
342 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200343
Derek Allard2067d1a2008-11-13 22:59:24 +0000344 /**
345 * Get Default Template
346 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000347 * @return string
348 */
Andrey Andreev114586f2011-12-26 16:27:17 +0200349 protected function _default_template()
Barry Mienydd671972010-10-04 16:33:58 +0200350 {
Andrey Andreev1b815532012-04-03 16:06:03 +0300351 $this->_template = "\n".'<table style="width:100%; font-size:small; margin:10px 0; border-collapse:collapse; border:1px solid #CCC;">{rows}'."\n</table>";
Barry Mienydd671972010-10-04 16:33:58 +0200352
Andrey Andreev2a27d312011-12-25 17:08:24 +0200353 $this->_template_rows = "\n\t<tr>\n\t\t".'<th style="text-align: left; border-bottom:1px solid #CCC;">{item}</th>'
Andrey Andreev1b815532012-04-03 16:06:03 +0300354 ."\n\t\t".'<td style="border-bottom:1px solid #CCC;">{result}</td>'."\n\t</tr>";
Derek Allard2067d1a2008-11-13 22:59:24 +0000355 }
Barry Mienydd671972010-10-04 16:33:58 +0200356
Derek Allard2067d1a2008-11-13 22:59:24 +0000357 // --------------------------------------------------------------------
358
359 /**
360 * Parse Template
361 *
362 * Harvests the data within the template {pseudo-variables}
363 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000364 * @return void
365 */
Andrey Andreev114586f2011-12-26 16:27:17 +0200366 protected function _parse_template()
Barry Mienydd671972010-10-04 16:33:58 +0200367 {
vlakoff1228fe22013-01-14 01:30:09 +0100368 if ($this->_template_rows !== NULL)
Barry Mienydd671972010-10-04 16:33:58 +0200369 {
370 return;
371 }
372
vlakoff1228fe22013-01-14 01:30:09 +0100373 if ($this->_template === NULL OR ! preg_match('/\{rows\}(.*?)\{\/rows\}/si', $this->_template, $match))
Barry Mienydd671972010-10-04 16:33:58 +0200374 {
375 $this->_default_template();
376 return;
377 }
378
Andrey Andreev2a27d312011-12-25 17:08:24 +0200379 $this->_template_rows = $match[1];
380 $this->_template = str_replace($match[0], '{rows}', $this->_template);
Barry Mienydd671972010-10-04 16:33:58 +0200381 }
382
Derek Allard2067d1a2008-11-13 22:59:24 +0000383}
Derek Allard2067d1a2008-11-13 22:59:24 +0000384
385/**
Andrey Andreev5fd3ae82012-10-24 14:55:35 +0300386 * Helper function to test boolean TRUE
Derek Allard2067d1a2008-11-13 22:59:24 +0000387 *
Andrey Andreev5fd3ae82012-10-24 14:55:35 +0300388 * @param mixed $test
Derek Allard2067d1a2008-11-13 22:59:24 +0000389 * @return bool
390 */
391function is_true($test)
392{
Andrey Andreev56454792012-05-17 14:32:19 +0300393 return ($test === TRUE);
Derek Allard2067d1a2008-11-13 22:59:24 +0000394}
Andrey Andreev5fd3ae82012-10-24 14:55:35 +0300395
396/**
397 * Helper function to test boolean FALSE
398 *
399 * @param mixed $test
400 * @return bool
401 */
Derek Allard2067d1a2008-11-13 22:59:24 +0000402function is_false($test)
403{
Andrey Andreev56454792012-05-17 14:32:19 +0300404 return ($test === FALSE);
Derek Allard2067d1a2008-11-13 22:59:24 +0000405}