PHPackages                             solidframe/archtest - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Testing &amp; Quality](/categories/testing)
4. /
5. solidframe/archtest

ActiveLibrary[Testing &amp; Quality](/categories/testing)

solidframe/archtest
===================

Architecture testing with fluent API: enforce DDD, CQRS, modular rules as PHPUnit tests for SolidFrame

v0.1.0(3mo ago)08MITPHPPHP ^8.2

Since Apr 12Pushed 3mo agoCompare

[ Source](https://github.com/solidframe/archtest)[ Packagist](https://packagist.org/packages/solidframe/archtest)[ RSS](/packages/solidframe-archtest/feed)WikiDiscussions main Synced 3w ago

READMEChangelog (1)Dependencies (1)Versions (2)Used By (0)

SolidFrame ArchTest
===================

[](#solidframe-archtest)

Architecture testing with fluent API: enforce DDD, CQRS, event-driven, and modular rules as PHPUnit tests.

Write architectural constraints as tests. Break a rule, break the build.

Installation
------------

[](#installation)

```
composer require solidframe/archtest --dev
```

Quick Start
-----------

[](#quick-start)

### Fluent Assertions

[](#fluent-assertions)

```
use SolidFrame\Archtest\Arch;
use PHPUnit\Framework\TestCase;
use PHPUnit\Framework\Attributes\Test;

final class ArchitectureTest extends TestCase
{
    #[Test]
    public function valueObjectsAreFinalAndReadonly(): void
    {
        Arch::assertThat(__DIR__ . '/../src/Domain/ValueObject')
            ->areFinal()
            ->areReadonly();
    }

    #[Test]
    public function domainDoesNotDependOnInfrastructure(): void
    {
        Arch::assertThat(__DIR__ . '/../src/Domain')
            ->doesNotDependOn('App\Infrastructure');
    }

    #[Test]
    public function handlersHaveCorrectSuffix(): void
    {
        Arch::assertThat(__DIR__ . '/../src/Application/Handler')
            ->haveSuffix('Handler');
    }
}
```

### Presets

[](#presets)

Built-in presets enforce common architectural patterns with zero configuration:

```
#[Test]
public function dddRules(): void
{
    Arch::preset('ddd', [
        'domainDir' => __DIR__ . '/../src/Domain',
        'infrastructureDir' => __DIR__ . '/../src/Infrastructure',
        'applicationDir' => __DIR__ . '/../src/Application',
    ])->assert();
}

#[Test]
public function cqrsRules(): void
{
    Arch::preset('cqrs', [
        'commandDir' => __DIR__ . '/../src/Application/Command',
        'queryDir' => __DIR__ . '/../src/Application/Query',
        'handlerDir' => __DIR__ . '/../src/Application/Handler',
    ])->assert();
}

#[Test]
public function eventDrivenRules(): void
{
    Arch::preset('event-driven', [
        'eventDir' => __DIR__ . '/../src/Domain/Event',
    ])->assert();
}

#[Test]
public function modularRules(): void
{
    Arch::preset('modular', [
        'modulesDir' => __DIR__ . '/../modules',
        'contractSubNamespace' => 'Contract', // default
    ])->assert();
}
```

Available Assertions
--------------------

[](#available-assertions)

### Structural

[](#structural)

```
Arch::assertThat($dir)
    ->areFinal()       // all classes must be final
    ->areReadonly()     // all classes must be readonly
    ->areAbstract()    // all classes must be abstract
    ->areInterfaces()  // all must be interfaces
    ->areEnums();      // all must be enums
```

### Naming

[](#naming)

```
Arch::assertThat($dir)
    ->haveSuffix('Handler')     // class name ends with Handler
    ->havePrefix('Abstract');   // class name starts with Abstract
```

### Inheritance

[](#inheritance)

```
Arch::assertThat($dir)
    ->implement(DomainEventInterface::class)   // must implement interface
    ->extend(AbstractEntity::class);           // must extend class
```

### Dependencies

[](#dependencies)

```
Arch::assertThat($dir)
    ->doesNotDependOn('App\Infrastructure')   // no imports from namespace
    ->onlyDependsOn([                         // whitelist allowed namespaces
        'App\Domain',
        'SolidFrame\Core',
        'SolidFrame\Ddd',
    ]);
```

Preset Rules
------------

[](#preset-rules)

### DDD Preset

[](#ddd-preset)

RuleDescriptionDomain isolationDomain must not depend on Infrastructure or ApplicationValueObject finalAll ValueObject classes must be finalValueObject readonlyAll ValueObject classes must be readonly### CQRS Preset

[](#cqrs-preset)

RuleDescriptionCommand immutabilityCommands must be final readonlyQuery immutabilityQueries must be final readonlyHandler pairingEach Command/Query must have a matching Handler (optional)### Event-Driven Preset

[](#event-driven-preset)

RuleDescriptionEvent immutabilityEvents must be final readonlyEvent interfaceEvents must implement DomainEventInterface### Modular Preset

[](#modular-preset)

RuleDescriptionModule isolationCross-module dependencies only allowed through Contract namespaceCustom Presets
--------------

[](#custom-presets)

Implement `PresetInterface` for your own rules:

```
use SolidFrame\Archtest\Preset\PresetInterface;

final readonly class MyCustomPreset implements PresetInterface
{
    public function __construct(private string $srcDir) {}

    public function evaluate(): array
    {
        $violations = [];

        // your validation logic...
        // return array of violation message strings

        return $violations;
    }
}

// Usage
Arch::presetFrom(new MyCustomPreset(__DIR__ . '/../src'))->assert();
```

API Reference
-------------

[](#api-reference)

Class / InterfacePurpose`Arch`Main entry point: `assertThat()` and `preset()``ArchExpectation`Fluent assertion builder`PresetInterface`Contract for custom presets`PresetResult`Wraps preset with `assert()` method`DddPreset`DDD rules (domain isolation, VO immutability)`CqrsPreset`CQRS rules (message immutability, handler pairing)`EventDrivenPreset`Event rules (immutability, interface)`ModularPreset`Module isolation rules`ClassInfo`Metadata about a PHP class`ClassFinder`Discovers classes in directories`DependencyParser`Extracts use-statement dependencies`ArchViolationException`Thrown on rule violationsRelated Packages
----------------

[](#related-packages)

- [solidframe/core](../core) — DomainEventInterface checked by presets
- [solidframe/ddd](../ddd) — ValueObject, Entity conventions enforced
- [solidframe/cqrs](../cqrs) — Command/Query immutability enforced
- [solidframe/phpstan-rules](../phpstan-rules) — Complementary static analysis rules

Contributing
------------

[](#contributing)

This repository is a read-only split of the [solidframe/solidframe](https://github.com/solidframe/solidframe) monorepo, auto-synced on every push to `main`. Issues, pull requests, and discussions belong in the monorepo.

###  Health Score

33

—

LowBetter than 72% of packages

Maintenance81

Actively maintained with recent releases

Popularity4

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity36

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

103d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/97de2a466719393a21a8ce5caef247a1afb8aec5a8974248da0583f4197765b2?d=identicon)[abdulkadir-posul](/maintainers/abdulkadir-posul)

---

Top Contributors

[![abdulkadir-posul](https://avatars.githubusercontent.com/u/88670954?v=4)](https://github.com/abdulkadir-posul "abdulkadir-posul (1 commits)")

### Embed Badge

![Health badge](/badges/solidframe-archtest/health.svg)

```
[![Health](https://phpackages.com/badges/solidframe-archtest/health.svg)](https://phpackages.com/packages/solidframe-archtest)
```

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
