83% of 778OPs |
84% of 119Lines |
66% of 67Branches |
63% of 54Paths |
# | |
---|---|
1 |
<?php |
2 |
|
3 |
namespace mageekguy\atoum\test; |
4 |
|
5 |
use |
6 |
mageekguy\atoum, |
7 |
mageekguy\atoum\fs\path, |
8 |
mageekguy\atoum\template, |
9 |
mageekguy\atoum\test\generator |
10 |
; |
11 |
|
12 |
class generator |
13 |
{ |
14 |
protected $templatesDirectory = ''; |
15 |
protected $testedClassesDirectory = null; |
16 |
protected $testedClassNamespace = null; |
17 |
protected $testClassesDirectory = null; |
18 |
protected $testClassNamespace = null; |
19 |
protected $testedClassPathExtractor = null; |
20 |
protected $fullyQualifiedTestClassNameExtractor = null; |
21 |
protected $fullyQualifiedTestedClassNameExtractor = null; |
22 |
protected $runnerPath = null; |
23 |
protected $templateParser = null; |
24 |
protected $pathFactory = null; |
25 |
protected $adapter = null; |
26 |
|
27 |
public function __construct()100% |
28 |
{ |
29 |
$this |
30 |
->setTemplatesDirectory() |
31 |
->setTemplateParser() |
32 |
->setPathFactory() |
33 |
->setAdapter() |
34 |
->setFullyQualifiedTestClassNameExtractor() |
35 |
->setFullyQualifiedTestedClassNameExtractor() |
36 |
->setTestedClassPathExtractor() |
37 |
; |
38 |
} |
39 |
|
40 |
public function setTemplatesDirectory($directory = null)100% |
41 |
{ |
42 |
$this->templatesDirectory = $directory ?: atoum\directory . DIRECTORY_SEPARATOR . 'resources' . DIRECTORY_SEPARATOR . 'templates' . DIRECTORY_SEPARATOR . 'test' . DIRECTORY_SEPARATOR . 'generator'; |
43 |
|
44 |
return $this; |
45 |
} |
46 |
|
47 |
public function getTemplatesDirectory()100% |
48 |
{ |
49 |
return $this->templatesDirectory; |
50 |
} |
51 |
|
52 |
public function setTestedClassesDirectory($directory)100% |
53 |
{ |
54 |
$this->testedClassesDirectory = self::cleanDirectory($directory); |
55 |
|
56 |
return $this; |
57 |
} |
58 |
|
59 |
public function getTestedClassesDirectory()100% |
60 |
{ |
61 |
return $this->testedClassesDirectory; |
62 |
} |
63 |
|
64 |
public function setTestClassesDirectory($directory)100% |
65 |
{ |
66 |
$this->testClassesDirectory = self::cleanDirectory($directory); |
67 |
|
68 |
return $this; |
69 |
} |
70 |
|
71 |
public function getTestClassesDirectory()100% |
72 |
{ |
73 |
return $this->testClassesDirectory; |
74 |
} |
75 |
|
76 |
public function setRunnerPath($path)100% |
77 |
{ |
78 |
$this->runnerPath = $path; |
79 |
|
80 |
return $this; |
81 |
} |
82 |
|
83 |
public function getRunnerPath()100% |
84 |
{ |
85 |
return $this->runnerPath; |
86 |
} |
87 |
|
88 |
public function setTemplateParser(template\parser $parser = null)100% |
89 |
{ |
90 |
$this->templateParser = $parser ?: new template\parser(); |
91 | |
92 |
return $this; |
93 |
} |
94 |
|
95 |
public function getTemplateParser()100% |
96 |
{ |
97 |
return $this->templateParser; |
98 |
} |
99 |
|
100 |
public function setPathFactory(path\factory $factory = null)100% |
101 |
{ |
102 |
$this->pathFactory = $factory ?: new path\factory(); |
103 |
|
104 |
return $this; |
105 |
} |
106 |
|
107 |
public function getPathFactory()100% |
108 |
{ |
109 |
return $this->pathFactory; |
110 |
} |
111 |
|
112 |
public function setAdapter(atoum\adapter $adapter = null)100% |
113 |
{ |
114 |
$this->adapter = $adapter ?: new atoum\adapter(); |
115 |
|
116 |
return $this; |
117 |
} |
118 |
|
119 |
public function getAdapter()100% |
120 |
{ |
121 |
return $this->adapter; |
122 |
} |
123 |
|
124 |
public function setTestedClassNamespace($namespace)100% |
125 |
{ |
126 |
$this->testedClassNamespace = self::cleanNamespace($namespace); |
127 |
|
128 |
return $this; |
129 |
} |
130 |
|
131 |
public function getTestedClassNamespace()100% |
132 |
{ |
133 |
return $this->testedClassNamespace; |
134 |
} |
135 |
|
136 |
public function setTestClassNamespace($namespace)100% |
137 |
{ |
138 |
$this->testClassNamespace = self::cleanNamespace($namespace); |
139 |
|
140 |
return $this; |
141 |
} |
142 |
|
143 |
public function getTestClassNamespace()100% |
144 |
{ |
145 |
return $this->testClassNamespace; |
146 |
} |
147 |
|
148 |
public function setFullyQualifiedTestClassNameExtractor(\closure $extractor = null)75% |
149 |
{ |
150 |
$this->fullyQualifiedTestClassNameExtractor = $extractor ?: function($generator, $relativeTestClassPath) { |
151 |
return $generator->getTestClassNamespace() . str_replace(DIRECTORY_SEPARATOR, '\\', substr($relativeTestClassPath, 0, -4)); |
152 |
}; |
153 |
|
154 |
return $this; |
155 |
} |
156 |
|
157 |
public function getFullyQualifiedTestClassNameExtractor()100% |
158 |
{ |
159 |
return $this->fullyQualifiedTestClassNameExtractor; |
160 |
} |
161 |
|
162 |
public function setFullyQualifiedTestedClassNameExtractor(\closure $extractor = null)75% |
163 |
{ |
164 |
$this->fullyQualifiedTestedClassNameExtractor = $extractor ?: function($generator, $fullyQualifiedTestClassName) { |
165 |
return $generator->getTestedClassNamespace() . substr($fullyQualifiedTestClassName, strlen($generator->getTestClassNamespace())); |
166 |
}; |
167 |
|
168 |
return $this; |
169 |
} |
170 |
|
171 |
public function getFullyQualifiedTestedClassNameExtractor()100% |
172 |
{ |
173 |
return $this->fullyQualifiedTestedClassNameExtractor; |
174 |
} |
175 |
|
176 |
public function setTestedClassPathExtractor(\closure $extractor = null)75% |
177 |
{ |
178 |
$this->testedClassPathExtractor = $extractor ?: function($generator, $fullyQualifiedTestedClassName) { |
179 |
return $generator->getTestedClassesDirectory() . substr(str_replace('\\', DIRECTORY_SEPARATOR, $fullyQualifiedTestedClassName), strlen($generator->getTestedClassNamespace())) . '.php'; |
180 |
}; |
181 |
|
182 |
return $this; |
183 |
} |
184 |
|
185 |
public function getTestedClassPathExtractor()100% |
186 |
{ |
187 |
return $this->testedClassPathExtractor; |
188 |
} |
189 |
|
190 |
public function generate($testClassPath)79% |
191 |
{ |
192 |
if ($this->testedClassesDirectory === null) |
193 |
{ |
194 |
throw new generator\exception('Tested classes directory is undefined'); |
195 |
} |
196 | |
197 |
if ($this->testClassesDirectory === null) |
198 |
{ |
199 |
throw new generator\exception('Tests directory is undefined'); |
200 |
} |
201 |
|
202 |
if ($this->testedClassNamespace === null) |
203 |
{ |
204 |
throw new generator\exception('Tested class namespace is undefined'); |
205 |
} |
206 |
|
207 |
if ($this->testClassNamespace === null) |
208 |
{ |
209 |
throw new generator\exception('Test class namespace is undefined'); |
210 |
} |
211 |
|
212 |
$testClassesDirectory = $this->pathFactory->build($this->testClassesDirectory); |
213 |
|
214 |
if ($testClassesDirectory->exists() === false) |
215 |
{ |
216 |
throw new generator\exception('Test classes directory \'' . $testClassesDirectory . '\' does not exist'); |
217 |
} |
218 |
|
219 |
$realTestClassesDirectory = $testClassesDirectory->getRealPath(); |
220 |
$realTestClassPath = $this->pathFactory->build($testClassPath)->getRealPath(); |
221 |
$realTestClassBaseDirectory = $realTestClassPath->getRealParentDirectoryPath(); |
222 |
|
223 |
if ((string) $realTestClassesDirectory !== (string) $realTestClassBaseDirectory && $realTestClassBaseDirectory->isSubPathOf($realTestClassesDirectory) === false) |
224 |
{ |
225 |
throw new generator\exception('Path \'' . $testClassPath . '\' is not in directory \'' . $this->testClassesDirectory . '\''); |
226 |
} |
227 |
|
228 |
$realTestClassRelativePath = substr($realTestClassPath->getRelativePathFrom($realTestClassesDirectory), 2); |
229 |
|
230 |
$fullyQualifiedTestClassName = call_user_func_array($this->fullyQualifiedTestClassNameExtractor, array($this, $realTestClassRelativePath)); |
231 |
|
232 |
$testClassTemplate = $this->templateParser->parseFile($this->templatesDirectory . DIRECTORY_SEPARATOR . 'testClass.php'); |
233 |
|
234 |
$testClassTemplate->fullyQualifiedTestClassName = $fullyQualifiedTestClassName; |
235 |
$testClassTemplate->testClassName = self::getShortClassName($fullyQualifiedTestClassName); |
236 |
$testClassTemplate->testClassNamespace = self::getClassNamespace($fullyQualifiedTestClassName); |
237 |
|
238 |
if ($this->runnerPath !== null) |
239 |
{ |
240 |
$runnerPath = $this->pathFactory->build($this->runnerPath); |
241 |
$relativeRunnerPath = $runnerPath->relativizeFrom($realTestClassBaseDirectory); |
242 |
|
243 |
$testClassTemplate->requireRunner->relativeRunnerPath = $relativeRunnerPath; |
244 |
$testClassTemplate->requireRunner->build(); |
245 |
} |
246 |
|
247 |
$fullyQualifiedTestedClassName = call_user_func_array($this->fullyQualifiedTestedClassNameExtractor, array($this, $fullyQualifiedTestClassName)); |
248 |
|
249 |
if ($this->adapter->class_exists($fullyQualifiedTestedClassName) === false) |
250 |
{ |
251 |
$testClassTemplate->testMethods->testMethod->methodName = '__construct'; |
252 |
$testClassTemplate->testMethods->testMethod->methodName->build(); |
253 |
$testClassTemplate->testMethods->testMethod->build(); |
254 |
|
255 |
$testedClassPath = $this->pathFactory->build(call_user_func_array($this->testedClassPathExtractor, array($this, $fullyQualifiedTestedClassName))); |
256 |
|
257 |
$testedClassTemplate = $this->templateParser->parseFile($this->templatesDirectory . DIRECTORY_SEPARATOR . 'testedClass.php'); |
258 |
|
259 |
$testedClassTemplate->testedClassName = self::getShortClassName($fullyQualifiedTestedClassName); |
260 |
$testedClassTemplate->testedClassNamespace = self::getClassNamespace($fullyQualifiedTestedClassName); |
261 |
|
262 |
$testedClassPath->putContents($testedClassTemplate->build()); |
263 |
} |
264 |
else |
265 |
{ |
266 |
$testedClass = new \reflectionClass($fullyQualifiedTestedClassName); |
267 |
|
268 |
foreach ($testedClass->getMethods(\reflectionMethod::IS_PUBLIC) as $publicMethod) |
269 |
{ |
270 |
$testClassTemplate->testMethods->testMethod->methodName = $publicMethod->getName(); |
271 |
$testClassTemplate->testMethods->testMethod->methodName->build(); |
272 |
$testClassTemplate->testMethods->testMethod->build(); |
273 |
} |
274 |
} |
275 |
|
276 |
$testClassTemplate->testMethods->build(); |
277 |
|
278 |
$realTestClassPath->putContents($testClassTemplate->build()); |
279 |
|
280 |
return $this; |
281 |
} |
282 |
|
283 |
protected function saveClassInFile($class, $file)0% |
284 |
{ |
285 |
if (@$this->adapter->file_put_contents($file, $class) === false) |
286 |
{ |
287 |
throw new generator\exception('Unable to write in file \'' . $file . '\''); |
288 |
} |
289 |
|
290 |
return $this; |
291 |
} |
292 |
|
293 |
protected static function cleanDirectory($path)100% |
294 |
{ |
295 |
return rtrim($path, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR; |
296 |
} |
297 |
|
298 |
protected static function cleanNamespace($namespace)100% |
299 |
{ |
300 |
return trim($namespace, '\\') . '\\'; |
301 |
} |
302 |
|
303 |
protected static function getShortClassName($fullyQualifiedClassName)100% |
304 |
{ |
305 |
return basename(str_replace('\\', DIRECTORY_SEPARATOR, $fullyQualifiedClassName)); |
306 |
} |
307 |
|
308 |
protected static function getClassNamespace($fullyQualifiedClassName)100% |
309 |
{ |
310 |
return str_replace(DIRECTORY_SEPARATOR, '\\', dirname(str_replace('\\', DIRECTORY_SEPARATOR, $fullyQualifiedClassName))); |
311 |
} |
312 |
} |