1
+ <?php namespace ParaTest \Runners \PHPUnit ;
2
+
3
+ use ParaTest \Coverage \CoverageMerger ;
4
+ use ParaTest \Logging \LogInterpreter ;
5
+ use ParaTest \Logging \JUnit \Writer ;
6
+ use PHP_CodeCoverage_Report_Clover ;
7
+ use PHP_CodeCoverage_Report_HTML ;
8
+ use PHP_CodeCoverage_Report_PHP ;
9
+ use RuntimeException ;
10
+
11
+
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
+ public function __construct ($ opts = array ())
64
+ {
65
+ $ this ->options = new Options ($ opts );
66
+ $ this ->interpreter = new LogInterpreter ();
67
+ $ this ->printer = new ResultPrinter ($ this ->interpreter );
68
+ }
69
+
70
+ public function run ()
71
+ {
72
+ $ this ->verifyConfiguration ();
73
+ $ this ->initCoverage ();
74
+ $ this ->load ();
75
+ $ this ->printer ->start ($ this ->options );
76
+ }
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
+ protected function verifyConfiguration ()
84
+ {
85
+ 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
+ }
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
+ protected function load ()
98
+ {
99
+ $ loader = new SuiteLoader ($ this ->options );
100
+ $ loader ->load ($ this ->options ->path );
101
+ $ executables = $ this ->options ->functional ? $ loader ->getTestMethods () : $ loader ->getSuites ();
102
+ $ this ->pending = array_merge ($ this ->pending , $ executables );
103
+ foreach ($ this ->pending as $ pending ) {
104
+ $ this ->printer ->addTest ($ pending );
105
+ }
106
+ }
107
+
108
+ /**
109
+ * Returns the highest exit code encountered
110
+ * throughout the course of test execution
111
+ *
112
+ * @return int
113
+ */
114
+ public function getExitCode ()
115
+ {
116
+ return $ this ->exitcode ;
117
+ }
118
+
119
+ /**
120
+ * Write output to JUnit format if requested
121
+ */
122
+ protected function log ()
123
+ {
124
+ if (!isset ($ this ->options ->filtered ['log-junit ' ])) {
125
+ return ;
126
+ }
127
+ $ output = $ this ->options ->filtered ['log-junit ' ];
128
+ $ writer = new Writer ($ this ->interpreter , $ this ->options ->path );
129
+ $ writer ->write ($ output );
130
+ }
131
+
132
+ /**
133
+ * Write coverage to file if requested
134
+ */
135
+ protected function logCoverage ()
136
+ {
137
+ if (!$ this ->hasCoverage ()) {
138
+ return ;
139
+ }
140
+
141
+ $ filteredOptions = $ this ->options ->filtered ;
142
+ if (isset ($ filteredOptions ['coverage-clover ' ])) {
143
+ $ clover = new PHP_CodeCoverage_Report_Clover ();
144
+ $ clover ->process ($ this ->getCoverage ()->getCoverage (), $ filteredOptions ['coverage-clover ' ]);
145
+ }
146
+
147
+ if (isset ($ filteredOptions ['coverage-html ' ])) {
148
+ $ html = new PHP_CodeCoverage_Report_HTML ();
149
+ $ html ->process ($ this ->getCoverage ()->getCoverage (), $ filteredOptions ['coverage-html ' ]);
150
+ }
151
+
152
+ $ php = new PHP_CodeCoverage_Report_PHP ();
153
+ $ php ->process ($ this ->getCoverage ()->getCoverage (), $ filteredOptions ['coverage-php ' ]);
154
+ }
155
+
156
+ protected function initCoverage ()
157
+ {
158
+ if (!isset ($ this ->options ->filtered ['coverage-php ' ])) {
159
+ return ;
160
+ }
161
+
162
+ $ this ->coverage = new CoverageMerger ();
163
+ }
164
+
165
+ protected function hasCoverage ()
166
+ {
167
+ return $ this ->getCoverage () != null ;
168
+ }
169
+
170
+ /**
171
+ * @return CoverageMerger
172
+ */
173
+ public function getCoverage ()
174
+ {
175
+ return $ this ->coverage ;
176
+ }
177
+
178
+ /**
179
+ * Returns coverage object from file.
180
+ *
181
+ * @param string $coverageFile Coverage file.
182
+ *
183
+ * @return \PHP_CodeCoverage
184
+ */
185
+ protected function getCoverageObject ($ coverageFile )
186
+ {
187
+ $ coverage = file_get_contents ($ coverageFile );
188
+
189
+ if (substr ($ coverage , 0 , 5 ) === '<?php ' ) {
190
+ return include $ coverageFile ;
191
+ }
192
+
193
+ // the PHPUnit 3.x and below
194
+ 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
+ protected function addCoverageFromFile ($ coverageFile )
203
+ {
204
+ if ($ coverageFile === null || !file_exists ($ coverageFile )) {
205
+ return ;
206
+ }
207
+
208
+ if (filesize ($ coverageFile ) == 0 ) {
209
+ throw new RuntimeException ("Coverage file $ coverageFile is empty. This means a PHPUnit process has crashed. " );
210
+ }
211
+
212
+ $ this ->getCoverage ()->addCoverage ($ this ->getCoverageObject ($ coverageFile ));
213
+ unlink ($ coverageFile );
214
+ }
215
+
216
+ }
0 commit comments