Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 256 lines (233 sloc) 6.996 kb
fe822aa @gwoo initial work on test controller and reporters
gwoo authored
1 <?php
2 /**
3 * Lithium: the most rad php framework
4 *
4f1a9c0 @nateabele Updating copyright year.
nateabele authored
5 * @copyright Copyright 2011, Union of RAD (http://union-of-rad.org)
fe822aa @gwoo initial work on test controller and reporters
gwoo authored
6 * @license http://opensource.org/licenses/bsd-license.php The BSD License
7 */
8
9 namespace lithium\test;
10
00ce46c @nateabele Implemented core exceptions. Implemented `\core\Libraries::instance()` t...
nateabele authored
11 use lithium\core\Libraries;
12 use lithium\util\Inflector;
13 use lithium\core\ClassNotFoundException;
7cdd71a @gwoo more refactoring of test suite
gwoo authored
14
15 /**
8dd7503 @jperras Adding class doc blocks to `test\Report`.
jperras authored
16 * This `Report` object aggregates tests in a group and allows you to run said tests to
17 * obtain the results and stats (passes, fails, exceptions, skips) of the test run.
18 *
19 * While Lithium already comes with a text-based as well as web-based test interface, you
20 * may use or extend the `Report` class to create your own test reporter functionality. In
21 * addition, you can also create your own custom templates for displaying results in a different
22 * format, such as json.
23 *
24 * Example usage, for built-in HTML format/reporter:
25 *
26 * {{{
27 * $report = new Report(array(
28 * 'title' => 'Test Report Title',
29 * 'group' => new Group(array('data' => array('\lithium\tests\cases\net\http\MediaTest'))),
30 * 'format' => 'html',
31 * 'reporter' => 'html'
32 * ));
33 *
34 * $report->run();
35 *
36 * //Get the test stats:
37 * $report->stats();
38 *
39 * //Get test results:
40 * $report->results
41 * }}}
42 *
43 * You may also choose to filter the results of the test runs to obtain additional information.
44 * For example, say you wish to calculate the cyclomatic complexity of the classes you are testing:
45 *
46 * {{{
47 * $report = new Report(array(
48 * 'title' => 'Test Report Title',
49 * 'group' => new Group(array('data' => array('\lithium\tests\cases\net\http\MediaTest'))),
50 * 'filters' => array('Complexity')
51 * ));
52 *
53 * $report->run();
54 *
55 * //Get test results, including filter results:
56 * $report->results
57 * }}}
58 *
59 * @see lithium\test\Group
60 * @see lithium\test\filter
61 * @see lithium\test\templates
7cdd71a @gwoo more refactoring of test suite
gwoo authored
62 */
fe822aa @gwoo initial work on test controller and reporters
gwoo authored
63 class Report extends \lithium\core\Object {
64
65 /**
66 * Contains an instance of `lithium\test\Group`, which contains all unit tests to be executed
67 * this test run.
68 *
69 * @var object
70 */
71 public $group = null;
72
73 /**
7cdd71a @gwoo more refactoring of test suite
gwoo authored
74 * Title of the group being run
75 *
76 * @var string
77 */
78 public $title = null;
79
80 /**
81 * group and filter results
82 *
83 * @var array
84 */
85 public $results = array('group' => array(), 'filters' => array());
86
87 /**
88 * start and end timers
89 *
90 * @var array
91 */
92 public $timer = array('start' => null, 'end' => null);
81d6725 @gwoo test suite refactor is "working" still needs more cleanup and organizati...
gwoo authored
93
7cdd71a @gwoo more refactoring of test suite
gwoo authored
94 /**
8ac8a36 @gwoo refactoring how filters are handled
gwoo authored
95 * An array key on fully-namespaced class names of the filter with options to be
96 * applied for the filter as the value
97 *
98 * @var array
99 */
100 protected $_filters = array();
101
102 /**
7cdd71a @gwoo more refactoring of test suite
gwoo authored
103 * Construct Report Object
104 *
105 * @param array $config Options array for the test run. Valid options are:
eb53e19 @gwoo adding some coverage for \test\Report
gwoo authored
106 * - 'group': The test group with items to be run.
7cdd71a @gwoo more refactoring of test suite
gwoo authored
107 * - 'filters': An array of filters that the test output should be run through.
108 */
f80098d @nateabele Adding type hinting to constructor `$config` arrays and all applicable `...
nateabele authored
109 public function __construct(array $config = array()) {
7cdd71a @gwoo more refactoring of test suite
gwoo authored
110 $defaults = array(
eb53e19 @gwoo adding some coverage for \test\Report
gwoo authored
111 'title' => null,
7cdd71a @gwoo more refactoring of test suite
gwoo authored
112 'group' => null,
113 'filters' => array(),
97199ea @gwoo adding some filters for `\test\Dispatcher` and `\test\Report`
gwoo authored
114 'format' => 'txt',
26c2192 @davidpersson QA: Removing trailing comma in arrays, lowercasing some keywords.
davidpersson authored
115 'reporter' => 'console'
7cdd71a @gwoo more refactoring of test suite
gwoo authored
116 );
126affc @nateabele Type fixes to handle test suite warnings.
nateabele authored
117 parent::__construct($config + $defaults);
7cdd71a @gwoo more refactoring of test suite
gwoo authored
118 }
fe822aa @gwoo initial work on test controller and reporters
gwoo authored
119
7cdd71a @gwoo more refactoring of test suite
gwoo authored
120 /**
121 * undocumented function
122 *
123 * @return void
124 */
fe822aa @gwoo initial work on test controller and reporters
gwoo authored
125 protected function _init() {
7cdd71a @gwoo more refactoring of test suite
gwoo authored
126 $this->group = $this->_config['group'];
127 $this->title = $this->_config['title'] ?: $this->_config['title'];
fe822aa @gwoo initial work on test controller and reporters
gwoo authored
128 }
1e23d77 @gwoo hacking on Report
gwoo authored
129
7cdd71a @gwoo more refactoring of test suite
gwoo authored
130 /**
131 * undocumented function
132 *
133 * @return void
134 */
135 public function run() {
136 $tests = $this->group->tests();
e6cd7c1 @davidpersson Adding `Base` test filter.
davidpersson authored
137
8ac8a36 @gwoo refactoring how filters are handled
gwoo authored
138 foreach ($this->filters() as $filter => $options) {
139 $this->results['filters'][$filter] = array();
140 $tests = $filter::apply($this, $tests, $options['apply']) ?: $tests;
1e23d77 @gwoo hacking on Report
gwoo authored
141 }
7cdd71a @gwoo more refactoring of test suite
gwoo authored
142 $this->results['group'] = $tests->run();
1e23d77 @gwoo hacking on Report
gwoo authored
143
8ac8a36 @gwoo refactoring how filters are handled
gwoo authored
144 foreach ($this->filters() as $filter => $options) {
145 $this->results['filters'][$filter] = $filter::analyze($this, $options['analyze']);
1e23d77 @gwoo hacking on Report
gwoo authored
146 }
7cdd71a @gwoo more refactoring of test suite
gwoo authored
147 }
148
149 /**
f0f623e @indiefan Updated Report to use new Test Filter interface
indiefan authored
150 * Collects Results from the test filters and aggregates them.
151 *
0fddf6c @indiefan Refactored test filter interface to better handle raw filter results pri...
indiefan authored
152 * @param string $class Classname of the filter for which to aggregate results.
153 * @param array $results Array of the filter results for
f0f623e @indiefan Updated Report to use new Test Filter interface
indiefan authored
154 * later analysis by the filter itself.
155 * @return void
156 */
c552f97 @indiefan Renamed Report collectFilterResults to just be collect
indiefan authored
157 public function collect($class, $results) {
0fddf6c @indiefan Refactored test filter interface to better handle raw filter results pri...
indiefan authored
158 $this->results['filters'][$class][] = $results;
f0f623e @indiefan Updated Report to use new Test Filter interface
indiefan authored
159 }
160
161 /**
7cdd71a @gwoo more refactoring of test suite
gwoo authored
162 * undocumented function
163 *
164 * @return void
165 */
166 public function stats() {
81d6725 @gwoo test suite refactor is "working" still needs more cleanup and organizati...
gwoo authored
167 $results = (array) $this->results['group'];
36f1b2c @gwoo updating `\test\Unit` handling of array comparisons and exception report...
gwoo authored
168 $defaults = array(
169 'asserts' => 0,
170 'passes' => array(),
171 'fails' => array(),
172 'exceptions' => array(),
173 'errors' => array(),
174 'skips' => array()
175 );
176 $stats = array_reduce($results, function($stats, $result) use ($defaults) {
5616836 @gwoo `\core\Object::instance()` will return false or null `$name` is null
gwoo authored
177 $stats = (array) $stats + $defaults;
7cdd71a @gwoo more refactoring of test suite
gwoo authored
178 $result = empty($result[0]) ? array($result) : $result;
179 foreach ($result as $response) {
180 if (empty($response['result'])) {
181 continue;
182 }
183 $result = $response['result'];
184
185 if (in_array($result, array('fail', 'exception'))) {
a00543d @indiefan Moved test stat reporting into template and completely removed Html Repo...
indiefan authored
186 $response = array_merge(
187 array('class' => 'unknown', 'method' => 'unknown'), $response
188 );
7cdd71a @gwoo more refactoring of test suite
gwoo authored
189 $stats['errors'][] = $response;
190 }
191 unset($response['file'], $response['result']);
192
193 if (in_array($result, array('pass', 'fail'))) {
194 $stats['asserts']++;
195 }
b3601fc @gwoo adding skip rendering to \test
gwoo authored
196 if (in_array($result, array('pass', 'fail', 'exception', 'skip'))) {
7cdd71a @gwoo more refactoring of test suite
gwoo authored
197 $stats[Inflector::pluralize($result)][] = $response;
198 }
199 }
200 return $stats;
a00543d @indiefan Moved test stat reporting into template and completely removed Html Repo...
indiefan authored
201 });
126affc @nateabele Type fixes to handle test suite warnings.
nateabele authored
202 $stats = (array) $stats + $defaults;
a00543d @indiefan Moved test stat reporting into template and completely removed Html Repo...
indiefan authored
203 $count = array_map(
126affc @nateabele Type fixes to handle test suite warnings.
nateabele authored
204 function($value) { return is_array($value) ? count($value) : $value; }, $stats
a00543d @indiefan Moved test stat reporting into template and completely removed Html Repo...
indiefan authored
205 );
b3d0a5e @indiefan Fixed empty test run reporting color. Added 'Run All Tests' Button. Styl...
indiefan authored
206 $success = $count['passes'] == $count['asserts'] && $count['errors'] === 0;
a00543d @indiefan Moved test stat reporting into template and completely removed Html Repo...
indiefan authored
207 return compact("stats", "count", "success");
7cdd71a @gwoo more refactoring of test suite
gwoo authored
208 }
81d6725 @gwoo test suite refactor is "working" still needs more cleanup and organizati...
gwoo authored
209
7cdd71a @gwoo more refactoring of test suite
gwoo authored
210 /**
dca5abf @indiefan Refactored Test execution to filter in test bootstrap and removed Test C...
indiefan authored
211 * Renders the test output (e.g. layouts and filter templates)
212 *
213 * @param string $template name of the template (eg: layout)
214 * @param string $data array from `_data()` method
e5489e9 @indiefan Added options to Report render for format type
indiefan authored
215 * @param array $options Array of options (e.g. rendering type)
dca5abf @indiefan Refactored Test execution to filter in test bootstrap and removed Test C...
indiefan authored
216 * @return string
59cb735 @nateabele Ensuring `@filter` tags are present in docblocks that support filtering....
nateabele authored
217 * @filter
dca5abf @indiefan Refactored Test execution to filter in test bootstrap and removed Test C...
indiefan authored
218 */
97199ea @gwoo adding some filters for `\test\Dispatcher` and `\test\Report`
gwoo authored
219 public function render($template, $data = array()) {
220 $config = $this->_config;
ea0abeb @nateabele Refactoring the `Test` command to use typed output handlers, and consoli...
nateabele authored
221
222 if ($template == "stats" && !$data) {
d4a14da @indiefan Added test coverage for Report.
indiefan authored
223 $data = $this->stats();
224 }
97199ea @gwoo adding some filters for `\test\Dispatcher` and `\test\Report`
gwoo authored
225 $template = Libraries::locate("test.templates.{$config['reporter']}", $template, array(
26c2192 @davidpersson QA: Removing trailing comma in arrays, lowercasing some keywords.
davidpersson authored
226 'filter' => false, 'type' => 'file', 'suffix' => ".{$config['format']}.php"
dca5abf @indiefan Refactored Test execution to filter in test bootstrap and removed Test C...
indiefan authored
227 ));
97199ea @gwoo adding some filters for `\test\Dispatcher` and `\test\Report`
gwoo authored
228 $params = compact('template', 'data', 'config');
229
230 return $this->_filter(__METHOD__, $params, function($self, $params, $chain) {
231 extract($params['data']);
232 ob_start();
233 include $params['template'];
234 return ob_get_clean();
235 });
dca5abf @indiefan Refactored Test execution to filter in test bootstrap and removed Test C...
indiefan authored
236 }
944fd8f @indiefan Added filters method to Report to render all filters and updated html an...
indiefan authored
237
8ac8a36 @gwoo refactoring how filters are handled
gwoo authored
238 public function filters(array $filters = array()) {
ea0abeb @nateabele Refactoring the `Test` command to use typed output handlers, and consoli...
nateabele authored
239 if ($this->_filters && !$filters) {
8ac8a36 @gwoo refactoring how filters are handled
gwoo authored
240 return $this->_filters;
944fd8f @indiefan Added filters method to Report to render all filters and updated html an...
indiefan authored
241 }
8ac8a36 @gwoo refactoring how filters are handled
gwoo authored
242 $filters += (array) $this->_config['filters'];
243 $results = array();
ea0abeb @nateabele Refactoring the `Test` command to use typed output handlers, and consoli...
nateabele authored
244
8ac8a36 @gwoo refactoring how filters are handled
gwoo authored
245 foreach ($filters as $filter => $options) {
246 if (!$class = Libraries::locate('test.filter', $filter)) {
583059b @davidpersson Adding and replacing ticks/quotes with backticks in error and exception ...
davidpersson authored
247 throw new ClassNotFoundException("`{$class}` is not a valid test filter.");
8ac8a36 @gwoo refactoring how filters are handled
gwoo authored
248 }
249 $options['name'] = strtolower(join('', array_slice(explode("\\", $class), -1)));
250 $results[$class] = $options + array('apply' => array(), 'analyze' => array());
251 }
252 return $this->_filters = $results;
944fd8f @indiefan Added filters method to Report to render all filters and updated html an...
indiefan authored
253 }
fe822aa @gwoo initial work on test controller and reporters
gwoo authored
254 }
255
256 ?>
Something went wrong with that request. Please try again.