blob: ea78e0d98c0951fb83cec8590b44d4ea2cc4f467 [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 Andreev125ef472016-01-11 12:33:00 +02009 * Copyright (c) 2014 - 2016, 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
Andrey Andreev1924e872016-01-11 12:55:34 +020031 * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
Andrey Andreev125ef472016-01-11 12:33:00 +020032 * @copyright Copyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)
Andrey Andreevbdb96ca2014-10-28 00:13:31 +020033 * @license http://opensource.org/licenses/MIT MIT License
Andrey Andreevbd202c92016-01-11 12:50:18 +020034 * @link https://codeigniter.com
Andrey Andreevbdb96ca2014-10-28 00:13:31 +020035 * @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
Andrey Andreevbd202c92016-01-11 12:50:18 +020049 * @link https://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 Andreeva45e37e2015-07-08 17:58:21 +030058 public $active = TRUE;
Andrey Andreev597ea272012-11-01 22:56:26 +020059
60 /**
61 * Test results
62 *
63 * @var array
64 */
Andrey Andreeva45e37e2015-07-08 17:58:21 +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 Andreeva45e37e2015-07-08 17:58:21 +030074 public $strict = FALSE;
Andrey Andreev597ea272012-11-01 22:56:26 +020075
76 /**
77 * Template
78 *
79 * @var string
80 */
Andrey Andreeva45e37e2015-07-08 17:58:21 +030081 protected $_template = NULL;
Andrey Andreev597ea272012-11-01 22:56:26 +020082
83 /**
84 * Template rows
85 *
86 * @var string
87 */
Andrey Andreeva45e37e2015-07-08 17:58:21 +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(
Andrey Andreeva45e37e2015-07-08 17:58:21 +030096 'test_name',
97 'test_datatype',
98 'res_datatype',
99 'result',
100 'file',
101 'line',
102 'notes'
Andrey Andreeva6eae872014-01-03 18:25:20 +0200103 );
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 (
Andrey Andreeva45e37e2015-07-08 17:58:21 +0300170 'test_name' => $test_name,
171 'test_datatype' => gettype($test),
172 'res_datatype' => $extype,
173 'result' => ($result === TRUE) ? 'passed' : 'failed',
174 'file' => $back['file'],
175 'line' => $back['line'],
176 'notes' => $notes
177 );
Derek Allard2067d1a2008-11-13 22:59:24 +0000178
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 }
Andrey Andreevb5e24102016-08-10 13:21:15 +0300294 elseif (in_array($key, array('test_name', 'test_datatype', 'res_datatype', 'result'), TRUE))
Derek Allard2067d1a2008-11-13 22:59:24 +0000295 {
Andrey Andreev7018d892015-07-08 17:57:52 +0300296 if (FALSE !== ($line = $CI->lang->line(strtolower('ut_'.$val), FALSE)))
297 {
298 $val = $line;
299 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000300 }
Andrey Andreeva6eae872014-01-03 18:25:20 +0200301
Andrey Andreevce0c9562012-11-22 17:26:29 +0200302 $temp[$CI->lang->line('ut_'.$key, FALSE)] = $val;
Derek Allard2067d1a2008-11-13 22:59:24 +0000303 }
Barry Mienydd671972010-10-04 16:33:58 +0200304
Derek Allard2067d1a2008-11-13 22:59:24 +0000305 $retval[] = $temp;
306 }
Barry Mienydd671972010-10-04 16:33:58 +0200307
Derek Allard2067d1a2008-11-13 22:59:24 +0000308 return $retval;
309 }
Barry Mienydd671972010-10-04 16:33:58 +0200310
Derek Allard2067d1a2008-11-13 22:59:24 +0000311 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200312
Derek Allard2067d1a2008-11-13 22:59:24 +0000313 /**
314 * Set the template
315 *
316 * This lets us set the template to be used to display results
317 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000318 * @param string
319 * @return void
Barry Mienydd671972010-10-04 16:33:58 +0200320 */
Andrey Andreev2a27d312011-12-25 17:08:24 +0200321 public function set_template($template)
Derek Allard2067d1a2008-11-13 22:59:24 +0000322 {
323 $this->_template = $template;
324 }
Barry Mienydd671972010-10-04 16:33:58 +0200325
Derek Allard2067d1a2008-11-13 22:59:24 +0000326 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200327
Derek Allard2067d1a2008-11-13 22:59:24 +0000328 /**
329 * Generate a backtrace
330 *
331 * This lets us show file names and line numbers
332 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000333 * @return array
334 */
Andrey Andreev114586f2011-12-26 16:27:17 +0200335 protected function _backtrace()
Derek Allard2067d1a2008-11-13 22:59:24 +0000336 {
Andrey Andreevc839d282012-06-07 14:35:27 +0300337 $back = debug_backtrace();
338 return array(
Andrey Andreeva45e37e2015-07-08 17:58:21 +0300339 'file' => (isset($back[1]['file']) ? $back[1]['file'] : ''),
340 'line' => (isset($back[1]['line']) ? $back[1]['line'] : '')
341 );
Derek Allard2067d1a2008-11-13 22:59:24 +0000342 }
343
344 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200345
Derek Allard2067d1a2008-11-13 22:59:24 +0000346 /**
347 * Get Default Template
348 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000349 * @return string
350 */
Andrey Andreev114586f2011-12-26 16:27:17 +0200351 protected function _default_template()
Barry Mienydd671972010-10-04 16:33:58 +0200352 {
Andrey Andreev1b815532012-04-03 16:06:03 +0300353 $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 +0200354
Andrey Andreev2a27d312011-12-25 17:08:24 +0200355 $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 +0300356 ."\n\t\t".'<td style="border-bottom:1px solid #CCC;">{result}</td>'."\n\t</tr>";
Derek Allard2067d1a2008-11-13 22:59:24 +0000357 }
Barry Mienydd671972010-10-04 16:33:58 +0200358
Derek Allard2067d1a2008-11-13 22:59:24 +0000359 // --------------------------------------------------------------------
360
361 /**
362 * Parse Template
363 *
364 * Harvests the data within the template {pseudo-variables}
365 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000366 * @return void
367 */
Andrey Andreev114586f2011-12-26 16:27:17 +0200368 protected function _parse_template()
Barry Mienydd671972010-10-04 16:33:58 +0200369 {
vlakoff1228fe22013-01-14 01:30:09 +0100370 if ($this->_template_rows !== NULL)
Barry Mienydd671972010-10-04 16:33:58 +0200371 {
372 return;
373 }
374
vlakoff1228fe22013-01-14 01:30:09 +0100375 if ($this->_template === NULL OR ! preg_match('/\{rows\}(.*?)\{\/rows\}/si', $this->_template, $match))
Barry Mienydd671972010-10-04 16:33:58 +0200376 {
377 $this->_default_template();
378 return;
379 }
380
Andrey Andreev2a27d312011-12-25 17:08:24 +0200381 $this->_template_rows = $match[1];
382 $this->_template = str_replace($match[0], '{rows}', $this->_template);
Barry Mienydd671972010-10-04 16:33:58 +0200383 }
384
Derek Allard2067d1a2008-11-13 22:59:24 +0000385}
Derek Allard2067d1a2008-11-13 22:59:24 +0000386
387/**
Andrey Andreev5fd3ae82012-10-24 14:55:35 +0300388 * Helper function to test boolean TRUE
Derek Allard2067d1a2008-11-13 22:59:24 +0000389 *
Andrey Andreev5fd3ae82012-10-24 14:55:35 +0300390 * @param mixed $test
Derek Allard2067d1a2008-11-13 22:59:24 +0000391 * @return bool
392 */
393function is_true($test)
394{
Andrey Andreev56454792012-05-17 14:32:19 +0300395 return ($test === TRUE);
Derek Allard2067d1a2008-11-13 22:59:24 +0000396}
Andrey Andreev5fd3ae82012-10-24 14:55:35 +0300397
398/**
399 * Helper function to test boolean FALSE
400 *
401 * @param mixed $test
402 * @return bool
403 */
Derek Allard2067d1a2008-11-13 22:59:24 +0000404function is_false($test)
405{
Andrey Andreev56454792012-05-17 14:32:19 +0300406 return ($test === FALSE);
Derek Allard2067d1a2008-11-13 22:59:24 +0000407}