105 lines
4.9 KiB
YAML
105 lines
4.9 KiB
YAML
uuid:
|
|
- value: c337a375-7fec-45d9-ad89-60ece71c2194
|
|
langcode:
|
|
- value: en
|
|
type:
|
|
- target_id: daily_email
|
|
target_type: node_type
|
|
target_uuid: 8bde1f2f-eef9-4f2d-ae9c-96921f8193d7
|
|
revision_timestamp:
|
|
- value: '2025-06-25T07:00:48+00:00'
|
|
revision_uid:
|
|
- target_type: user
|
|
target_uuid: b8966985-d4b2-42a7-a319-2e94ccfbb849
|
|
revision_log: { }
|
|
status:
|
|
- value: true
|
|
uid:
|
|
- target_type: user
|
|
target_uuid: b8966985-d4b2-42a7-a319-2e94ccfbb849
|
|
title:
|
|
- value: 'Consistency with architectural testing'
|
|
created:
|
|
- value: '2025-06-22T06:58:19+00:00'
|
|
changed:
|
|
- value: '2025-06-25T07:00:48+00:00'
|
|
promote:
|
|
- value: false
|
|
sticky:
|
|
- value: false
|
|
default_langcode:
|
|
- value: true
|
|
revision_translation_affected:
|
|
- value: true
|
|
path:
|
|
- alias: /daily/2025/06/22/consistency-architectural-testing
|
|
langcode: en
|
|
body:
|
|
- value: |-
|
|
Yesterday, I asked whether class names should include suffixes or be named a certain way in your application.
|
|
|
|
I said that [consistency is key][1].
|
|
|
|
But how do you enforce these rules to keep things consistent?
|
|
|
|
It could be done manually in a code review or pair programming session, but it would be better if it could be automated.
|
|
|
|
Similar to phpcs for code linting and automated tests that ensure functionality works as expected, architectural tests allow you to define and run your own architectural rules.
|
|
|
|
For example, I could write this to ensure Action classes don't have the `Action` suffix:
|
|
|
|
```php
|
|
function test_action_classes_are_not_suffixed(): Rule
|
|
{
|
|
return PHPat::rule()
|
|
->classes(Selector::inNamespace('App\Action'))
|
|
->shouldBeNamed(
|
|
fqcn: '/^(?!.*Action$).*$/',
|
|
regex: TRUE,
|
|
);
|
|
}
|
|
```
|
|
|
|
This is using PHPat - an extension for PHPStan - that finds all classes in an `App\Action` namespace and checks the class name matches the given format.
|
|
|
|
If the class name is incorrect, PHPStan will return an error:
|
|
|
|
> App\Action\DoesSomethingAction should be named matching the regex /^(?!.*Action$).*$/
|
|
|
|
I [created more examples][0] to ensure the classes are final, read-only and don't extend or implement anything.
|
|
|
|
PHPat has [an examples page][2] of potential use cases for architectural tests, and how to implement layered architectures or Model-View-Controller.
|
|
|
|
Pest PHP also has an architectural testing library so, if you use PHP, try both and see which works best for you.
|
|
|
|
[0]: https://code.oliverdavies.uk/opdavies/phpat-example/src/commit/cf07cec6d20bd4f6108736efdfbd2af549df2748/tests/Architecture/ArchitectureTest.php
|
|
[1]: /daily/2025/06/21/consistency-key
|
|
[2]: https://www.phpat.dev/examples
|
|
format: markdown
|
|
processed: |
|
|
<p>Yesterday, I asked whether class names should include suffixes or be named a certain way in your application.</p>
|
|
<p>I said that <a href="/daily/2025/06/21/consistency-key">consistency is key</a>.</p>
|
|
<p>But how do you enforce these rules to keep things consistent?</p>
|
|
<p>It could be done manually in a code review or pair programming session, but it would be better if it could be automated.</p>
|
|
<p>Similar to phpcs for code linting and automated tests that ensure functionality works as expected, architectural tests allow you to define and run your own architectural rules.</p>
|
|
<p>For example, I could write this to ensure Action classes don't have the <code>Action</code> suffix:</p>
|
|
<pre><code>function test_action_classes_are_not_suffixed(): Rule
|
|
{
|
|
return PHPat::rule()
|
|
->classes(Selector::inNamespace('App\Action'))
|
|
->shouldBeNamed(
|
|
fqcn: '/^(?!.*Action$).*$/',
|
|
regex: TRUE,
|
|
);
|
|
}
|
|
</code></pre><p>This is using PHPat - an extension for PHPStan - that finds all classes in an <code>App\Action</code> namespace and checks the class name matches the given format.</p>
|
|
<p>If the class name is incorrect, PHPStan will return an error:</p>
|
|
<blockquote><p>App\Action\DoesSomethingAction should be named matching the regex /^(?!.<em>Action$).</em>$/</p>
|
|
</blockquote>
|
|
<p>I <a href="https://code.oliverdavies.uk/opdavies/phpat-example/src/commit/cf07cec6d20bd4f6108736efdfbd2af549df2748/tests/Architecture/ArchitectureTest.php">created more examples</a> to ensure the classes are final, read-only and don't extend or implement anything.</p>
|
|
<p>PHPat has <a href="https://www.phpat.dev/examples">an examples page</a> of potential use cases for architectural tests, and how to implement layered architectures or Model-View-Controller.</p>
|
|
<p>Pest PHP also has an architectural testing library so, if you use PHP, try both and see which works best for you.</p>
|
|
summary: ''
|
|
field_daily_email_cta:
|
|
- target_type: node
|
|
target_uuid: 3074e1e9-c691-4f73-a71c-cfe5920f884e
|