Skip to content

Commit 5d5ff67

Browse files
authored
Merge pull request #44 from bakame-php/feature/exposing-codecoverage-blacklist-options
Exposes Code coverage optional arguments for directory filtering
2 parents 8e2e3cb + 053bf31 commit 5d5ff67

File tree

5 files changed

+142
-4
lines changed

5 files changed

+142
-4
lines changed

README.md

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,10 @@ extensions:
127127
whitelist:
128128
- src
129129
- lib
130+
# or to apply filtering on files names
131+
#- directory: src
132+
# suffix: "Controller.php"
133+
# prefix: "Get"
130134
#
131135
# Whiltelist files for which code generation should be done
132136
# Default: empty
@@ -137,6 +141,10 @@ extensions:
137141
# Blacklist directories for which code generation should NOT be done
138142
#blacklist:
139143
#- src/legacy
144+
# or to apply filtering on files names
145+
#- directory: src/legacy
146+
# suffix: "Spec.php"
147+
# prefix: "Test"
140148
#
141149
# Blacklist files for which code generation should NOT be done
142150
#blacklist_files:
@@ -161,10 +169,12 @@ extensions:
161169
* `high_lower_bound` (optional) sets high lower bound for code coverage
162170
(default `70`)
163171
* `whitelist` takes an array of directories to whitelist (default: `lib`,
164-
`src`).
172+
`src`). The array can be made more specific if an associative array is
173+
given with the following keys (`directory`, `prefix`, `suffix`)
165174
* `whitelist_files` takes an array of files to whitelist (default: none).
166175
* `blacklist` takes an array of directories to blacklist (default: `test,
167-
vendor, spec`)
176+
vendor, spec`). The array can be made more specific if an associative
177+
array is given with the following keys (`directory`, `prefix`, `suffix`)
168178
* `blacklist_files` takes an array of files to blacklist
169179

170180
## Authors
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace spec\FriendsOfPhpSpec\PhpSpec\CodeCoverage\Exception;
6+
7+
use FriendsOfPhpSpec\PhpSpec\CodeCoverage\Exception\ConfigurationException;
8+
use InvalidArgumentException;
9+
use PhpSpec\ObjectBehavior;
10+
11+
/**
12+
* @author Ignace Nyamagana Butera
13+
*/
14+
class ConfigurationExceptionSpec extends ObjectBehavior
15+
{
16+
public function it_is_initializable(): void
17+
{
18+
$this->shouldBeAnInstanceOf(InvalidArgumentException::class);
19+
$this->shouldHaveType(ConfigurationException::class);
20+
}
21+
}

spec/Listener/CodeCoverageListenerSpec.php

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,16 @@
44

55
namespace spec\FriendsOfPhpSpec\PhpSpec\CodeCoverage\Listener;
66

7+
use FriendsOfPhpSpec\PhpSpec\CodeCoverage\Exception\ConfigurationException;
78
use FriendsOfPhpSpec\PhpSpec\CodeCoverage\Listener\CodeCoverageListener;
89
use PhpSpec\Console\ConsoleIO;
10+
use PhpSpec\Event\SuiteEvent;
911
use PhpSpec\ObjectBehavior;
1012
use SebastianBergmann\CodeCoverage\CodeCoverage;
1113
use SebastianBergmann\CodeCoverage\Driver\Driver;
1214
use SebastianBergmann\CodeCoverage\Filter;
1315
use SebastianBergmann\CodeCoverage\RawCodeCoverageData;
16+
use stdClass;
1417

1518
/**
1619
* Disabled due to tests breaking as php-code-coverage marked their classes
@@ -23,11 +26,66 @@
2326
*/
2427
class CodeCoverageListenerSpec extends ObjectBehavior
2528
{
29+
public function it_can_process_all_directory_filtering_options(SuiteEvent $event)
30+
{
31+
$this->setOptions([
32+
'blacklist' => [
33+
'src',
34+
['directory' => 'src', 'suffix' => 'Spec.php', 'prefix' => 'Get'],
35+
['directory' => 'src', 'suffix' => 'Test.php'],
36+
['directory' => 'src'],
37+
],
38+
]);
39+
40+
$this
41+
->shouldNotThrow(ConfigurationException::class)
42+
->during('beforeSuite', [$event]);
43+
}
44+
2645
public function it_is_initializable()
2746
{
2847
$this->shouldHaveType(CodeCoverageListener::class);
2948
}
3049

50+
public function it_will_ignore_unknown_directory_filtering_options(SuiteEvent $event)
51+
{
52+
$this->setOptions([
53+
'whitelist' => [
54+
['directory' => 'test', 'foobar' => 'baz'],
55+
],
56+
]);
57+
58+
$this
59+
->shouldNotThrow(ConfigurationException::class)
60+
->during('beforeSuite', [$event]);
61+
}
62+
63+
public function it_will_throw_if_the_directory_filter_option_type_is_not_supported(SuiteEvent $event)
64+
{
65+
$this->setOptions([
66+
'whitelist' => [
67+
new stdClass(),
68+
],
69+
]);
70+
71+
$this
72+
->shouldThrow(ConfigurationException::class)
73+
->during('beforeSuite', [$event]);
74+
}
75+
76+
public function it_will_throw_if_the_directory_parameter_is_missing(SuiteEvent $event)
77+
{
78+
$this->setOptions([
79+
'whitelist' => [
80+
['foobar' => 'baz', 'suffix' => 'Spec.php', 'prefix' => 'Get'],
81+
],
82+
]);
83+
84+
$this
85+
->shouldThrow(ConfigurationException::class)
86+
->during('beforeSuite', [$event]);
87+
}
88+
3189
public function let(ConsoleIO $io)
3290
{
3391
$codeCoverage = new CodeCoverage(new DriverStub(), new Filter());
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace FriendsOfPhpSpec\PhpSpec\CodeCoverage\Exception;
6+
7+
use InvalidArgumentException;
8+
9+
class ConfigurationException extends InvalidArgumentException
10+
{
11+
}

src/Listener/CodeCoverageListener.php

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,18 @@
1414

1515
namespace FriendsOfPhpSpec\PhpSpec\CodeCoverage\Listener;
1616

17+
use FriendsOfPhpSpec\PhpSpec\CodeCoverage\Exception\ConfigurationException;
1718
use PhpSpec\Console\ConsoleIO;
1819
use PhpSpec\Event\ExampleEvent;
1920
use PhpSpec\Event\SuiteEvent;
2021
use SebastianBergmann\CodeCoverage\CodeCoverage;
2122
use SebastianBergmann\CodeCoverage\Report;
2223
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
2324

25+
use function gettype;
26+
use function is_array;
27+
use function is_string;
28+
2429
/**
2530
* @author Henrik Bjornskov
2631
*/
@@ -146,11 +151,15 @@ public function beforeSuite(SuiteEvent $event): void
146151
$filter = $this->coverage->filter();
147152

148153
foreach ($this->options['whitelist'] as $option) {
149-
$filter->includeDirectory($option);
154+
$settings = $this->filterDirectoryParams($option);
155+
156+
$filter->includeDirectory($settings['directory'], $settings['suffix'], $settings['prefix']);
150157
}
151158

152159
foreach ($this->options['blacklist'] as $option) {
153-
$filter->excludeDirectory($option);
160+
$settings = $this->filterDirectoryParams($option);
161+
162+
$filter->excludeDirectory($settings['directory'], $settings['suffix'], $settings['prefix']);
154163
}
155164

156165
$filter->includeFiles($this->options['whitelist_files']);
@@ -180,4 +189,33 @@ public function setOptions(array $options): void
180189
{
181190
$this->options = $options + $this->options;
182191
}
192+
193+
/**
194+
* @param array<string, string>|string $option
195+
*
196+
* @return array{directory:string, prefix:string, suffix:string}
197+
*/
198+
protected function filterDirectoryParams($option): array
199+
{
200+
if (is_string($option)) {
201+
$option = ['directory' => $option];
202+
}
203+
204+
if (!is_array($option)) {
205+
throw new ConfigurationException(sprintf(
206+
'Directory filtering options must be a string or an associated array, %s given instead.',
207+
gettype($option)
208+
));
209+
}
210+
211+
if (!isset($option['directory'])) {
212+
throw new ConfigurationException('Missing required directory path.');
213+
}
214+
215+
return [
216+
'directory' => $option['directory'],
217+
'suffix' => $option['suffix'] ?? '.php',
218+
'prefix' => $option['prefix'] ?? '',
219+
];
220+
}
183221
}

0 commit comments

Comments
 (0)