1
|
|
|
#!/usr/bin/env php |
|
|
|
|
2
|
|
|
<?php declare(strict_types=1); |
3
|
|
|
|
4
|
|
|
use Terah\Assert\Tester; |
5
|
|
|
|
6
|
|
|
require_once __DIR__ . '/../vendor/autoload.php'; |
7
|
|
|
|
8
|
|
|
class TestRunner |
|
|
|
|
9
|
|
|
{ |
10
|
|
|
public static function run() |
11
|
|
|
{ |
12
|
|
|
$fileName = (string)static::getArg(1, getcwd()); |
13
|
|
|
$suite = (string)static::getArg('suite', ''); |
14
|
|
|
$test = (string)static::getArg('test', ''); |
15
|
|
|
$recursive = (bool)static::getArg('recursive', true); |
16
|
|
|
$tests = static::getTestFiles($fileName, $recursive); |
17
|
|
|
if ( empty($tests) ) |
18
|
|
|
{ |
19
|
|
|
Tester::getLogger()->error("No test files found/specified"); |
20
|
|
|
|
21
|
|
|
exit(1); |
22
|
|
|
} |
23
|
|
|
foreach ( $tests as $fileName ) |
24
|
|
|
{ |
25
|
|
|
Tester::getLogger()->debug("Loading test file {$fileName}"); |
26
|
|
|
require($fileName); |
27
|
|
|
Tester::run($suite, $test); |
28
|
|
|
} |
29
|
|
|
|
30
|
|
|
exit(0); |
31
|
|
|
} |
32
|
|
|
|
33
|
|
|
/** |
34
|
|
|
* @param string $fileName |
35
|
|
|
* @param bool $recursive |
36
|
|
|
* @return array |
37
|
|
|
*/ |
38
|
|
|
public static function getTestFiles(string $fileName='', bool $recursive=false) : array |
39
|
|
|
{ |
40
|
|
|
if ( empty($fileName) ) |
41
|
|
|
{ |
42
|
|
|
return []; |
43
|
|
|
} |
44
|
|
|
if ( ! file_exists($fileName) ) |
45
|
|
|
{ |
46
|
|
|
Tester::getLogger()->error("{$fileName} does not exist; exiting"); |
47
|
|
|
|
48
|
|
|
exit(1); |
49
|
|
|
} |
50
|
|
|
$fileName = realpath($fileName); |
51
|
|
|
if ( is_dir($fileName) ) |
52
|
|
|
{ |
53
|
|
|
$iterator = new \DirectoryIterator($fileName); |
54
|
|
|
if ( $recursive ) |
55
|
|
|
{ |
56
|
|
|
$iterator = new \RecursiveDirectoryIterator($fileName); |
57
|
|
|
$iterator = $recursive ? new RecursiveIteratorIterator($iterator) : $iterator; |
58
|
|
|
} |
59
|
|
|
$testFiles = []; |
60
|
|
|
foreach ( $iterator as $fileInfo ) |
61
|
|
|
{ |
62
|
|
|
if ( preg_match('/Suite.php$/', $fileInfo->getBasename()) ) |
63
|
|
|
{ |
64
|
|
|
$testFiles[] = $fileInfo->getPathname(); |
65
|
|
|
} |
66
|
|
|
} |
67
|
|
|
|
68
|
|
|
return $testFiles; |
69
|
|
|
} |
70
|
|
|
if ( ! is_file($fileName) ) |
71
|
|
|
{ |
72
|
|
|
Tester::getLogger()->error("{$fileName} is not a file; exiting"); |
73
|
|
|
|
74
|
|
|
exit(1); |
75
|
|
|
} |
76
|
|
|
|
77
|
|
|
return [$fileName]; |
78
|
|
|
} |
79
|
|
|
|
80
|
|
|
/** |
81
|
|
|
* PARSE ARGUMENTS |
82
|
|
|
* |
83
|
|
|
* This command line option parser supports any combination of three types of options |
84
|
|
|
* [single character options (`-a -b` or `-ab` or `-c -d=dog` or `-cd dog`), |
85
|
|
|
* long options (`--foo` or `--bar=baz` or `--bar baz`) |
86
|
|
|
* and arguments (`arg1 arg2`)] and returns a simple array. |
87
|
|
|
* |
88
|
|
|
* [pfisher ~]$ php test.php --foo --bar=baz --spam eggs |
89
|
|
|
* ["foo"] => true |
90
|
|
|
* ["bar"] => "baz" |
91
|
|
|
* ["spam"] => "eggs" |
92
|
|
|
* |
93
|
|
|
* [pfisher ~]$ php test.php -abc foo |
94
|
|
|
* ["a"] => true |
95
|
|
|
* ["b"] => true |
96
|
|
|
* ["c"] => "foo" |
97
|
|
|
* |
98
|
|
|
* [pfisher ~]$ php test.php arg1 arg2 arg3 |
99
|
|
|
* [0] => "arg1" |
100
|
|
|
* [1] => "arg2" |
101
|
|
|
* [2] => "arg3" |
102
|
|
|
* |
103
|
|
|
* [pfisher ~]$ php test.php plain-arg --foo --bar=baz --funny="spam=eggs" --also-funny=spam=eggs \ |
104
|
|
|
* > 'plain arg 2' -abc -k=value "plain arg 3" --s="original" --s='overwrite' --s |
105
|
|
|
* [0] => "plain-arg" |
106
|
|
|
* ["foo"] => true |
107
|
|
|
* ["bar"] => "baz" |
108
|
|
|
* ["funny"] => "spam=eggs" |
109
|
|
|
* ["also-funny"]=> "spam=eggs" |
110
|
|
|
* [1] => "plain arg 2" |
111
|
|
|
* ["a"] => true |
112
|
|
|
* ["b"] => true |
113
|
|
|
* ["c"] => true |
114
|
|
|
* ["k"] => "value" |
115
|
|
|
* [2] => "plain arg 3" |
116
|
|
|
* ["s"] => "overwrite" |
117
|
|
|
* |
118
|
|
|
* Not supported: `-cd=dog`. |
119
|
|
|
* |
120
|
|
|
* @author Patrick Fisher <[email protected]> |
121
|
|
|
* @since August 21, 2009 |
122
|
|
|
* @see https://github.com/pwfisher/CommandLine.php |
123
|
|
|
* @see http://www.php.net/manual/en/features.commandline.php |
124
|
|
|
* #81042 function arguments($argv) by technorati at gmail dot com, 12-Feb-2008 |
125
|
|
|
* #78651 function getArgs($args) by B Crawford, 22-Oct-2007 |
126
|
|
|
* @usage $args = CommandLine::parseArgs($_SERVER['argv']); |
127
|
|
|
* @param array $argv |
128
|
|
|
* @return array |
129
|
|
|
*/ |
130
|
|
|
public static function parseArgs(array $argv=[]) : array |
131
|
|
|
{ |
132
|
|
|
$argv = $argv ?: ! empty($_SERVER['argv']) ? $_SERVER['argv'] : []; |
133
|
|
|
array_shift($argv); |
134
|
|
|
$out = []; |
135
|
|
|
for ( $i = 0, $j = count($argv); $i < $j; $i++ ) |
136
|
|
|
{ |
137
|
|
|
$arg = $argv[$i]; |
138
|
|
|
// --foo --bar=baz |
139
|
|
|
if ( mb_substr($arg, 0, 2) === '--' ) |
140
|
|
|
{ |
141
|
|
|
$eqPos = mb_strpos($arg, '='); |
142
|
|
|
// --foo |
143
|
|
|
if ($eqPos === false) |
144
|
|
|
{ |
145
|
|
|
$key = mb_substr($arg, 2); |
146
|
|
|
// --foo value |
147
|
|
|
if ($i + 1 < $j && $argv[$i + 1][0] !== '-') |
148
|
|
|
{ |
149
|
|
|
$value = $argv[$i + 1]; |
150
|
|
|
$i++; |
151
|
|
|
} |
152
|
|
|
else |
153
|
|
|
{ |
154
|
|
|
$value = isset($out[$key]) ? $out[$key] : true; |
155
|
|
|
} |
156
|
|
|
$out[$key] = $value; |
157
|
|
|
} |
158
|
|
|
// --bar=baz |
159
|
|
|
else |
160
|
|
|
{ |
161
|
|
|
$key = mb_substr($arg, 2, $eqPos - 2); |
162
|
|
|
$value = mb_substr($arg, $eqPos + 1); |
163
|
|
|
$out[$key] = $value; |
164
|
|
|
} |
165
|
|
|
} |
166
|
|
|
// -k=value -abc |
167
|
|
|
else if (mb_substr($arg, 0, 1) === '-') |
168
|
|
|
{ |
169
|
|
|
// -k=value |
170
|
|
|
if (mb_substr($arg, 2, 1) === '=') |
171
|
|
|
{ |
172
|
|
|
$key = mb_substr($arg, 1, 1); |
173
|
|
|
$value = mb_substr($arg, 3); |
174
|
|
|
$out[$key] = $value; |
175
|
|
|
} |
176
|
|
|
// -abc |
177
|
|
|
else |
178
|
|
|
{ |
179
|
|
|
$chars = str_split(mb_substr($arg, 1)); |
180
|
|
|
$key = ''; |
181
|
|
|
foreach ( $chars as $char ) |
182
|
|
|
{ |
183
|
|
|
$key = $char; |
184
|
|
|
$value = isset($out[$key]) ? $out[$key] : true; |
185
|
|
|
$out[$key] = $value; |
186
|
|
|
} |
187
|
|
|
// -a value1 -abc value2 |
188
|
|
|
if ($i + 1 < $j && $argv[$i + 1][0] !== '-') |
189
|
|
|
{ |
190
|
|
|
$out[$key] = $argv[$i + 1]; |
191
|
|
|
$i++; |
192
|
|
|
} |
193
|
|
|
} |
194
|
|
|
} |
195
|
|
|
// plain-arg |
196
|
|
|
else |
197
|
|
|
{ |
198
|
|
|
$value = $arg; |
199
|
|
|
$out[] = $value; |
200
|
|
|
} |
201
|
|
|
} |
202
|
|
|
foreach ( $out as $idx => $val ) |
203
|
|
|
{ |
204
|
|
|
if ( is_string($val) && strpos($val, '|') !== false ) |
205
|
|
|
{ |
206
|
|
|
$out[$idx] = explode('|', $val); |
207
|
|
|
} |
208
|
|
|
} |
209
|
|
|
|
210
|
|
|
return $out; |
211
|
|
|
} |
212
|
|
|
|
213
|
|
|
/** |
214
|
|
|
* @param $name |
215
|
|
|
* @param mixed $default |
216
|
|
|
* @return string |
217
|
|
|
*/ |
218
|
|
|
protected static function getArg($name, $default=null) |
219
|
|
|
{ |
220
|
|
|
$args = static::parseArgs(); |
221
|
|
|
|
222
|
|
|
return isset($args[$name]) && $args[$name] ? $args[$name] : $default; |
223
|
|
|
} |
224
|
|
|
|
225
|
|
|
} |
226
|
|
|
|
227
|
|
|
TestRunner::run(); |
The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.
The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.
To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.