Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Atoum Laravel Package

mageekguy/atoum

atoum is a modern, standalone PHP unit testing framework with an expressive assertion API, built-in mocking, code coverage, and clear reports. Its simple, intuitive DSL and fluent syntax help developers write and run tests quickly, making PHP testing more enjoyable, readable, and less verbose.

Deep Wiki
Context7

Getting Started

atoum is a unit-testing framework with a fluent, object-based assertion API ($this->string($x)->isEqualTo(...)), first-class mock generation via a magic \mock\ namespace, and per-file process isolation. Tests are plain classes extending atoum\test; methods prefixed with test are discovered and run.

Install the Composer package (published as atoum/atoum, repo/namespace mageekguy/atoum):

composer require --dev atoum/atoum

Minimum viable setup — a tests/units directory and a test whose file/namespace/class line up:

<?php
// tests/units/Calculator.php
namespace tests\units;

use mageekguy\atoum;

class Calculator extends atoum\test
{
    public function testAdd()
    {
        $this->integer(2 + 2)->isEqualTo(4);
    }
}

Run it:

./vendor/bin/atoum -d tests/units        # whole directory
./vendor/bin/atoum -f tests/units/Calculator.php   # one file while iterating

For anything beyond a smoke test, add a root .atoum.php so ./vendor/bin/atoum needs no arguments:

<?php
$runner->addTestsFromDirectory(__DIR__ . '/tests/units');
$runner->setBootstrapFile(__DIR__ . '/vendor/autoload.php');

Where to look first: .atoum.php (runner/bootstrap/coverage config), the base class vendor/atoum/atoum/classes/test.php, and the classes/asserters/ directory to see every available asserter method. The docs at atoum.org are useful but stale; the source is the source of truth.

First real use case: characterization-test an existing service. Instantiate it with newTestedInstance(), mock one collaborator, call a method, and assert the return value and the collaborator interaction. That gives you a safety net before refactoring and exercises the three features you'll use daily: asserters, mocks, and testedInstance.

Implementation Patterns

Tested instance instead of manual new. atoum derives the class under test from the test's namespace (tests\units\Foo → Foo) and gives you a property:

$this->newTestedInstance($mailer, $clock);
$this->testedInstance->sendInvoice($invoice);
$this->boolean($this->testedInstance->isSent())->isTrue();

Mocks with call assertions. Generate a mock from a concrete class, interface, or abstract class, stub methods through the mock controller, then verify interactions with the mock asserter:

$mailer = new \mock\MailerInterface();
$mailer->getMockController()->send = true;

$this->newTestedInstance($mailer);
$this->testedInstance->sendInvoice($invoice);

$this->mock($mailer)
    ->call('send')
    ->withArguments($invoice)
    ->once();

For dynamic class names use $this->newMockInstance($class). Stub before the code under test runs, otherwise the real path is taken.

Exception assertions. Wrap the throwing code in a closure and assert on the exception object:

$this
    ->exception(function () use ($service) {
        $service->withdraw(10);
    })
        ->isInstanceOf(\RuntimeException::class)
        ->hasMessage('Insufficient funds');

Deterministic time/random. atoum can intercept native function calls from the tested code, which is far cleaner than injecting a clock for a one-line time() call:

$this->function->time = function () { return 1_600_000_000; };

(Supported in current 3.x/4.x; only covers calls made in the same process as the test.)

Data providers. Annotate the test and return an array of argument arrays from a provider method — useful for table-driven validation tests. If your pinned version predates @dataProvider support, loop over the cases inside one test instead.

Hooks. beforeTestMethod($method) / afterTestMethod($method) are your setUp/tearDown. atoum creates a fresh test object per method, so instance properties are effectively per-test — but statics and singletons are not reset; clear them in the hooks.

Shared base test class. Put custom asserters and fixture helpers in tests\units\base extends atoum\test, then have suites extend it. Custom assertion methods (e.g. assertValidEmail()) compose existing asserters and keep tests readable.

CI integration. Emit a JUnit/XML report field (or use the reports extension) so your CI can ingest results, add a Composer script ("test": "atoum -d tests/units"), and use -f plus -v for local triage. Tags/annotations let you exclude slow or integration suites from the default run.

Gotchas and Tips

  • Maintenance risk. This is the legacy root repo; the framework's last significant release is 4.x (2020) and the low score reflects low activity. It still runs, but expect friction on PHP 8.1+ (dynamic-property deprecations from mocks) and no roadmap. Pin the version and budget a PHPUnit/Pest migration for new projects.
  • Package/namespace mismatch. The Composer package is atoum/atoum while the GitHub repo and PHP namespace remain mageekguy\atoum. Don't let a composer require mageekguy/atoum failure derail setup.
  • Discovery depends on file/namespace/class agreement. atoum maps paths to class names; a test class that isn't autoloadable or doesn't match its directory silently won't run. Register tests\units\ (and your src\) in composer.json autoload/autoload-dev, and keep one class per file.
  • Assertions are fail-fast. A failed assertion throws and aborts the rest of the test method. Don't pile unrelated checks into one method; split them so you see every failure in one run.
  • Void tests. A test* method that asserts nothing is reported as "void" — historically it does not fail the run. Make void methods fatal in runner config so a half-written test can't masquerade as green.
  • Mock controller typos are silent. $mock->getMockController()->sned = ... does nothing; the method returns null and your test passes for the wrong reason. Always pair stubs with a $this->mock(...)->call(...) assertion on the methods you care about.
  • Unmockable things. Final classes, final methods, and static calls can't be mocked. Introduce a seam (wrapper/adapter) rather than fighting the framework.
  • Process isolation surprises. atoum runs each test file in a child process. This is great for state isolation and crash resilience, but it means xdebug/coverage settings must be inherited, var_dump output can interleave, and debugger breakpoints must target child processes.
  • Config double-loading. .atoum.php is picked up from the working directory and from tested directories; if both call addTestsFromDirectory, tests run twice. Keep one source of truth.
  • Coverage requires Xdebug. pcov isn't supported. Under Xdebug 3 set xdebug.mode=coverage; coverage is slow and must be enabled in the report configuration, not just by running the binary.
  • Exit codes. A missing/typo'd test directory can look like a successful run depending on how you invoke atoum. Assert in CI that the expected test count was executed.
  • Debugging recipe. Reproduce with ./vendor/bin/atoum -f path/to/Test.php -v, then attach a debugger to the spawned child or temporarily run the logic from a small script. Reading the full asserter failure output (expected vs. actual, call arguments) usually beats stepping through.
  • Extension points. Custom asserters (via a base test class), custom report fields (for CI formats), and runner extensions loaded in .atoum.php are the supported seams; the atoum/bdd-extension gives a given/when/then DSL if your team prefers that style.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums
rlacerda83/query-parser
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings