Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 259 lines (236 sloc) 7.091 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()` 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
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 *
ba697b8 @davidpersson Fixing formatting in docblocks.
davidpersson authored
35 * // Get the test stats:
8dd7503 @jperras Adding class doc blocks to `test\Report`.
jperras authored
36 * $report->stats();
37 *
ba697b8 @davidpersson Fixing formatting in docblocks.
davidpersson authored
38 * // Get test results:
8dd7503 @jperras Adding class doc blocks to `test\Report`.
jperras authored
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 *
ba697b8 @davidpersson Fixing formatting in docblocks.
davidpersson authored
54 * // Get test results, including filter results:
8dd7503 @jperras Adding class doc blocks to `test\Report`.
jperras authored
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 *
ba697b8 @davidpersson Fixing formatting in docblocks.
davidpersson authored
68 * @see lithium\test\Group
fe822aa @gwoo initial work on test controller and reporters
gwoo authored
69 * @var object
70 */
71 public $group = null;
72
73 /**
ba697b8 @davidpersson Fixing formatting in docblocks.
davidpersson authored
74 * Title of the group being run.
7cdd71a @gwoo more refactoring of test suite
gwoo authored
75 *
76 * @var string
77 */
ba697b8 @davidpersson Fixing formatting in docblocks.
davidpersson authored
78 public $title;
7cdd71a @gwoo more refactoring of test suite
gwoo authored
79
80 /**
ba697b8 @davidpersson Fixing formatting in docblocks.
davidpersson authored
81 * Group and filter results.
7cdd71a @gwoo more refactoring of test suite
gwoo authored
82 *
83 * @var array
84 */
85 public $results = array('group' => array(), 'filters' => array());
86
87 /**
ba697b8 @davidpersson Fixing formatting in docblocks.
davidpersson authored
88 * Start and end timers.
7cdd71a @gwoo more refactoring of test suite
gwoo authored
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 /**
ba697b8 @davidpersson Fixing formatting in docblocks.
davidpersson authored
103 * Constructor.
7cdd71a @gwoo more refactoring of test suite
gwoo authored
104 *
105 * @param array $config Options array for the test run. Valid options are:
dc68018 @davidpersson Synchronizing defaults in test `Report` and `Dispatcher`.
davidpersson authored
106 * - `'group'`: The test group with items to be run.
107 * - `'filters'`: An array of filters that the test output should be run through.
266559b @davidpersson Refitting test reporter as progress reporter.
davidpersson authored
108 * - `'format'`: The format of the template to use, defaults to `'txt'`.
109 * - `'reporter'`: The reporter to use.
7cdd71a @gwoo more refactoring of test suite
gwoo authored
110 */
f80098d @nateabele Adding type hinting to constructor `$config` arrays and all applicable `...
nateabele authored
111 public function __construct(array $config = array()) {
7cdd71a @gwoo more refactoring of test suite
gwoo authored
112 $defaults = array(
eb53e19 @gwoo adding some coverage for \test\Report
gwoo authored
113 'title' => null,
7cdd71a @gwoo more refactoring of test suite
gwoo authored
114 'group' => null,
115 'filters' => array(),
952d9a5 @davidpersson Initial implementation of console test progress.
davidpersson authored
116 'format' => 'txt',
0408339 @davidpersson Removing progress filter option.
davidpersson authored
117 'reporter' => null
7cdd71a @gwoo more refactoring of test suite
gwoo authored
118 );
126affc @nateabele Type fixes to handle test suite warnings.
nateabele authored
119 parent::__construct($config + $defaults);
7cdd71a @gwoo more refactoring of test suite
gwoo authored
120 }
fe822aa @gwoo initial work on test controller and reporters
gwoo authored
121
7cdd71a @gwoo more refactoring of test suite
gwoo authored
122 /**
ba697b8 @davidpersson Fixing formatting in docblocks.
davidpersson authored
123 * Initializer.
7cdd71a @gwoo more refactoring of test suite
gwoo authored
124 *
125 * @return void
126 */
fe822aa @gwoo initial work on test controller and reporters
gwoo authored
127 protected function _init() {
7cdd71a @gwoo more refactoring of test suite
gwoo authored
128 $this->group = $this->_config['group'];
129 $this->title = $this->_config['title'] ?: $this->_config['title'];
fe822aa @gwoo initial work on test controller and reporters
gwoo authored
130 }
1e23d77 @gwoo hacking on Report
gwoo authored
131
7cdd71a @gwoo more refactoring of test suite
gwoo authored
132 /**
ba697b8 @davidpersson Fixing formatting in docblocks.
davidpersson authored
133 * Runs tests.
7cdd71a @gwoo more refactoring of test suite
gwoo authored
134 *
135 * @return void
136 */
137 public function run() {
138 $tests = $this->group->tests();
e6cd7c1 @davidpersson Adding `Base` test filter.
davidpersson authored
139
8ac8a36 @gwoo refactoring how filters are handled
gwoo authored
140 foreach ($this->filters() as $filter => $options) {
141 $this->results['filters'][$filter] = array();
142 $tests = $filter::apply($this, $tests, $options['apply']) ?: $tests;
1e23d77 @gwoo hacking on Report
gwoo authored
143 }
266559b @davidpersson Refitting test reporter as progress reporter.
davidpersson authored
144 $this->results['group'] = $tests->run(array(
145 'reporter' => $this->_config['reporter']
146 ));
1e23d77 @gwoo hacking on Report
gwoo authored
147
8ac8a36 @gwoo refactoring how filters are handled
gwoo authored
148 foreach ($this->filters() as $filter => $options) {
149 $this->results['filters'][$filter] = $filter::analyze($this, $options['analyze']);
1e23d77 @gwoo hacking on Report
gwoo authored
150 }
7cdd71a @gwoo more refactoring of test suite
gwoo authored
151 }
152
153 /**
f0f623e @indiefan Updated Report to use new Test Filter interface
indiefan authored
154 * Collects Results from the test filters and aggregates them.
155 *
0fddf6c @indiefan Refactored test filter interface to better handle raw filter results pri...
indiefan authored
156 * @param string $class Classname of the filter for which to aggregate results.
157 * @param array $results Array of the filter results for
ba697b8 @davidpersson Fixing formatting in docblocks.
davidpersson authored
158 * later analysis by the filter itself.
f0f623e @indiefan Updated Report to use new Test Filter interface
indiefan authored
159 * @return void
160 */
c552f97 @indiefan Renamed Report collectFilterResults to just be collect
indiefan authored
161 public function collect($class, $results) {
0fddf6c @indiefan Refactored test filter interface to better handle raw filter results pri...
indiefan authored
162 $this->results['filters'][$class][] = $results;
f0f623e @indiefan Updated Report to use new Test Filter interface
indiefan authored
163 }
164
165 /**
ba697b8 @davidpersson Fixing formatting in docblocks.
davidpersson authored
166 * Return statistics from the test runs.
7cdd71a @gwoo more refactoring of test suite
gwoo authored
167 *
ba697b8 @davidpersson Fixing formatting in docblocks.
davidpersson authored
168 * @return array
7cdd71a @gwoo more refactoring of test suite
gwoo authored
169 */
170 public function stats() {
81d6725 @gwoo test suite refactor is "working" still needs more cleanup and organizati...
gwoo authored
171 $results = (array) $this->results['group'];
36f1b2c @gwoo updating `\test\Unit` handling of array comparisons and exception report...
gwoo authored
172 $defaults = array(
173 'asserts' => 0,
174 'passes' => array(),
175 'fails' => array(),
176 'exceptions' => array(),
177 'errors' => array(),
178 'skips' => array()
179 );
180 $stats = array_reduce($results, function($stats, $result) use ($defaults) {
5616836 @gwoo `\core\Object::instance()` will return false or null `$name` is null
gwoo authored
181 $stats = (array) $stats + $defaults;
7cdd71a @gwoo more refactoring of test suite
gwoo authored
182 $result = empty($result[0]) ? array($result) : $result;
183 foreach ($result as $response) {
184 if (empty($response['result'])) {
185 continue;
186 }
187 $result = $response['result'];
188
189 if (in_array($result, array('fail', 'exception'))) {
a00543d @indiefan Moved test stat reporting into template and completely removed Html Repo...
indiefan authored
190 $response = array_merge(
191 array('class' => 'unknown', 'method' => 'unknown'), $response
192 );
7cdd71a @gwoo more refactoring of test suite
gwoo authored
193 $stats['errors'][] = $response;
194 }
195 unset($response['file'], $response['result']);
196
197 if (in_array($result, array('pass', 'fail'))) {
198 $stats['asserts']++;
199 }
b3601fc @gwoo adding skip rendering to \test
gwoo authored
200 if (in_array($result, array('pass', 'fail', 'exception', 'skip'))) {
7cdd71a @gwoo more refactoring of test suite
gwoo authored
201 $stats[Inflector::pluralize($result)][] = $response;
202 }
203 }
204 return $stats;
a00543d @indiefan Moved test stat reporting into template and completely removed Html Repo...
indiefan authored
205 });
126affc @nateabele Type fixes to handle test suite warnings.
nateabele authored
206 $stats = (array) $stats + $defaults;
a00543d @indiefan Moved test stat reporting into template and completely removed Html Repo...
indiefan authored
207 $count = array_map(
126affc @nateabele Type fixes to handle test suite warnings.
nateabele authored
208 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
209 );
b3d0a5e @indiefan Fixed empty test run reporting color. Added 'Run All Tests' Button. Styl...
indiefan authored
210 $success = $count['passes'] == $count['asserts'] && $count['errors'] === 0;
ba697b8 @davidpersson Fixing formatting in docblocks.
davidpersson authored
211 return compact('stats', 'count', 'success');
7cdd71a @gwoo more refactoring of test suite
gwoo authored
212 }
81d6725 @gwoo test suite refactor is "working" still needs more cleanup and organizati...
gwoo authored
213
7cdd71a @gwoo more refactoring of test suite
gwoo authored
214 /**
ba697b8 @davidpersson Fixing formatting in docblocks.
davidpersson authored
215 * Renders the test output (e.g. layouts and filter templates).
dca5abf @indiefan Refactored Test execution to filter in test bootstrap and removed Test C...
indiefan authored
216 *
ba697b8 @davidpersson Fixing formatting in docblocks.
davidpersson authored
217 * @param string $template name of the template (i.e. `'layout'`).
218 * @param string|array $data array from `_data()` method.
dca5abf @indiefan Refactored Test execution to filter in test bootstrap and removed Test C...
indiefan authored
219 * @return string
59cb735 @nateabele Ensuring `@filter` tags are present in docblocks that support filtering....
nateabele authored
220 * @filter
dca5abf @indiefan Refactored Test execution to filter in test bootstrap and removed Test C...
indiefan authored
221 */
97199ea @gwoo adding some filters for `\test\Dispatcher` and `\test\Report`
gwoo authored
222 public function render($template, $data = array()) {
223 $config = $this->_config;
ea0abeb @nateabele Refactoring the `Test` command to use typed output handlers, and consoli...
nateabele authored
224
225 if ($template == "stats" && !$data) {
d4a14da @indiefan Added test coverage for Report.
indiefan authored
226 $data = $this->stats();
227 }
266559b @davidpersson Refitting test reporter as progress reporter.
davidpersson authored
228 $template = Libraries::locate('test.templates', $template, array(
26c2192 @davidpersson QA: Removing trailing comma in arrays, lowercasing some keywords.
davidpersson authored
229 'filter' => false, 'type' => 'file', 'suffix' => ".{$config['format']}.php"
dca5abf @indiefan Refactored Test execution to filter in test bootstrap and removed Test C...
indiefan authored
230 ));
97199ea @gwoo adding some filters for `\test\Dispatcher` and `\test\Report`
gwoo authored
231 $params = compact('template', 'data', 'config');
232
233 return $this->_filter(__METHOD__, $params, function($self, $params, $chain) {
234 extract($params['data']);
235 ob_start();
236 include $params['template'];
237 return ob_get_clean();
238 });
dca5abf @indiefan Refactored Test execution to filter in test bootstrap and removed Test C...
indiefan authored
239 }
944fd8f @indiefan Added filters method to Report to render all filters and updated html an...
indiefan authored
240
8ac8a36 @gwoo refactoring how filters are handled
gwoo authored
241 public function filters(array $filters = array()) {
ea0abeb @nateabele Refactoring the `Test` command to use typed output handlers, and consoli...
nateabele authored
242 if ($this->_filters && !$filters) {
8ac8a36 @gwoo refactoring how filters are handled
gwoo authored
243 return $this->_filters;
944fd8f @indiefan Added filters method to Report to render all filters and updated html an...
indiefan authored
244 }
8ac8a36 @gwoo refactoring how filters are handled
gwoo authored
245 $filters += (array) $this->_config['filters'];
246 $results = array();
ea0abeb @nateabele Refactoring the `Test` command to use typed output handlers, and consoli...
nateabele authored
247
8ac8a36 @gwoo refactoring how filters are handled
gwoo authored
248 foreach ($filters as $filter => $options) {
249 if (!$class = Libraries::locate('test.filter', $filter)) {
583059b @davidpersson Adding and replacing ticks/quotes with backticks in error and exception ...
davidpersson authored
250 throw new ClassNotFoundException("`{$class}` is not a valid test filter.");
8ac8a36 @gwoo refactoring how filters are handled
gwoo authored
251 }
252 $options['name'] = strtolower(join('', array_slice(explode("\\", $class), -1)));
253 $results[$class] = $options + array('apply' => array(), 'analyze' => array());
254 }
255 return $this->_filters = $results;
944fd8f @indiefan Added filters method to Report to render all filters and updated html an...
indiefan authored
256 }
fe822aa @gwoo initial work on test controller and reporters
gwoo authored
257 }
258
259 ?>
Something went wrong with that request. Please try again.