Skip to content

Commit

Permalink
Merge pull request #62 from jolicode/feat/allow-to-run-if-failed
Browse files Browse the repository at this point in the history
feat(dependency): allow to still run a test even if a dependency has failed
  • Loading branch information
joelwurtz committed Apr 10, 2024
2 parents e95ebfa + 379b396 commit 3bcfefe
Show file tree
Hide file tree
Showing 8 changed files with 37 additions and 34 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yaml
Expand Up @@ -16,7 +16,7 @@ jobs:
composer-flags: [""]
name: [""]
include:
- php-version: "8.1"
- php-version: "8.2"
composer-flags: "--prefer-lowest"
name: "(prefer lowest dependencies)"
name: Tests PHP ${{ matrix.php-version }} ${{ matrix.name }}
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Expand Up @@ -26,7 +26,7 @@
"test": "bin/asynit tests/"
},
"require": {
"php": "^8.1",
"php": "^8.2",
"amphp/amp": "^3.0",
"amphp/sync": "^2.0",
"bovigo/assert": "^7.0",
Expand Down
4 changes: 2 additions & 2 deletions src/Attribute/Depend.php
Expand Up @@ -3,9 +3,9 @@
namespace Asynit\Attribute;

#[\Attribute(\Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)]
class Depend
final readonly class Depend
{
public function __construct(public string $dependency)
public function __construct(public string $dependency, public bool $skipIfFailed = true)
{
}
}
2 changes: 1 addition & 1 deletion src/Output/PhpUnitAlike.php
Expand Up @@ -75,7 +75,7 @@ public function outputSkipped(Test $test, $debugOutput)

private function writeTest(Test $test, $text)
{
if (!$test->isRealTest()) {
if (!$test->isRealTest) {
return;
}

Expand Down
19 changes: 10 additions & 9 deletions src/Parser/TestPoolBuilder.php
Expand Up @@ -42,25 +42,26 @@ private function processTestAnnotations(\ArrayObject $tests, Test $test): void
$attributes = $testMethod->getAttributes(Depend::class);

foreach ($attributes as $attribute) {
$dependency = $attribute->newInstance()->dependency;
/** @var Depend $dependency */
$dependency = $attribute->newInstance();

if (isset($tests[$dependency])) {
$dependentTest = $tests[$dependency];
if (isset($tests[$dependency->dependency])) {
$dependentTest = $tests[$dependency->dependency];

$dependentTest->addChildren($test);
$dependentTest->addChildren($test, $dependency->skipIfFailed);
$test->addParent($dependentTest);
continue;
}

if (false === strpos($dependency, '::')) {
if (false === strpos($dependency->dependency, '::')) {
$class = $test->getMethod()->getDeclaringClass()->getName();
$method = $dependency;
$method = $dependency->dependency;
} else {
[$class, $method] = explode('::', $dependency, 2);
[$class, $method] = explode('::', $dependency->dependency, 2);
}

if (!method_exists($class, $method)) {
throw new \RuntimeException(sprintf('Failed to build test pool "%s" dependency is not resolvable for "%s::%s".', $dependency, $test->getMethod()->getDeclaringClass()->getName(), $test->getMethod()->getName()));
throw new \RuntimeException(sprintf('Failed to build test pool "%s" dependency is not resolvable for "%s::%s".', $dependency->dependency, $test->getMethod()->getDeclaringClass()->getName(), $test->getMethod()->getName()));
}

$dependentTest = new Test(new \ReflectionMethod($class, $method), null, false);
Expand All @@ -71,7 +72,7 @@ private function processTestAnnotations(\ArrayObject $tests, Test $test): void
$tests[$dependentTest->getIdentifier()] = $dependentTest;
}

$dependentTest->addChildren($test);
$dependentTest->addChildren($test, $dependency->skipIfFailed);
$test->addParent($dependentTest);
}

Expand Down
36 changes: 19 additions & 17 deletions src/Test.php
Expand Up @@ -19,8 +19,6 @@ class Test
/** @var mixed[] */
private array $arguments = [];

private \ReflectionMethod $method;

/** @var string[] */
private array $assertions = [];

Expand All @@ -30,24 +28,19 @@ class Test

private string $displayName;

private bool $isRealTest;

public function __construct(\ReflectionMethod $reflectionMethod, string $identifier = null, bool $isRealTest = true)
public function __construct(
private readonly \ReflectionMethod $method,
string $identifier = null,
public readonly bool $isRealTest = true,
)
{
$this->method = $reflectionMethod;
$this->identifier = $identifier ?: sprintf(
'%s::%s',
$this->method->getDeclaringClass()->getName(),
$this->method->getName()
);
$this->displayName = $this->identifier;
$this->state = self::STATE_PENDING;
$this->isRealTest = $isRealTest;
}

public function isRealTest(): bool
{
return $this->isRealTest;
}

public function isCompleted(): bool
Expand Down Expand Up @@ -100,9 +93,12 @@ public function getMethod(): \ReflectionMethod
return $this->method;
}

public function addChildren(Test $test): void
public function addChildren(Test $test, bool $skipIfFailed): void
{
$this->children[] = $test;
$this->children[] = [
'test' => $test,
'skipIfFailed' => $skipIfFailed,
];
}

public function addParent(Test $test): void
Expand Down Expand Up @@ -135,11 +131,17 @@ public function getParents(): array
}

/**
* @return Test[]
* @return iterable<Test>
*/
public function getChildren(): array
public function getChildren(bool $onlySkipIfFailed = false): iterable
{
return $this->children;
foreach ($this->children as $child) {
if ($onlySkipIfFailed && !$child['skipIfFailed']) {
continue;
}

yield $child['test'];
}
}

/** @return mixed[] */
Expand Down
2 changes: 1 addition & 1 deletion src/TestWorkflow.php
Expand Up @@ -52,7 +52,7 @@ public function markTestAsFailed(Test $test, \Throwable $error): void
$this->output->outputFailure($test, $debugOutput, $error);
}

foreach ($test->getChildren() as $child) {
foreach ($test->getChildren(true) as $child) {
$this->markTestAsSkipped($child);
}
}
Expand Down
4 changes: 2 additions & 2 deletions tests/WebAndApiTests.php
Expand Up @@ -18,8 +18,8 @@ class WebAndApiTests
HttpClientWebCaseTrait::put insteadof HttpClientApiCaseTrait;
HttpClientWebCaseTrait::options insteadof HttpClientApiCaseTrait;
HttpClientWebCaseTrait::delete insteadof HttpClientApiCaseTrait;
HttpClientApiCaseTrait::get as private getApi;
HttpClientApiCaseTrait::post as private postApi;
HttpClientApiCaseTrait::get as getApi;
HttpClientApiCaseTrait::post as postApi;
HttpClientApiCaseTrait::patch as patchApi;
HttpClientApiCaseTrait::put as putApi;
HttpClientApiCaseTrait::options as optionsApi;
Expand Down

0 comments on commit 3bcfefe

Please sign in to comment.