1 | <?php |
||
12 | abstract class BaseRunner |
||
13 | { |
||
14 | const PHPUNIT_FATAL_ERROR = 255; |
||
15 | |||
16 | /** |
||
17 | * @var Options |
||
18 | */ |
||
19 | protected $options; |
||
20 | |||
21 | /** |
||
22 | * @var \ParaTest\Logging\LogInterpreter |
||
23 | */ |
||
24 | protected $interpreter; |
||
25 | |||
26 | /** |
||
27 | * @var ResultPrinter |
||
28 | */ |
||
29 | protected $printer; |
||
30 | |||
31 | /** |
||
32 | * A collection of pending ExecutableTest objects that have |
||
33 | * yet to run |
||
34 | * |
||
35 | * @var array |
||
36 | */ |
||
37 | protected $pending = array(); |
||
38 | |||
39 | /** |
||
40 | * A collection of ExecutableTest objects that have processes |
||
41 | * currently running |
||
42 | * |
||
43 | * @var array |
||
44 | */ |
||
45 | protected $running = array(); |
||
46 | |||
47 | /** |
||
48 | * A tallied exit code that returns the highest exit |
||
49 | * code returned out of the entire collection of tests |
||
50 | * |
||
51 | * @var int |
||
52 | */ |
||
53 | protected $exitcode = -1; |
||
54 | |||
55 | /** |
||
56 | * CoverageMerger to hold track of the accumulated coverage |
||
57 | * |
||
58 | * @var CoverageMerger |
||
59 | */ |
||
60 | protected $coverage = null; |
||
61 | |||
62 | |||
63 | 8 | public function __construct($opts = array()) |
|
64 | { |
||
65 | 8 | $this->options = new Options($opts); |
|
66 | 8 | $this->interpreter = new LogInterpreter(); |
|
67 | 8 | $this->printer = new ResultPrinter($this->interpreter); |
|
68 | 8 | } |
|
69 | |||
70 | 2 | public function run() |
|
71 | { |
||
72 | 2 | $this->verifyConfiguration(); |
|
73 | 2 | $this->initCoverage(); |
|
74 | 2 | $this->load(); |
|
75 | 2 | $this->printer->start($this->options); |
|
76 | 2 | } |
|
77 | |||
78 | /** |
||
79 | * Ensures a valid configuration was supplied. If not |
||
80 | * causes ParaTest to print the error message and exit immediately |
||
81 | * with an exit code of 1 |
||
82 | */ |
||
83 | 2 | protected function verifyConfiguration() |
|
84 | { |
||
85 | 2 | if (isset($this->options->filtered['configuration']) && !file_exists($this->options->filtered['configuration']->getPath())) { |
|
86 | $this->printer->println(sprintf('Could not read "%s".', $this->options->filtered['configuration'])); |
||
87 | exit(1); |
||
|
|||
88 | } |
||
89 | 2 | } |
|
90 | |||
91 | /** |
||
92 | * Builds the collection of pending ExecutableTest objects |
||
93 | * to run. If functional mode is enabled $this->pending will |
||
94 | * contain a collection of TestMethod objects instead of Suite |
||
95 | * objects |
||
96 | */ |
||
97 | 2 | protected function load() |
|
98 | { |
||
99 | 2 | $loader = new SuiteLoader($this->options); |
|
100 | 2 | $loader->load($this->options->path); |
|
101 | 2 | $executables = $this->options->functional ? $loader->getTestMethods() : $loader->getSuites(); |
|
102 | 2 | $this->pending = array_merge($this->pending, $executables); |
|
103 | 2 | foreach ($this->pending as $pending) { |
|
104 | 2 | $this->printer->addTest($pending); |
|
105 | 2 | } |
|
106 | 2 | } |
|
107 | |||
108 | /** |
||
109 | * Returns the highest exit code encountered |
||
110 | * throughout the course of test execution |
||
111 | * |
||
112 | * @return int |
||
113 | */ |
||
114 | 1 | public function getExitCode() |
|
118 | |||
119 | /** |
||
120 | * Write output to JUnit format if requested |
||
121 | */ |
||
122 | 2 | protected function log() |
|
123 | { |
||
124 | 2 | if (!isset($this->options->filtered['log-junit'])) { |
|
125 | 1 | return; |
|
126 | } |
||
127 | 1 | $output = $this->options->filtered['log-junit']; |
|
128 | 1 | $writer = new Writer($this->interpreter, $this->options->path); |
|
129 | 1 | $writer->write($output); |
|
130 | 1 | } |
|
131 | |||
132 | /** |
||
133 | * Write coverage to file if requested |
||
134 | */ |
||
135 | 2 | protected function logCoverage() |
|
136 | { |
||
137 | 2 | if (!$this->hasCoverage()) { |
|
138 | return; |
||
139 | } |
||
140 | |||
141 | 2 | $filteredOptions = $this->options->filtered; |
|
142 | 2 | if (isset($filteredOptions['coverage-clover'])) { |
|
143 | 2 | $clover = new PHP_CodeCoverage_Report_Clover(); |
|
144 | $clover->process($this->getCoverage()->getCoverage(), $filteredOptions['coverage-clover']); |
||
145 | 2 | } |
|
146 | |||
147 | 2 | if (isset($filteredOptions['coverage-html'])) { |
|
148 | $html = new PHP_CodeCoverage_Report_HTML(); |
||
149 | 2 | $html->process($this->getCoverage()->getCoverage(), $filteredOptions['coverage-html']); |
|
150 | } |
||
151 | |||
152 | 2 | $php = new PHP_CodeCoverage_Report_PHP(); |
|
153 | 2 | $php->process($this->getCoverage()->getCoverage(), $filteredOptions['coverage-php']); |
|
154 | 2 | } |
|
155 | |||
156 | 2 | protected function initCoverage() |
|
157 | { |
||
158 | 2 | if (!isset($this->options->filtered['coverage-php'])) { |
|
159 | return; |
||
160 | } |
||
161 | |||
162 | 2 | $this->coverage = new CoverageMerger(); |
|
163 | 2 | } |
|
164 | |||
165 | 2 | protected function hasCoverage() |
|
169 | |||
170 | /** |
||
171 | * @return CoverageMerger |
||
172 | */ |
||
173 | 2 | public function getCoverage() |
|
177 | |||
178 | /** |
||
179 | * Returns coverage object from file. |
||
180 | * |
||
181 | * @param string $coverageFile Coverage file. |
||
182 | * |
||
183 | * @return \PHP_CodeCoverage |
||
184 | */ |
||
185 | 2 | protected function getCoverageObject($coverageFile) |
|
186 | { |
||
187 | 2 | $coverage = file_get_contents($coverageFile); |
|
188 | |||
189 | 2 | if (substr($coverage, 0, 5) === '<?php') { |
|
190 | return include $coverageFile; |
||
191 | } |
||
192 | |||
193 | // the PHPUnit 3.x and below |
||
194 | 2 | return unserialize($coverage); |
|
195 | } |
||
196 | |||
197 | /** |
||
198 | * Adds the coverage contained in $coverageFile and deletes the file afterwards |
||
199 | * @param $coverageFile |
||
200 | * @throws RuntimeException |
||
201 | */ |
||
202 | 2 | protected function addCoverageFromFile($coverageFile) |
|
215 | } |
||
216 |
An exit expression should only be used in rare cases. For example, if you write a short command line script.
In most cases however, using an
exit
expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.