You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Tests use inline anonymous classes with PHP 8.1+ attributes, snake_case method names, and high-level behavioral assertions. Use this skill when writing or debugging any Ecotone test.
15
17
18
+
## 0. Test-First Rule (MANDATORY)
19
+
20
+
Every new feature or bug fix **MUST** start with a test written using **Ecotone Lite** (`EcotoneLite::bootstrapFlowTesting()` or `EcotoneLite::bootstrapForTesting()`). This is a blocking requirement — do not write production code before the test exists.
21
+
22
+
**Tests must follow the userland perspective.** Each test should read like an example of how an Ecotone end-user would use the feature in their application. The test sets up real handler classes (inline anonymous classes with attributes), sends commands/events/queries through the bus, and asserts on the outcome — exactly as a user would interact with the framework. Never test framework internals directly; instead, demonstrate the feature through its public API as seen by the user.
23
+
24
+
**Workflow:**
25
+
1.**Write the test first** using Ecotone Lite — model it as a real-world usage example from the user's perspective
26
+
2. Run the test — confirm it fails (red)
27
+
3. Write the minimal production code to make it pass (green)
28
+
4. Refactor if needed
29
+
30
+
**Example test-first skeleton (userland perspective with inline classes):**
31
+
32
+
```php
33
+
public function test_placing_order_publishes_event(): void
34
+
{
35
+
$ecotoneLite = EcotoneLite::bootstrapFlowTesting(
36
+
[new class {
37
+
private array $products = [];
38
+
39
+
#[CommandHandler]
40
+
public function placeOrder(#[Header('orderId')] string $orderId, #[Header('product')] string $product): void
41
+
{
42
+
$this->products[$orderId] = $product;
43
+
}
44
+
45
+
#[QueryHandler('order.getProduct')]
46
+
public function getProduct(string $orderId): string
Tests use **inline anonymous classes** defined directly inside the test method — never create separate fixture files. This keeps each test self-contained and readable as a complete usage example. **Never use static properties or static methods** in test classes — use instance properties and instance methods only. The test demonstrates **how a user would use the feature** — registering handlers, sending commands, and querying results. It does not test internal message routing, channel resolution, or framework wiring directly.
63
+
64
+
This applies to **all** code changes that add or modify behavior — features, bug fixes, refactors that change behavior. Pure refactors with no behavior change may skip this if existing tests already cover the behavior.
0 commit comments