Skip to content

HTTPS clone URL

Subversion checkout URL

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