Skip to content

Commit 72fab2d

Browse files
authored
Add --skip option (#9)
* add skip * readme
1 parent c8faf2e commit 72fab2d

File tree

10 files changed

+101
-35
lines changed

10 files changed

+101
-35
lines changed

README.md

Lines changed: 36 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -12,55 +12,65 @@ Find unused and duplicated definitions easily – without running Behat test
1212
composer require behastan/behastan --dev
1313
```
1414

15-
## Features
15+
## Usage
1616

17-
## 1. Find duplicated definitions
17+
```bash
18+
vendor/bin/behastan analyse tests
19+
```
20+
21+
<br>
1822

19-
Some definitions have very similar masks, but even identical contents. Better use a one definitions with exact mask, to make your tests more precise and easier to maintain:
23+
Do you want to skip some rule? You can:
2024

2125
```bash
22-
vendor/bin/behastan analyze
26+
vendor/bin/behastan analyse tests --skip=<rule-identifier>
2327
```
2428

29+
<br>
30+
31+
Here are the available rules:
32+
33+
### 1. Find duplicated definitions contents
34+
35+
* identifier: `duplicated-contents`
36+
37+
Some definitions have similar masks, even identical contents. Better use a one definitions with exact mask, to make your tests more precise and easier to maintain:
2538

2639
<br>
2740

28-
## 2. Find unused Behat definitions with static analysis
41+
### 2. Find duplicate masks
2942

30-
Behat uses `@When()`, `@Then()` and `@Given()` annotations and their PHP 8 attribute alternatives to define method to be called in `*.feature` files. Sometimes test change and lines from `*.feature` files are deleted. But what about definitions?
43+
* identifier: `duplicated-masks`
3144

32-
This command helps you to spot definitions that are no longer needed. Just provide test directory (1 or more) and let it statically compare defined and used masks:
45+
Same as services, there should be no 2 same definition masks. Make them unique with different behavior, or merge them and use one definition instead.
3346

34-
```bash
35-
vendor/bin/behastan unused-definitions tests
36-
```
47+
<br>
3748

38-
49+
### 3. Find unused Behat definitions with static analysis
3950

40-
```bash
41-
Checking static, named and regex masks from 100 *Feature files
42-
==============================================================
51+
* identifier: `unused-definitions`
4352

44-
Found 1036 masks:
53+
Behat uses `@When()`, `@Then()` and `@Given()` annotations or attributes to define a class method that is called in `*.feature` files. Sometimes test change and lines from `*.feature` files are deleted. But what about definitions?
4554

46-
* 747 exact
47-
* 106 /regex/
48-
* 181 :named
55+
This rule spots definitions that are no longer needed.
4956

50-
1036/1036 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 100%
57+
<br>
5158

52-
the product price is :value
53-
tests/Behat/ProductContext.php
59+
## Output example
5460

55-
/^I submit order form and see payment page$/
56-
tests/Behat/OrderContext.php
61+
```bash
62+
Found 127 Context and 225 feature files
63+
Extracting definitions masks...
5764

65+
Found 1367 masks:
66+
* 863 exact
67+
* 204 /regex/
68+
* 298 :named
5869

59-
[ERROR] Found 2 unused definitions
70+
Running analysis...
6071
```
6172

62-
You can also add this command to CI, to get instant feedback about unused definitions.
63-
73+
Add this command to CI, to get instant feedback of any changes.
6474

6575
That's it!
6676

rector.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@
1616
codingStyle: true,
1717
instanceOf: true,
1818
phpunitCodeQuality: true,
19-
naming: true
19+
naming: true,
20+
rectorPreset: true,
2021
)
2122
->withImportNames()
2223
->withSkip(['*/scoper.php', '*/Source/*', '*/Fixture/*']);

src/Analyzer/UnusedDefinitionsAnalyzer.php

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66

