Usage
Make Test
After creating and completing your configuration file, you can use the command to create architecture tests:
php bin/structura make:testHere's a simple example of architecture testing for your DTOs:
use StructuraPhp\Structura\Asserts\ToExtendNothing;
use StructuraPhp\Structura\Attributes\TestDox;
use StructuraPhp\Structura\Expr;
use StructuraPhp\Structura\Testing\TestBuilder;
use Symfony\Component\Finder\Finder;
final class TestDto extends TestBuilder
{
#[TestDox('Asserts rules Dto architecture')]
public function testAssertArchitectureRules(): void
{
$this
->allClasses()
->fromDir(
'app/Dto',
fn(Finder $finder) => $finder->depth('== 0')
)
->that($this->conditionThat(...))
->except($this->exception(...))
->should($this->should(...));
}
private function that(Expr $expr): void
{
$expr->toBeClasses();
}
private function exception(Except $except): void
{
$except
->byClassname(
className: [
FooDto::class,
BarDto::class,
],
expression: ToExtendNothing::class
);
}
private function should(Expr $expr): void
{
$expr
->toBeFinal()
->toBeReadonly()
->toHaveSuffix('Dto')
->toExtendsNothing()
->toHaveMethod('fromArray')
->toImplement(\JsonSerializable::class);
}
}Analysis Types
allClasses()
Analysis of classes. A class MUST be present, otherwise an exception is raised.
$this->allClasses()allScripts()
Analysis of all PHP scripts. All PHP code can be analysed, but only script rules can be used.
$this->allScripts()File Selection
fromDir()
Takes the path of the files to be analysed. It accepts an optional second closure parameter to customise the Finder:
->fromDir(
'src/Dto',
static fn(Finder $finder): Finder => $finder->depth('== 0')
)fromRaw()
Test PHP code in the form of a string. You can provide a file name as the second parameter. If null, it defaults to tmp\run_<count>.php:
->fromRaw(
raw: '<?php
use ArrayAccess;
use Depend\Bap;
use Depend\Bar;
class Foo implements \Stringable {
public function __construct(ArrayAccess $arrayAccess) {}
public function __toString(): string {
return $this->arrayAccess[\'foo\'] ?? throw new \Exception();
}
}',
pathname: 'path/example_1.php'
)fromRawMultiple()
Test multiple PHP code snippets. You can provide file names as array keys. If numeric, they default to tmp\run_<count>.php:
->fromRawMultiple([
'path/example_1.php' => '<?php /* ... */',
'path/example_2.php' => '<?php /* ... */',
])Filtering
that()
Specifies rules for targeting class analysis (optional):
// with allClasses()
->that(static fn(Expr $expr): Expr => $expr->toBeClasses())
// with allScripts()
->that(static fn(ExprScript $expr): ExprScript => $expr->toBeClasses())Exceptions
except()
Exclude specific classes or patterns from rules.
byClassname()
Ignore rules for specific classes by their fully qualified class name:
->except(static fn(Except $except): Except => $except
->byClassname(
className: [
FooDto::class,
BarDto::class,
],
expression: ToExtendNothing::class
)
)byNamespace()
Ignore rules for classes in specific namespaces (supports regex patterns):
->except(static fn(Except $except): Except => $except
->byNamespace(
namespace: 'App\Tests\.*',
expression: ToExtendNothing::class
)
)byFileName()
Ignore rules for scripts matching a filename regex pattern:
->except(static fn(Except $except): Except => $except
->byFileName(
filePattern: '/migrations\/.*\.php$/',
expression: ToBeClasses::class
)
)Rules
should()
List of architecture rules (required):
// with allClasses()
->should(static fn(Expr $expr): Expr => $expr
->toBeFinal()
->toBeReadonly()
->toHaveSuffix('Dto')
->toExtendsNothing()
->toHaveMethod('fromArray')
->toImplement(\JsonSerializable::class)
)
// with allScripts()
->should(static fn(ExprScript $expr): ExprScript => $expr)