blob: fa87e03b9e2e0f90f7b0c06a8e6eecccfd6f271f [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 Andreevcce6bd12018-01-09 11:32:02 +02009 * Copyright (c) 2014 - 2018, 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 Andreevcce6bd12018-01-09 11:32:02 +020032 * @copyright Copyright (c) 2014 - 2018, 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 $result = $expected($test);
Derek Allard2067d1a2008-11-13 22:59:24 +0000158 $extype = str_replace(array('true', 'false'), 'bool', str_replace('is_', '', $expected));
159 }
160 else
161 {
Andrey Andreev597ea272012-11-01 22:56:26 +0200162 $result = ($this->strict === TRUE) ? ($test === $expected) : ($test == $expected);
Derek Allard2067d1a2008-11-13 22:59:24 +0000163 $extype = gettype($expected);
164 }
Barry Mienydd671972010-10-04 16:33:58 +0200165
Derek Allard2067d1a2008-11-13 22:59:24 +0000166 $back = $this->_backtrace();
Barry Mienydd671972010-10-04 16:33:58 +0200167
Daniel Paul Searlesd2ae1d12012-11-02 17:39:44 -0700168 $report = array (
Andrey Andreeva45e37e2015-07-08 17:58:21 +0300169 'test_name' => $test_name,
170 'test_datatype' => gettype($test),
171 'res_datatype' => $extype,
172 'result' => ($result === TRUE) ? 'passed' : 'failed',
173 'file' => $back['file'],
174 'line' => $back['line'],
175 'notes' => $notes
176 );
Derek Allard2067d1a2008-11-13 22:59:24 +0000177
Derek Allard0ce73ef2010-01-18 15:48:25 +0000178 $this->results[] = $report;
179
Daniel Paul Searlesd2ae1d12012-11-02 17:39:44 -0700180 return $this->report($this->result(array($report)));
Derek Allard2067d1a2008-11-13 22:59:24 +0000181 }
182
183 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200184
Derek Allard2067d1a2008-11-13 22:59:24 +0000185 /**
186 * Generate a report
187 *
188 * Displays a table with the test data
189 *
Andrey Andreev597ea272012-11-01 22:56:26 +0200190 * @param array $result
Derek Allard2067d1a2008-11-13 22:59:24 +0000191 * @return string
192 */
Andrey Andreev2a27d312011-12-25 17:08:24 +0200193 public function report($result = array())
Derek Allard2067d1a2008-11-13 22:59:24 +0000194 {
Andrey Andreev2a27d312011-12-25 17:08:24 +0200195 if (count($result) === 0)
Derek Allard2067d1a2008-11-13 22:59:24 +0000196 {
197 $result = $this->result();
198 }
199
200 $CI =& get_instance();
201 $CI->load->language('unit_test');
202
203 $this->_parse_template();
204
205 $r = '';
206 foreach ($result as $res)
207 {
208 $table = '';
209
210 foreach ($res as $key => $val)
211 {
Alex Bilbied261b1e2012-06-02 11:12:16 +0100212 if ($key === $CI->lang->line('ut_result'))
Derek Allard2067d1a2008-11-13 22:59:24 +0000213 {
Alex Bilbied261b1e2012-06-02 11:12:16 +0100214 if ($val === $CI->lang->line('ut_passed'))
Derek Allard2067d1a2008-11-13 22:59:24 +0000215 {
216 $val = '<span style="color: #0C0;">'.$val.'</span>';
217 }
Alex Bilbied261b1e2012-06-02 11:12:16 +0100218 elseif ($val === $CI->lang->line('ut_failed'))
Derek Allard2067d1a2008-11-13 22:59:24 +0000219 {
220 $val = '<span style="color: #C00;">'.$val.'</span>';
221 }
222 }
223
Andrey Andreev2a27d312011-12-25 17:08:24 +0200224 $table .= str_replace(array('{item}', '{result}'), array($key, $val), $this->_template_rows);
Derek Allard2067d1a2008-11-13 22:59:24 +0000225 }
226
227 $r .= str_replace('{rows}', $table, $this->_template);
228 }
229
230 return $r;
231 }
Barry Mienydd671972010-10-04 16:33:58 +0200232
Derek Allard2067d1a2008-11-13 22:59:24 +0000233 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200234
Derek Allard2067d1a2008-11-13 22:59:24 +0000235 /**
236 * Use strict comparison
237 *
238 * Causes the evaluation to use === rather than ==
239 *
Andrey Andreeva6eae872014-01-03 18:25:20 +0200240 * @param bool $state
Andrey Andreev1b815532012-04-03 16:06:03 +0300241 * @return void
Derek Allard2067d1a2008-11-13 22:59:24 +0000242 */
Andrey Andreev2a27d312011-12-25 17:08:24 +0200243 public function use_strict($state = TRUE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000244 {
Andrey Andreev2a27d312011-12-25 17:08:24 +0200245 $this->strict = (bool) $state;
Derek Allard2067d1a2008-11-13 22:59:24 +0000246 }
Barry Mienydd671972010-10-04 16:33:58 +0200247
Derek Allard2067d1a2008-11-13 22:59:24 +0000248 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200249
Derek Allard2067d1a2008-11-13 22:59:24 +0000250 /**
251 * Make Unit testing active
252 *
253 * Enables/disables unit testing
254 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000255 * @param bool
Andrey Andreev1b815532012-04-03 16:06:03 +0300256 * @return void
Derek Allard2067d1a2008-11-13 22:59:24 +0000257 */
Andrey Andreev2a27d312011-12-25 17:08:24 +0200258 public function active($state = TRUE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000259 {
Andrey Andreev2a27d312011-12-25 17:08:24 +0200260 $this->active = (bool) $state;
Derek Allard2067d1a2008-11-13 22:59:24 +0000261 }
Barry Mienydd671972010-10-04 16:33:58 +0200262
Derek Allard2067d1a2008-11-13 22:59:24 +0000263 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200264
Derek Allard2067d1a2008-11-13 22:59:24 +0000265 /**
266 * Result Array
267 *
268 * Returns the raw result data
269 *
Andrey Andreev597ea272012-11-01 22:56:26 +0200270 * @param array $results
Derek Allard2067d1a2008-11-13 22:59:24 +0000271 * @return array
272 */
Andrey Andreev2a27d312011-12-25 17:08:24 +0200273 public function result($results = array())
Barry Mienydd671972010-10-04 16:33:58 +0200274 {
Derek Allard2067d1a2008-11-13 22:59:24 +0000275 $CI =& get_instance();
276 $CI->load->language('unit_test');
Barry Mienydd671972010-10-04 16:33:58 +0200277
Andrey Andreev2a27d312011-12-25 17:08:24 +0200278 if (count($results) === 0)
Derek Allard2067d1a2008-11-13 22:59:24 +0000279 {
280 $results = $this->results;
281 }
Barry Mienydd671972010-10-04 16:33:58 +0200282
Derek Allard2067d1a2008-11-13 22:59:24 +0000283 $retval = array();
284 foreach ($results as $result)
285 {
286 $temp = array();
287 foreach ($result as $key => $val)
288 {
Derek Allard0ce73ef2010-01-18 15:48:25 +0000289 if ( ! in_array($key, $this->_test_items_visible))
290 {
291 continue;
292 }
Andrey Andreevb5e24102016-08-10 13:21:15 +0300293 elseif (in_array($key, array('test_name', 'test_datatype', 'res_datatype', 'result'), TRUE))
Derek Allard2067d1a2008-11-13 22:59:24 +0000294 {
Andrey Andreev7018d892015-07-08 17:57:52 +0300295 if (FALSE !== ($line = $CI->lang->line(strtolower('ut_'.$val), FALSE)))
296 {
297 $val = $line;
298 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000299 }
Andrey Andreeva6eae872014-01-03 18:25:20 +0200300
Andrey Andreevce0c9562012-11-22 17:26:29 +0200301 $temp[$CI->lang->line('ut_'.$key, FALSE)] = $val;
Derek Allard2067d1a2008-11-13 22:59:24 +0000302 }
Barry Mienydd671972010-10-04 16:33:58 +0200303
Derek Allard2067d1a2008-11-13 22:59:24 +0000304 $retval[] = $temp;
305 }
Barry Mienydd671972010-10-04 16:33:58 +0200306
Derek Allard2067d1a2008-11-13 22:59:24 +0000307 return $retval;
308 }
Barry Mienydd671972010-10-04 16:33:58 +0200309
Derek Allard2067d1a2008-11-13 22:59:24 +0000310 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200311
Derek Allard2067d1a2008-11-13 22:59:24 +0000312 /**
313 * Set the template
314 *
315 * This lets us set the template to be used to display results
316 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000317 * @param string
318 * @return void
Barry Mienydd671972010-10-04 16:33:58 +0200319 */
Andrey Andreev2a27d312011-12-25 17:08:24 +0200320 public function set_template($template)
Derek Allard2067d1a2008-11-13 22:59:24 +0000321 {
322 $this->_template = $template;
323 }
Barry Mienydd671972010-10-04 16:33:58 +0200324
Derek Allard2067d1a2008-11-13 22:59:24 +0000325 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200326
Derek Allard2067d1a2008-11-13 22:59:24 +0000327 /**
328 * Generate a backtrace
329 *
330 * This lets us show file names and line numbers
331 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000332 * @return array
333 */
Andrey Andreev114586f2011-12-26 16:27:17 +0200334 protected function _backtrace()
Derek Allard2067d1a2008-11-13 22:59:24 +0000335 {
Andrey Andreevc839d282012-06-07 14:35:27 +0300336 $back = debug_backtrace();
337 return array(
Andrey Andreeva45e37e2015-07-08 17:58:21 +0300338 'file' => (isset($back[1]['file']) ? $back[1]['file'] : ''),
339 'line' => (isset($back[1]['line']) ? $back[1]['line'] : '')
340 );
Derek Allard2067d1a2008-11-13 22:59:24 +0000341 }
342
343 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200344
Derek Allard2067d1a2008-11-13 22:59:24 +0000345 /**
346 * Get Default Template
347 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000348 * @return string
349 */
Andrey Andreev114586f2011-12-26 16:27:17 +0200350 protected function _default_template()
Barry Mienydd671972010-10-04 16:33:58 +0200351 {
Andrey Andreev1b815532012-04-03 16:06:03 +0300352 $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 +0200353
Andrey Andreev2a27d312011-12-25 17:08:24 +0200354 $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 +0300355 ."\n\t\t".'<td style="border-bottom:1px solid #CCC;">{result}</td>'."\n\t</tr>";
Derek Allard2067d1a2008-11-13 22:59:24 +0000356 }
Barry Mienydd671972010-10-04 16:33:58 +0200357
Derek Allard2067d1a2008-11-13 22:59:24 +0000358 // --------------------------------------------------------------------
359
360 /**
361 * Parse Template
362 *
363 * Harvests the data within the template {pseudo-variables}
364 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000365 * @return void
366 */
Andrey Andreev114586f2011-12-26 16:27:17 +0200367 protected function _parse_template()
Barry Mienydd671972010-10-04 16:33:58 +0200368 {
vlakoff1228fe22013-01-14 01:30:09 +0100369 if ($this->_template_rows !== NULL)
Barry Mienydd671972010-10-04 16:33:58 +0200370 {
371 return;
372 }
373
vlakoff1228fe22013-01-14 01:30:09 +0100374 if ($this->_template === NULL OR ! preg_match('/\{rows\}(.*?)\{\/rows\}/si', $this->_template, $match))
Barry Mienydd671972010-10-04 16:33:58 +0200375 {
376 $this->_default_template();
377 return;
378 }
379
Andrey Andreev2a27d312011-12-25 17:08:24 +0200380 $this->_template_rows = $match[1];
381 $this->_template = str_replace($match[0], '{rows}', $this->_template);
Barry Mienydd671972010-10-04 16:33:58 +0200382 }
383
Derek Allard2067d1a2008-11-13 22:59:24 +0000384}
Derek Allard2067d1a2008-11-13 22:59:24 +0000385
386/**
Andrey Andreev5fd3ae82012-10-24 14:55:35 +0300387 * Helper function to test boolean TRUE
Derek Allard2067d1a2008-11-13 22:59:24 +0000388 *
Andrey Andreev5fd3ae82012-10-24 14:55:35 +0300389 * @param mixed $test
Derek Allard2067d1a2008-11-13 22:59:24 +0000390 * @return bool
391 */
392function is_true($test)
393{
Andrey Andreev56454792012-05-17 14:32:19 +0300394 return ($test === TRUE);
Derek Allard2067d1a2008-11-13 22:59:24 +0000395}
Andrey Andreev5fd3ae82012-10-24 14:55:35 +0300396
397/**
398 * Helper function to test boolean FALSE
399 *
400 * @param mixed $test
401 * @return bool
402 */
Derek Allard2067d1a2008-11-13 22:59:24 +0000403function is_false($test)
404{
Andrey Andreev56454792012-05-17 14:32:19 +0300405 return ($test === FALSE);
Derek Allard2067d1a2008-11-13 22:59:24 +0000406}