20
20
*/
21
21
class ConsolePrinter implements Tester \Runner \OutputHandler
22
22
{
23
- private Runner $ runner ;
24
-
25
23
/** @var resource */
26
24
private $ file ;
27
- private bool $ displaySkipped = false ;
28
- private string $ buffer ;
25
+
26
+ /** @var list<string> */
27
+ private array $ buffer ;
28
+
29
+ /**
30
+ * @phpstan-var array<Alias_TestResultState, string>
31
+ * @var array<int, string>
32
+ */
33
+ private array $ symbols ;
34
+
35
+ /**
36
+ * @phpstan-var array<Alias_TestResultState, int>
37
+ * @var array<int, string>
38
+ */
39
+ private array $ results = [
40
+ Test::Passed => 0 ,
41
+ Test::Skipped => 0 ,
42
+ Test::Failed => 0 ,
43
+ ];
44
+
29
45
private float $ time ;
30
46
private int $ count ;
31
- private array $ results ;
32
47
private ?string $ baseDir ;
33
- private array $ symbols ;
34
-
48
+ private int $ resultsCount = 0 ;
35
49
50
+ /**
51
+ * @param bool $lineMode If `true`, reports each finished test on separate line.
52
+ */
36
53
public function __construct (
37
- Runner $ runner ,
38
- bool $ displaySkipped = false ,
54
+ private Runner $ runner ,
55
+ private bool $ displaySkipped = false ,
39
56
?string $ file = null ,
40
57
bool $ ciderMode = false ,
58
+ private bool $ lineMode = false ,
41
59
) {
42
60
$ this ->runner = $ runner ;
43
61
$ this ->displaySkipped = $ displaySkipped ;
44
62
$ this ->file = fopen ($ file ?: 'php://output ' , 'w ' );
63
+
45
64
$ this ->symbols = [
46
- Test::Passed => $ ciderMode ? Dumper::color ('green ' , '🍎 ' ) : '. ' ,
47
- Test::Skipped => 's ' ,
48
- Test::Failed => $ ciderMode ? Dumper::color ('red ' , '🍎 ' ) : Dumper::color ('white/red ' , 'F ' ),
65
+ Test::Passed => $ this -> lineMode ? Dumper::color ('lime ' , 'OK ' ) : '. ' ,
66
+ Test::Skipped => $ this -> lineMode ? Dumper:: color ( ' yellow ' , ' SKIP ' ) : 's ' ,
67
+ Test::Failed => $ this -> lineMode ? Dumper::color ('white/ red ' , 'FAIL ' ) : Dumper::color ('white/red ' , 'F ' ),
49
68
];
69
+
70
+ if ($ ciderMode ) {
71
+ $ this ->symbols [Test::Passed] = '🍏 ' ;
72
+ $ this ->symbols [Test::Skipped] = '🍋 ' ;
73
+ $ this ->symbols [Test::Failed] = '🍎 ' ;
74
+ }
50
75
}
51
76
52
77
53
78
public function begin (): void
54
79
{
55
80
$ this ->count = 0 ;
56
- $ this ->buffer = '' ;
81
+ $ this ->buffer = [] ;
57
82
$ this ->baseDir = null ;
58
- $ this ->results = [
59
- Test::Passed => 0 ,
60
- Test::Skipped => 0 ,
61
- Test::Failed => 0 ,
62
- ];
63
83
$ this ->time = -microtime (true );
64
84
fwrite ($ this ->file , $ this ->runner ->getInterpreter ()->getShortInfo ()
65
85
. ' | ' . $ this ->runner ->getInterpreter ()->getCommandLine ()
@@ -94,15 +114,17 @@ public function prepare(Test $test): void
94
114
public function finish (Test $ test ): void
95
115
{
96
116
$ this ->results [$ test ->getResult ()]++;
97
- fwrite ($ this ->file , $ this ->symbols [$ test ->getResult ()]);
117
+ $ this ->lineMode
118
+ ? $ this ->printFinishedTestLine ($ test )
119
+ : $ this ->printFinishedTestDot ($ test );
98
120
99
121
$ title = ($ test ->title ? "$ test ->title | " : '' ) . substr ($ test ->getSignature (), strlen ($ this ->baseDir ));
100
122
$ message = ' ' . str_replace ("\n" , "\n " , trim ((string ) $ test ->message )) . "\n\n" ;
101
123
$ message = preg_replace ('/^ $/m ' , '' , $ message );
102
124
if ($ test ->getResult () === Test::Failed) {
103
- $ this ->buffer . = Dumper::color ('red ' , "-- FAILED: $ title " ) . "\n$ message " ;
125
+ $ this ->buffer [] = Dumper::color ('red ' , "-- FAILED: $ title " ) . "\n$ message " ;
104
126
} elseif ($ test ->getResult () === Test::Skipped && $ this ->displaySkipped ) {
105
- $ this ->buffer . = "-- Skipped: $ title \n$ message " ;
127
+ $ this ->buffer [] = "-- Skipped: $ title \n$ message " ;
106
128
}
107
129
}
108
130
@@ -111,14 +133,73 @@ public function end(): void
111
133
{
112
134
$ run = array_sum ($ this ->results );
113
135
fwrite ($ this ->file , !$ this ->count ? "No tests found \n" :
114
- "\n\n" . $ this ->buffer . "\n"
136
+ "\n\n" . implode ( '' , $ this ->buffer ) . "\n"
115
137
. ($ this ->results [Test::Failed] ? Dumper::color ('white/red ' ) . 'FAILURES! ' : Dumper::color ('white/green ' ) . 'OK ' )
116
138
. " ( $ this ->count test " . ($ this ->count > 1 ? 's ' : '' ) . ', '
117
139
. ($ this ->results [Test::Failed] ? $ this ->results [Test::Failed] . ' failure ' . ($ this ->results [Test::Failed] > 1 ? 's ' : '' ) . ', ' : '' )
118
140
. ($ this ->results [Test::Skipped] ? $ this ->results [Test::Skipped] . ' skipped, ' : '' )
119
141
. ($ this ->count !== $ run ? ($ this ->count - $ run ) . ' not run, ' : '' )
120
142
. sprintf ('%0.1f ' , $ this ->time + microtime (true )) . ' seconds) ' . Dumper::color () . "\n" );
121
143
122
- $ this ->buffer = '' ;
144
+ $ this ->buffer = [];
145
+ $ this ->resultsCount = 0 ;
146
+ }
147
+
148
+
149
+ private function printFinishedTestDot (Test $ test ): void
150
+ {
151
+ fwrite ($ this ->file , $ this ->symbols [$ test ->getResult ()]);
152
+ }
153
+
154
+
155
+ private function printFinishedTestLine (Test $ test ): void
156
+ {
157
+ $ this ->resultsCount ++;
158
+ $ result = $ test ->getResult ();
159
+
160
+ $ shortFilePath = str_replace ($ this ->baseDir , '' , $ test ->getFile ());
161
+ $ shortDirPath = dirname ($ shortFilePath ) . DIRECTORY_SEPARATOR ;
162
+ $ basename = basename ($ shortFilePath );
163
+
164
+ // Filename.
165
+ if ($ result === Test::Failed) {
166
+ $ fileText = Dumper::color ('red ' , $ shortDirPath ) . Dumper::color ('white/red ' , $ basename );
167
+ } else {
168
+ $ fileText = Dumper::color ('gray ' , $ shortDirPath ) . Dumper::color ('silver ' , $ basename );
169
+ }
170
+
171
+ // Line header.
172
+ $ header = "· " ;
173
+ // Test's title.
174
+ $ titleText = $ test ->title
175
+ ? Dumper::color ('fuchsia ' , " [ $ test ->title ] " )
176
+ : '' ;
177
+
178
+ // Print test's message only if it's not failed (those will be printed
179
+ // after all tests are finished and will contain detailed info about the
180
+ // failed test).
181
+ $ message = '' ;
182
+ if ($ result !== Test::Failed && $ test ->message ) {
183
+ $ message = $ test ->message ;
184
+ $ indent = str_repeat (' ' , mb_strlen ($ header ));
185
+
186
+ if (preg_match ('#\n# ' , $ message )) {
187
+ $ message = "\n$ indent " . preg_replace ('#\r?\n# ' , '\0 ' . $ indent , $ message );
188
+ } else {
189
+ $ message = Dumper::color ('olive ' , "[ $ message] " );
190
+ }
191
+ }
192
+
193
+ $ output = sprintf (
194
+ "%s%s %s %s %s %s \n" ,
195
+ $ header ,
196
+ "{$ this ->resultsCount }/ {$ this ->count }" ,
197
+ "$ fileText {$ titleText }" ,
198
+ $ this ->symbols [$ result ],
199
+ Dumper::color ('gray ' , sprintf ("in %.2f s " , $ test ->getDuration ())),
200
+ $ message ,
201
+ );
202
+
203
+ fwrite ($ this ->file , $ output );
123
204
}
124
205
}
0 commit comments