77
use Nette\Utils\Strings;
88
use Rector\Behastan\DefinitionMasksExtractor;
9-
use Rector\Behastan\Reporting\MaskCollectionStatsPrinter;
109
use Rector\Behastan\UsedInstructionResolver;
1110
use Rector\Behastan\ValueObject\Mask\AbstractMask;
1211
use Rector\Behastan\ValueObject\Mask\ExactMask;
@@ -32,7 +31,6 @@ public function __construct(
3231
private SymfonyStyle $symfonyStyle,
3332
private UsedInstructionResolver $usedInstructionResolver,
3433
private DefinitionMasksExtractor $definitionMasksExtractor,
35-
private MaskCollectionStatsPrinter $maskCollectionStatsPrinter,
3634
) {
3735
}
3836

@@ -55,7 +53,6 @@ public function analyse(array $contextFiles, array $featureFiles, MaskCollection
5553
}
5654

5755
$maskCollection = $this->definitionMasksExtractor->extract($contextFiles);
58-
$this->maskCollectionStatsPrinter->print($maskCollection);
5956

6057
$featureInstructions = $this->usedInstructionResolver->resolveInstructionsFromFeatureFiles($featureFiles);
6158
$maskProgressBar = $this->symfonyStyle->createProgressBar($maskCollection->count());

