5 * Copyright (c) 2002-2009, Sebastian Bergmann <sb@sebastian-bergmann.de>.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * * Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
15 * * Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in
17 * the documentation and/or other materials provided with the
20 * * Neither the name of Sebastian Bergmann nor the names of his
21 * contributors may be used to endorse or promote products derived
22 * from this software without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
27 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
28 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
29 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
30 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
34 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
39 * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
40 * @copyright 2002-2009 Sebastian Bergmann <sb@sebastian-bergmann.de>
41 * @license http://www.opensource.org/licenses/bsd-license.php BSD License
43 * @link http://www.phpunit.de/
44 * @since File available since Release 3.3.0
47 require_once 'PHPUnit/Util/Filter.php';
48 require_once 'PHPUnit/Util/Template.php';
49 require_once 'PHPUnit/Util/Skeleton.php';
51 PHPUnit_Util_Filter::addFileToFilter(__FILE__, 'PHPUNIT');
54 * Generator for class skeletons from test classes.
58 * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
59 * @copyright 2002-2009 Sebastian Bergmann <sb@sebastian-bergmann.de>
60 * @license http://www.opensource.org/licenses/bsd-license.php BSD License
61 * @version Release: 3.3.17
62 * @link http://www.phpunit.de/
63 * @since Class available since Release 3.3.0
65 class PHPUnit_Util_Skeleton_Class extends PHPUnit_Util_Skeleton
67 protected $tokens = array();
72 * @param string $inClassName
73 * @param string $inSourceFile
74 * @throws RuntimeException
76 public function __construct($inClassName, $inSourceFile = '')
78 if (empty($inSourceFile)) {
79 $this->inSourceFile = $inClassName . '.php';
81 $this->inSourceFile = $inSourceFile;
84 if (!is_file($inSourceFile)) {
85 throw new RuntimeException(
87 '"%s" could not be opened.',
94 $this->tokens = token_get_all(file_get_contents($inSourceFile));
96 $this->inClassName = $inClassName;
97 $this->outClassName = substr($inClassName, 0, strlen($inClassName) - 4);
98 $this->outSourceFile = dirname($this->inSourceFile) . DIRECTORY_SEPARATOR . $this->outClassName . '.php';
102 * Generates the class' source.
106 public function generate()
110 foreach ($this->findMethods() as $method) {
111 $methodTemplate = new PHPUnit_Util_Template(
113 '%s%sTemplate%sMethod.tpl',
121 $methodTemplate->setVar(
123 'methodName' => $method,
127 $methods .= $methodTemplate->render();
130 $classTemplate = new PHPUnit_Util_Template(
132 '%s%sTemplate%sClass.tpl',
140 $classTemplate->setVar(
142 'className' => $this->outClassName,
143 'methods' => $methods,
144 'date' => date('Y-m-d'),
145 'time' => date('H:i:s')
149 return $classTemplate->render();
153 * Returns the methods of the class under test
154 * that are called from the test methods.
158 protected function findMethods()
161 $numTokens = count($this->tokens);
162 $variables = $this->findVariablesThatReferenceClass();
164 for ($i = 0; $i < $numTokens; $i++) {
165 if (is_array($this->tokens[$i])) {
166 if ($this->tokens[$i][0] == T_DOUBLE_COLON &&
167 $this->tokens[$i-1][0] == T_STRING &&
168 $this->tokens[$i+1][0] == T_STRING &&
169 trim($this->tokens[$i+2]) == '(' &&
170 !in_array($this->tokens[$i+1][1], $methods)) {
171 $methods[] = $this->tokens[$i+1][1];
174 else if ($this->tokens[$i][0] == T_OBJECT_OPERATOR &&
175 is_string($this->tokens[$i+2]) && trim($this->tokens[$i+2]) == '(' &&
176 in_array($this->findVariableName($i), $variables) &&
177 !in_array($this->tokens[$i+1][1], $methods)) {
178 $methods[] = $this->tokens[$i+1][1];
189 * Returns the variables used in test methods
190 * that reference the class under test.
194 protected function findVariablesThatReferenceClass()
197 $numTokens = count($this->tokens);
198 $variables = array();
200 for ($i = 0; $i < $numTokens; $i++) {
201 if (is_string($this->tokens[$i])) {
202 if (trim($this->tokens[$i]) == ';') {
209 list ($_token, $_value) = $this->tokens[$i];
219 if ($_value == $this->outClassName) {
220 $variables[] = $this->findVariableName($i);
234 * Finds the variable name of the object for the method call
235 * that is currently being processed.
237 * @param integer $start
240 protected function findVariableName($start)
242 for ($i = $start - 1; $i >= 0; $i--) {
243 if (is_array($this->tokens[$i]) && $this->tokens[$i][0] == T_VARIABLE) {
244 $variable = $this->tokens[$i][1];
246 if (is_array($this->tokens[$i+1]) && $this->tokens[$i+1][0] == T_OBJECT_OPERATOR) {
247 $variable .= '->' . $this->tokens[$i+2][1];