Inline tests in Testo (#[TestInline])
SkillDev toolsAttach #[TestInline] cases directly to production methods so the example/doctest lives next to the implementation. Use when the user asks for "inline tests", "doctests", "examples next to code", or wants quick example-based verification of a pure function without a dedicated test class.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Inline tests in Testo (#[TestInline]) skill
What this skill tells your AI
The instructions your AI receives, as published by php-testo/testo in skills/testo-inline-tests/SKILL.md and read by ahel’s review.
#[TestInline] lets you attach example inputs and an expected return value directly to a method
in production code. The Testo runner discovers and executes them like normal tests, but they live
next to the implementation — handy for pure functions and library primitives.
This requires the InlineTestPlugin to be enabled for the suite that scans the relevant directory.
Fetch https://php-testo.github.io/llms.txt for the attribute signature and llms-full.txt for the
plugin wiring details — verify them before generating code, the API surface is small but specific.
Canonical shape
<?php
declare(strict_types=1);
namespace App\Math;
use Testo\Inline\TestInline;
final class Vector
{
#[TestInline([1, 2], 3)]
#[TestInline([5, 10], 15)]
#[TestInline([-1, 1], 0)]
public static function sum(int $a, int $b): int
{
return $a + $b;
}
}
- Each
#[TestInline]attribute = one case. - First argument: array of method arguments (positional).
- Second argument: expected return value (compared with strict equality).
- The decorated method must be deterministic and side-effect-free — inline tests aren't for I/O or stateful code.
When inline tests are the right choice
Use #[TestInline] when all of the following hold:
- The method is pure (same inputs → same output, no side effects).
- The examples document behaviour that readers of the source will benefit from seeing.
- Each example fits comfortably on one line.
Otherwise prefer a regular #[Test] class — testo-write-tests skill.
When inline tests are wrong
- The method has dependencies that need wiring (use DI + a normal test).
- The expected value isn't a simple literal (no fluent chain, no objects with identity).
- The test needs setup/teardown —
#[TestInline]cannot use#[BeforeTest]hooks. - You want to assert exceptions — use
Expect::exception(...)inside a regular test.
Configuration check
For inline tests to run, the suite scanning the production directory must include InlineTestPlugin.
Excerpt from testo.php:
use Testo\Application\Config\Plugin\SuitePlugins;
use Testo\Inline\InlineTestPlugin;
new SuiteConfig(
name: 'Sources',
location: ['src'],
plugins: SuitePlugins::only(new InlineTestPlugin()),
),
If the user adds #[TestInline] but the test never runs, check the suite plugin list first.
Pitfalls
- Don't put
#[TestInline]on methods that touch globals, the filesystem, time, or randomness. - Don't try to label cases with a third argument — case identity is the attribute position. Re-order, don't relabel.
- A failing
#[TestInline]reports the method's FQN + the attribute index as the test identifier. Order matters for diff readability.
Signals
- GitHub stars
- 213
- Forks
- 16
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
testo-inline-tests- Source
- github.com/php-testo/testo