Adds initial implementation of --dirty option.

This commit is contained in:
Luke Downing
2022-12-05 08:59:42 +00:00
parent d77715b0fe
commit d29d68a2c2
5 changed files with 109 additions and 29 deletions

View File

@ -3,8 +3,10 @@
use Pest\Actions\ValidatesEnvironment; use Pest\Actions\ValidatesEnvironment;
use Pest\ConfigLoader; use Pest\ConfigLoader;
use Pest\Repositories\TestRepository;
use Pest\Support\Container; use Pest\Support\Container;
use Pest\Kernel; use Pest\Kernel;
use Pest\Support\DirtyTestCaseFilter;
use Pest\TestSuite; use Pest\TestSuite;
use Symfony\Component\Console\Input\ArgvInput; use Symfony\Component\Console\Input\ArgvInput;
use Symfony\Component\Console\Output\ConsoleOutput; use Symfony\Component\Console\Output\ConsoleOutput;
@ -44,9 +46,18 @@ use Symfony\Component\Console\Output\OutputInterface;
$rootPath = dirname($autoloadPath, 2); $rootPath = dirname($autoloadPath, 2);
$argv = new ArgvInput(); $argv = new ArgvInput();
$filters = [];
foreach ($args as $key => $value) {
if (str_contains($value, '--dirty')) {
$filters[] = new DirtyTestCaseFilter($rootPath);
}
}
$testSuite = TestSuite::getInstance( $testSuite = TestSuite::getInstance(
$rootPath, $rootPath,
$argv->getParameterOption('--test-directory', (new ConfigLoader($rootPath))->getTestsDirectory()) $argv->getParameterOption('--test-directory', (new ConfigLoader($rootPath))->getTestsDirectory()),
new TestRepository($filters),
); );
$isDecorated = $argv->getParameterOption('--colors', 'always') !== 'never'; $isDecorated = $argv->getParameterOption('--colors', 'always') !== 'never';
@ -57,16 +68,10 @@ use Symfony\Component\Console\Output\OutputInterface;
$container->add(TestSuite::class, $testSuite); $container->add(TestSuite::class, $testSuite);
$container->add(OutputInterface::class, $output); $container->add(OutputInterface::class, $output);
$argsToUnset = ['--test-directory', '--compact', '--profile', '--dirty'];
foreach ($args as $key => $value) { foreach ($args as $key => $value) {
if (str_contains($value, '--test-directory')) { if (in_array($value, $argsToUnset)) {
unset($args[$key]);
}
if (str_contains($value, '--compact')) {
unset($args[$key]);
}
if (str_contains($value, '--profile')) {
unset($args[$key]); unset($args[$key]);
} }
} }

View File

@ -0,0 +1,10 @@
<?php
declare(strict_types=1);
namespace Pest\Contracts;
interface TestCaseFilter
{
public function canLoad(string $suiteClassFile): bool;
}

View File

@ -5,6 +5,7 @@ declare(strict_types=1);
namespace Pest\Repositories; namespace Pest\Repositories;
use Closure; use Closure;
use Pest\Contracts\TestCaseFilter;
use Pest\Exceptions\TestCaseAlreadyInUse; use Pest\Exceptions\TestCaseAlreadyInUse;
use Pest\Exceptions\TestCaseClassOrTraitNotFound; use Pest\Exceptions\TestCaseClassOrTraitNotFound;
use Pest\Factories\TestCaseFactory; use Pest\Factories\TestCaseFactory;
@ -27,6 +28,13 @@ final class TestRepository
*/ */
private array $uses = []; private array $uses = [];
/**
* @param array<int, TestCaseFilter> $testCaseFilters
*/
public function __construct(private readonly array $testCaseFilters = [])
{
}
/** /**
* Counts the number of test cases. * Counts the number of test cases.
*/ */
@ -109,7 +117,17 @@ final class TestRepository
*/ */
public function makeIfNeeded(string $filename): void public function makeIfNeeded(string $filename): void
{ {
if (array_key_exists($filename, $this->testCases)) { if (!array_key_exists($filename, $this->testCases)) {
return;
}
$canLoad = array_reduce(
$this->testCaseFilters,
fn(bool $carry, TestCaseFilter $filter): bool => $carry && $filter->canLoad($filename),
true,
);
if ($canLoad) {
$this->make($this->testCases[$filename]); $this->make($this->testCases[$filename]);
} }
} }

View File

@ -0,0 +1,47 @@
<?php
declare(strict_types=1);
namespace Pest\Support;
use Pest\Contracts\TestCaseFilter;
use Symfony\Component\Process\Process;
final class DirtyTestCaseFilter implements TestCaseFilter
{
/**
* @var array<string>
*/
private array $changedFiles = [];
public function __construct(private string $projectRoot)
{
$this->loadDiff();
}
public function canLoad(string $suiteClassFile): bool
{
$relativePath = str_replace($this->projectRoot, '', $suiteClassFile);
if (str_starts_with($relativePath, '/')) {
$relativePath = substr($relativePath, 1);
}
return in_array($relativePath, $this->changedFiles, true);
}
private function loadDiff(): void
{
$process = new Process([
'git',
'diff',
'--name-only',
'HEAD',
'--',
'*.php',
]);
$process->run();
$this->changedFiles = explode(PHP_EOL, trim($process->getOutput()));
}
}

View File

@ -23,11 +23,6 @@ final class TestSuite
*/ */
public ?TestCase $test = null; public ?TestCase $test = null;
/**
* Holds the tests repository.
*/
public TestRepository $tests;
/** /**
* Holds the before each repository. * Holds the before each repository.
*/ */
@ -68,11 +63,12 @@ final class TestSuite
*/ */
public function __construct( public function __construct(
string $rootPath, string $rootPath,
public string $testPath) public string $testPath,
public TestRepository $tests = new TestRepository(),
)
{ {
$this->beforeAll = new BeforeAllRepository(); $this->beforeAll = new BeforeAllRepository();
$this->beforeEach = new BeforeEachRepository(); $this->beforeEach = new BeforeEachRepository();
$this->tests = new TestRepository();
$this->afterEach = new AfterEachRepository(); $this->afterEach = new AfterEachRepository();
$this->afterAll = new AfterAllRepository(); $this->afterAll = new AfterAllRepository();
$this->retryTempRepository = new TempRepository('retry'); $this->retryTempRepository = new TempRepository('retry');
@ -83,10 +79,14 @@ final class TestSuite
/** /**
* Returns the current instance of the test suite. * Returns the current instance of the test suite.
*/ */
public static function getInstance(string $rootPath = null, string $testPath = null): TestSuite public static function getInstance(
string $rootPath = null,
string $testPath = null,
TestRepository $tests = null,
): TestSuite
{ {
if (is_string($rootPath) && is_string($testPath)) { if (is_string($rootPath) && is_string($testPath)) {
self::$instance = new TestSuite($rootPath, $testPath); self::$instance = new TestSuite($rootPath, $testPath, $tests);
foreach (Plugin::$callables as $callable) { foreach (Plugin::$callables as $callable) {
$callable(); $callable();