src/Command/AnalyzeCommand.php

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ public function __construct(
4040
protected function configure(): void
4141
{
4242
$this->setName('analyze');
43+
$this->setAliases(['analyse']);
44+
4345
$this->setDescription('Run complete static analysis on Behat definitions and features');
4446

4547
$this->addArgument(
@@ -65,7 +67,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
6567
$contextFileInfos = BehatMetafilesFinder::findContextFiles([$testDirectory]);
6668
if ($contextFileInfos === []) {
6769
$this->symfonyStyle->error(sprintf(
68-
'No *.Context files found in "%s". Please provide correct test directory',
70+
'No *.Context files found in "%s". Please provide correct directory',
6971
$testDirectory
7072
));
7173
return self::FAILURE;
@@ -74,12 +76,14 @@ protected function execute(InputInterface $input, OutputInterface $output): int
7476
$featureFileInfos = BehatMetafilesFinder::findFeatureFiles([$testDirectory]);
7577
if ($featureFileInfos === []) {
7678
$this->symfonyStyle->error(sprintf(
77-
'No *.feature files found in "%s". Please provide correct test directory',
79+
'No *.feature files found in "%s". Please provide correct directory',
7880
$testDirectory
7981
));
8082
return self::FAILURE;
8183
}
8284

85+
$skips = $input->getOption('skip');
86+
8387
$this->symfonyStyle->writeln(sprintf(
8488
'<fg=green>Found %d Context and %d feature files</>',
8589
count($contextFileInfos),
@@ -91,21 +95,26 @@ protected function execute(InputInterface $input, OutputInterface $output): int
9195
$this->symfonyStyle->newLine();
9296

9397
$this->maskCollectionStatsPrinter->print($maskCollection);
94-
9598
$this->symfonyStyle->newLine();
9699

97-
// @todo skip by "--skip" option
98-
99100
$this->symfonyStyle->writeln('<fg=yellow>Running analysis...</>');
101+
$this->symfonyStyle->newLine();
100102

101103
/** @var RuleError[] $allRuleErrors */
102104
$allRuleErrors = [];
103105
foreach ($this->rules as $rule) {
106+
if ($skips !== [] && in_array($rule->getIdentifier(), $skips, true)) {
107+
$this->symfonyStyle->writeln(sprintf('<fg=cyan>Skipping "%s" rule</>', $rule->getIdentifier()));
108+
$this->symfonyStyle->newLine();
109+
continue;
110+
}
111+
104112
$ruleErrors = $rule->process($contextFileInfos, $featureFileInfos, $maskCollection, $testDirectory);
105113
$allRuleErrors = array_merge($allRuleErrors, $ruleErrors);
106114
}
107115

108116
if ($allRuleErrors === []) {
117+
$this->symfonyStyle->newLine(2);
109118
$this->symfonyStyle->success('No errors found. Good job!');
110119

111120
return self::SUCCESS;

src/Contract/RuleInterface.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace Rector\Behastan\Contract;
66

7+
use Rector\Behastan\Enum\RuleIdentifier;
78
use Rector\Behastan\ValueObject\MaskCollection;
89
use Rector\Behastan\ValueObject\RuleError;
910
use Symfony\Component\Finder\SplFileInfo;
@@ -22,4 +23,9 @@ public function process(
2223
MaskCollection $maskCollection,
2324
string $projectDirectory
2425
): array;
26+
27+
/**
28+
* @return RuleIdentifier::*
29+
*/
30+
public function getIdentifier(): string;
2531
}

src/Enum/RuleIdentifier.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Rector\Behastan\Enum;
6+
7+
final class RuleIdentifier
8+
{
9+
/**
10+
* @var string
11+
*/
12+
public const DUPLICATED_CONTENTS = 'duplicated-contents';
13+
14+
/**
15+
* @var string
16+
*/
17+
public const DUPLICATED_MASKS = 'duplicated-masks';
18+
19+
/**
20+
* @var string
21+
*/
22+
public const UNUSED_DEFINITIONS = 'unused-definitions';
23+
}

src/Rule/DuplicatedContextDefinitionContentsRule.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
use Rector\Behastan\Analyzer\ContextDefinitionsAnalyzer;
88
use Rector\Behastan\Contract\RuleInterface;
9+
use Rector\Behastan\Enum\RuleIdentifier;
910
use Rector\Behastan\ValueObject\MaskCollection;
1011
use Rector\Behastan\ValueObject\RuleError;
1112
use Symfony\Component\Finder\SplFileInfo;
@@ -59,6 +60,11 @@ public function process(
5960
return $ruleErrors;
6061
}
6162

63+
public function getIdentifier(): string
64+
{
65+
return RuleIdentifier::DUPLICATED_CONTENTS;
66+
}
67+
6268
/**
6369
* @template TItem as object
6470
*

src/Rule/DuplicatedMaskRule.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
use Rector\Behastan\Analyzer\ContextDefinitionsAnalyzer;
88
use Rector\Behastan\Contract\RuleInterface;
9+
use Rector\Behastan\Enum\RuleIdentifier;
910
use Rector\Behastan\ValueObject\ContextDefinition;
1011
use Rector\Behastan\ValueObject\MaskCollection;
1112
use Rector\Behastan\ValueObject\RuleError;
@@ -59,4 +60,9 @@ public function process(
5960

6061
return $ruleErrors;
6162
}
63+
64+
public function getIdentifier(): string
65+
{
66+
return RuleIdentifier::DUPLICATED_MASKS;
67+
}
6268
}

src/Rule/UnusedContextDefinitionsRule.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
use Rector\Behastan\Analyzer\UnusedDefinitionsAnalyzer;
88
use Rector\Behastan\Contract\RuleInterface;
9+
use Rector\Behastan\Enum\RuleIdentifier;
910
use Rector\Behastan\ValueObject\MaskCollection;
1011
use Rector\Behastan\ValueObject\RuleError;
1112
use Symfony\Component\Finder\SplFileInfo;
@@ -43,4 +44,9 @@ public function process(
4344

4445
return $ruleErrors;
4546
}
47+
48+
public function getIdentifier(): string
49+
{
50+
return RuleIdentifier::UNUSED_DEFINITIONS;
51+
}
4652
}

src/ValueObject/Mask/AbstractMask.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
<?php
22

3+
declare(strict_types=1);
4+
35
namespace Rector\Behastan\ValueObject\Mask;
46

57
use Rector\Behastan\Contract\MaskInterface;

0 commit comments

Comments
 (0)