Skip to content

Commit 38b23b3

Browse files
authored
Merge pull request #298 from uuf6429/chore/use-vfs-in-tests
test: Use vfsStream to simplify / improve filesystem-related tests
2 parents 7eaf0ec + 42c0e29 commit 38b23b3

File tree

5 files changed

+81
-64
lines changed

5 files changed

+81
-64
lines changed

composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@
2525
"friendsofphp/php-cs-fixer": "^3.65",
2626
"phpstan/phpstan": "^2",
2727
"phpstan/extension-installer": "^1",
28-
"phpstan/phpstan-phpunit": "^2"
28+
"phpstan/phpstan-phpunit": "^2",
29+
"mikey179/vfsstream": "^1.6"
2930
},
3031

3132
"suggest": {

tests/Cache/FileCacheTest.php

Lines changed: 35 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -14,64 +14,62 @@
1414
use Behat\Gherkin\Exception\CacheException;
1515
use Behat\Gherkin\Node\FeatureNode;
1616
use Behat\Gherkin\Node\ScenarioNode;
17+
use org\bovigo\vfs\vfsStream;
18+
use org\bovigo\vfs\vfsStreamDirectory;
1719
use PHPUnit\Framework\TestCase;
1820
use Tests\Behat\Gherkin\Filesystem;
1921

20-
/**
21-
* @todo Use VFS
22-
*/
2322
class FileCacheTest extends TestCase
2423
{
25-
private string $path;
26-
private FileCache $cache;
27-
28-
protected function setUp(): void
29-
{
30-
$this->cache = new FileCache($this->path = sys_get_temp_dir() . uniqid('/gherkin-test'));
31-
}
32-
3324
public function testIsFreshWhenThereIsNoFile(): void
3425
{
35-
$this->assertFalse($this->cache->isFresh('unexisting', time() + 100));
26+
$cache = $this->createCache();
27+
28+
$this->assertFalse($cache->isFresh('unexisting', time() + 100));
3629
}
3730

3831
public function testIsFreshOnFreshFile(): void
3932
{
33+
$cache = $this->createCache();
4034
$feature = new FeatureNode(null, null, [], null, [], '', '', null, 1);
4135

42-
$this->cache->write('some_path', $feature);
36+
$cache->write('some_path', $feature);
4337

44-
$this->assertFalse($this->cache->isFresh('some_path', time() + 100));
38+
$this->assertFalse($cache->isFresh('some_path', time() + 100));
4539
}
4640

4741
public function testIsFreshOnOutdated(): void
4842
{
43+
$cache = $this->createCache();
4944
$feature = new FeatureNode(null, null, [], null, [], '', '', null, 1);
5045

51-
$this->cache->write('some_path', $feature);
46+
$cache->write('some_path', $feature);
5247

53-
$this->assertTrue($this->cache->isFresh('some_path', time() - 100));
48+
$this->assertTrue($cache->isFresh('some_path', time() - 100));
5449
}
5550

5651
public function testCacheAndRead(): void
5752
{
53+
$cache = $this->createCache();
5854
$scenarios = [new ScenarioNode('Some scenario', [], [], '', 1)];
5955
$feature = new FeatureNode('Some feature', 'some description', [], null, $scenarios, '', '', null, 1);
6056

61-
$this->cache->write('some_feature', $feature);
62-
$featureRead = $this->cache->read('some_feature');
57+
$cache->write('some_feature', $feature);
58+
$featureRead = $cache->read('some_feature');
6359

6460
$this->assertEquals($feature, $featureRead);
6561
}
6662

6763
public function testBrokenCacheRead(): void
6864
{
65+
$root = $this->createRoot();
66+
$cache = $this->createCache($root);
6967
// First, write a valid cache and find the file that was written
70-
$this->cache->write(
68+
$cache->write(
7169
'broken_feature',
7270
new FeatureNode(null, null, [], null, [], '', '', null, 1),
7371
);
74-
$files = Filesystem::find("$this->path/**/*.feature.cache");
72+
$files = Filesystem::findFilesRecursively($root->url(), '*.feature.cache');
7573

7674
$this->assertCount(1, $files, 'Cache should have written a single file');
7775

@@ -80,17 +78,28 @@ public function testBrokenCacheRead(): void
8078

8179
$this->expectException(CacheException::class);
8280

83-
$this->cache->read('broken_feature');
81+
$cache->read('broken_feature');
8482
}
8583

8684
public function testUnwriteableCacheDir(): void
8785
{
86+
$root = vfsStream::setup();
87+
$root->chmod(0);
88+
8889
$this->expectException(CacheException::class);
8990

90-
if (PHP_OS_FAMILY === 'Windows') {
91-
new FileCache('C:\\Windows\\System32\\drivers\\etc');
92-
} else {
93-
new FileCache('/dev/null/gherkin-test');
94-
}
91+
new FileCache($root->url());
92+
}
93+
94+
private function createRoot(): vfsStreamDirectory
95+
{
96+
return vfsStream::setup();
97+
}
98+
99+
private function createCache(?vfsStreamDirectory $root = null): FileCache
100+
{
101+
return new FileCache(
102+
($root ?? $this->createRoot())->url()
103+
);
95104
}
96105
}

tests/Filesystem.php

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,18 @@
1010

1111
namespace Tests\Behat\Gherkin;
1212

13+
use RecursiveDirectoryIterator;
14+
use RecursiveIteratorIterator;
15+
use RuntimeException;
16+
use SplFileInfo;
17+
1318
class Filesystem
1419
{
1520
public static function readFile(string $fileName): string
1621
{
1722
$data = @file_get_contents($fileName);
1823
if ($data === false) {
19-
throw new \RuntimeException("Failed to read file: $fileName");
24+
throw new RuntimeException("Failed to read file: $fileName");
2025
}
2126

2227
return $data;
@@ -25,8 +30,20 @@ public static function readFile(string $fileName): string
2530
/**
2631
* @return list<string>
2732
*/
28-
public static function find(string $pattern): array
33+
public static function findFilesRecursively(string $path, string $pattern): array
2934
{
30-
return glob($pattern) ?: [];
35+
/**
36+
* @var iterable<string, SplFileInfo> $fileIterator
37+
*/
38+
$fileIterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path), RecursiveIteratorIterator::CHILD_FIRST);
39+
40+
$found = [];
41+
foreach ($fileIterator as $file) {
42+
if ($file->isFile() && fnmatch($pattern, $file->getFilename())) {
43+
$found[] = $file->getPathname();
44+
}
45+
}
46+
47+
return $found;
3148
}
3249
}

tests/Keywords/CucumberKeywordsTest.php

Lines changed: 23 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
use Behat\Gherkin\Keywords\CucumberKeywords;
1414
use Behat\Gherkin\Keywords\KeywordsInterface;
1515
use Behat\Gherkin\Node\StepNode;
16+
use org\bovigo\vfs\vfsStream;
1617
use Symfony\Component\Yaml\Exception\ParseException;
1718
use Symfony\Component\Yaml\Yaml;
1819

@@ -44,22 +45,20 @@ protected static function getSteps(string $keywords, string $text, int &$line, ?
4445

4546
public function testYamlSourceFileIsAttachedToException(): void
4647
{
47-
$tempFile = tempnam(sys_get_temp_dir(), 'test');
48-
49-
try {
50-
file_put_contents($tempFile, "invalid:\n\tinvalid:yaml");
48+
$root = vfsStream::setup();
49+
$root->addChild(
50+
$file = vfsStream::newFile('invalid.yaml')
51+
->setContent("invalid:\n\tinvalid:yaml")
52+
);
5153

52-
$this->expectExceptionObject(new ParseException(
53-
'YAML file cannot contain tabs as indentation',
54-
2,
55-
"\tinvalid:yaml",
56-
$tempFile,
57-
));
54+
$this->expectExceptionObject(new ParseException(
55+
'YAML file cannot contain tabs as indentation',
56+
2,
57+
"\tinvalid:yaml",
58+
$file->url(),
59+
));
5860

59-
new CucumberKeywords($tempFile);
60-
} finally {
61-
@unlink($tempFile);
62-
}
61+
new CucumberKeywords($file->url());
6362
}
6463

6564
public function testYamlRootMustBeAnArray(): void
@@ -71,28 +70,19 @@ public function testYamlRootMustBeAnArray(): void
7170
new CucumberKeywords("a\nstring");
7271
}
7372

74-
/**
75-
* @todo Use VFS
76-
*/
7773
public function testYamlFileMustBeReadable(): void
7874
{
79-
$tempFile = tempnam(sys_get_temp_dir(), 'test');
80-
81-
try {
82-
file_put_contents($tempFile, "aaa:\n bbb: cccc");
83-
if (PHP_OS_FAMILY === 'Windows') {
84-
exec('icacls ' . escapeshellarg($tempFile) . ' /deny Everyone:(R)');
85-
} else {
86-
chmod($tempFile, 0);
87-
}
75+
$root = vfsStream::setup();
76+
$root->addChild(
77+
$file = vfsStream::newFile('unreadable.yaml')
78+
->setContent("aaa:\n bbb: cccc")
79+
->chmod(0)
80+
);
8881

89-
$this->expectExceptionObject(
90-
new ParseException("Unable to parse \"$tempFile\" as the file is not readable.")
91-
);
82+
$this->expectExceptionObject(
83+
new ParseException("Unable to parse \"{$file->url()}\" as the file is not readable.")
84+
);
9285

93-
new CucumberKeywords($tempFile);
94-
} finally {
95-
@unlink($tempFile);
96-
}
86+
new CucumberKeywords($file->url());
9787
}
9888
}

tests/ParserTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ final class ParserTest extends TestCase
2929
*/
3030
public static function parserTestDataProvider(): iterable
3131
{
32-
foreach (Filesystem::find(__DIR__ . '/Fixtures/etalons/*.yml') as $file) {
32+
foreach (Filesystem::findFilesRecursively(__DIR__ . '/Fixtures/etalons', '*.yml') as $file) {
3333
$testname = basename($file, '.yml');
3434
yield $testname => ['fixtureName' => $testname];
3535
}

0 commit comments

Comments
 (0)