README.md

May 20, 2026 · View on GitHub

TESTO

The PHP Testing Framework You Control

Documentation Support on Boosty


Testo is an extensible testing framework built on a lightweight core with a middleware system. It gives you full control over your testing environment while keeping the familiar PHP syntax you already know.

Get Started

Installation

composer require --dev testo/testo *

PHP Latest Version on Packagist License Total Destroys

Configuration

The fastest way to set up Testo in your project is the built-in init command:

vendor/bin/testo init

It will:

  • detect your src/ directory (or prompt for it),
  • create tests/Unit/ if missing,
  • generate a minimal testo.php next to your composer.json,
  • register composer test and composer test:<suite> scripts.

For a sub-app layout, point it at the project root: vendor/bin/testo init --path=app.

Tuning testo.php manually

testo.php is plain PHP returning an ApplicationConfig — edit it freely to add suites, plugins, or coverage. A typical setup looks like:

<?php

declare(strict_types=1);

use Testo\Application\Config\ApplicationConfig;
use Testo\Application\Config\Plugin\SuitePlugins;
use Testo\Application\Config\SuiteConfig;
use Testo\Bench\BenchmarkPlugin;
use Testo\Inline\InlineTestPlugin;

return new ApplicationConfig(
    src: ['src'],
    suites: [
        new SuiteConfig(
            name: 'Sources',
            location: ['src'],
            // Only Benchmarking and Inline Tests for Source files
            plugins: SuitePlugins::only(
                new InlineTestPlugin(),
                new BenchmarkPlugin(),
            ),
        ),
        new SuiteConfig(
            name: 'Unit',
            location: ['tests/Unit'],
        ),
    ],
);

If no testo.php is present at all, Testo falls back to running every test under the tests/ folder.

Running Tests

To run your tests, execute:

composer test

…or call the binary directly if you skipped init / didn't register the script:

vendor/bin/testo

You can also run a single suite by name (one script per detected suite is registered by init):

composer test:unit
composer test:integration

Writing Your First Test

Create a test class in the configured test directory (e.g., tests/CalculatorTest.php):

<?php

declare(strict_types=1);

namespace Tests;

use Testo\Assert;
use Testo\Assert\ExpectException;
use Testo\Retry;
use Testo\Test;

#[Test]
final class CalculatorTest
{
    public function dividesNumbers(): void
    {
        $result = 10 / 2;

        Assert::same($result, 5.0);
        Assert::notSame($result, 5); // Types matter!
    }

    #[Retry(maxAttempts: 3)]
    public function flakyApiCall(): void
    {
        // Retries up to 3 times if test fails
        $response = $this->makeExternalApiCall();

        Assert::same($response->status, 200);
    }

    #[ExpectException(\RuntimeException::class)]
    public function throwsException(): void
    {
        throw new \RuntimeException('Expected error');
    }
}

What to note:

  • Use the #[Test] attribute to mark test methods or classes
  • Test classes don't need to extend any base class
  • Use Assert class for assertions (same, true, false, null, contains, instanceOf, etc.)
  • Testo provides multiple attributes to extend testing capabilities (retry policies, exception handling, and more)

IDE Support

Testo comes with the IDEA plugin Testo.

Version Rating Downloads