Execution Model
DocTest executes each code block in an isolated PHP process. This page explains the execution model in detail.
Process Isolation
Every code block runs in its own PHP subprocess via proc_open. This provides:
- No side effects — A fatal error in one block doesn't affect others
- Memory safety — Memory leaks are contained to the subprocess
- Clean state — Each block starts fresh with no implicit dependencies
- Timeout protection — Runaway code is killed after the configured timeout
Code Generation
Before execution, DocTest transforms each code block into a self-contained PHP script:
Normal Blocks
php
<?php
$__doctest_results = [];
$__doctest_segment = 0;
ob_start();
echo 'Hello, World!';
$__doctest_output = ob_get_clean();
$__doctest_results[] = [
'type' => 'output',
'expected' => 'Hello, World!',
'actual' => $__doctest_output,
'line' => 3,
];
$__doctest_segment++;
fwrite(STDERR, json_encode($__doctest_results));Key aspects:
- Output is captured via
ob_start()/ob_get_clean() - Results are written to
STDERRas JSON - Each assertion type generates appropriate instrumentation
Throws Blocks
php
<?php
try {
throw new RuntimeException('Error');
fwrite(STDERR, json_encode(['thrown' => false]));
} catch (\Throwable $__doctest_e) {
fwrite(STDERR, json_encode([
'thrown' => true,
'class' => get_class($__doctest_e),
'message' => $__doctest_e->getMessage(),
]));
}The code is wrapped in a try/catch to capture exception details.
Grouped Execution
Blocks with the same group attribute execute in a single process:
- All blocks in the group are concatenated into one script
setupblocks are prepended,teardownblocks are appended- Assertions are partitioned back to their original blocks for reporting
- Variables persist across group blocks within the same process
Process Runner
The process runner manages subprocess execution:
- Uses
proc_openwith pipes for STDIN, STDOUT, and STDERR - Enforces the configured timeout (default: 30 seconds)
- Sets the configured memory limit (default: 256M) via
php -d memory_limit=... - Captures exit code, STDOUT, and STDERR
Result Evaluation
After execution, results flow through the comparator:
- Output assertions — Captured output is compared against expected values
- Wildcard matching — If wildcards are present, the expected value is converted to regex
- Normalization — Trailing whitespace is trimmed, line endings are unified
- Diff generation — For failed comparisons, a unified diff is generated
Temp File Cleanup
Generated scripts are written to the system temp directory (sys_get_temp_dir()) with a doctest_ prefix and cleaned up after execution. Each file has a random suffix to avoid collisions.