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

Test Traits Laravel Package

selective/test-traits

Selective Test Traits provides reusable PHPUnit and Pest traits for Laravel, helping you cut test boilerplate, keep suites focused, and share common setup across tests. It makes cleaner, more maintainable tests easier to write without repeating helpers.

View on GitHub
Deep Wiki
Context7

Getting Started

Install as a dev dependency only — this is a test-only package and should never land in require:

composer require --dev selective/test-traits

Where to look first: open src/ in the repo rather than the README. Each file is a single trait, and the trait name tells you its concern (assertions, container/bootstrap helpers, mock factories, HTTP/response helpers). Because the package is small and has zero dependents, the source is the documentation — read the trait you intend to use end to end before wiring it in. Check composer.json for the phpunit/phpunit constraint to confirm it matches your PHPUnit major version (9 vs 10/11 matters a lot for attributes vs annotations).

First use case: the lowest-friction entry point is a shared TestCase that pulls in the trait providing the helper you currently copy-paste between test classes. A typical first adoption:

use PHPUnit\Framework\TestCase;
use Selective\TestTraits\...; // pick the trait matching your need

final class MyFeatureTest extends TestCase
{
    use SomeHelperTrait;

    public function testSomething(): void
    {
        $this->assertSomethingCustom($value);
    }
}

Start with one trait, in one test class. Confirm it works with your PHPUnit version and PHP version before rolling it into a base class used by the whole suite.

Implementation Patterns

Compose into a project-level base TestCase. The intended usage is trait reuse, not inheritance from a package class. Create your own tests/TestCase.php, use the traits there, and have every test extend it. This keeps a single seam for later changes and avoids scattering use statements across hundreds of files.

abstract class AppTestCase extends TestCase
{
    use ContainerTrait;
    use AssertionTrait;

    protected function setUp(): void
    {
        parent::setUp();
        $this->bootContainer();
    }
}

Use one trait per capability, not all of them. Because traits are granular, adopt them individually as a need appears. Pulling five traits into a base class on day one makes conflicts and unused surface area much harder to reason about.

Pair with data providers for assertion traits. Custom assertions are most valuable when driven by a provider so the failure message names the case:

/**
 * @dataProvider invalidPayloadProvider
 */
public function testRejectsInvalidPayload(array $payload): void
{
    $this->assertValidationFails($payload);
}

Integration in a container-based app. If the package ships a container/bootstrap trait, use it in setUp() and reset it in tearDown() so state does not leak between tests. Prefer rebuilding a fresh container per test over mutating a shared one.

Use in package development. If you maintain libraries in the same style as selective-php, these traits are designed for that context: small, dependency-light helpers you can vendor into each package's test suite via require-dev without dragging in a framework.

Keep the traits out of production autoloading concerns. Since it is require-dev, composer install --no-dev in production never sees it — but be aware that static analysis (PHPStan/Psalm) run against src/ will not resolve the traits unless you include tests/ in the analysed paths.

Gotchas and Tips

Trait method collisions are the main failure mode. If two traits define the same method, or a trait collides with a method on your base TestCase, PHP fatals at class declaration with a cryptic message. Resolve explicitly:

use TraitA, TraitB {
    TraitA::assertThing insteadof TraitB;
    TraitB::assertThing as assertThingB;
}

Properties in traits are shared namespace. Traits that declare $container, $fixtures, or similar will silently clash with properties on the consuming class or other traits. Audit property names before combining traits in one class.

setUp() ordering is not guaranteed by the trait. If a trait defines setUp() or tearDown(), PHP will use the class's own definition and skip the trait's unless you alias it (use T { setUp as traitSetUp; } then call $this->traitSetUp();). Always call parent::setUp() and any aliased trait setup explicitly.

PHPUnit major-version drift. With a last release dated 2026, the package may target PHPUnit 10/11 conventions (attributes like #[DataProvider], static data providers). If your suite is still on PHPUnit 9 with annotations, verify each trait works before adopting — assertion helpers usually port fine, but anything hooking into test lifecycle or metadata may not.

Static and global state leaks. Helper traits that cache a container, a mock registry, or a config array on $this are per-instance and fine; anything static persists across the whole run. Check for static properties and reset them in tearDown() if present.

Zero dependents means low blast radius but also low signal. Nobody else is filing issues for your edge case. Pin the version in composer.json (e.g. ^1.0) and read the source of any trait you rely on — it is small enough that this takes minutes and saves hours of debugging.

Debugging a failing custom assertion. When a package assertion fails with an unhelpful message, drop a var_dump() into a wrapper method or temporarily copy the trait method into your test class so you can step through it. Because it is a trait, copying the method locally is a legitimate and fast debugging strategy.

Extension points. You cannot subclass a trait, so customization means either (a) aliasing and wrapping trait methods in your base class, or (b) copying the trait into your own tests/Support/ namespace and editing it. For a package this small, (b) is often cleaner than fighting collisions — fork the trait, keep the license header (MIT), and own it.

Autoload in CI. Ensure composer install in CI includes dev dependencies (--no-dev will break the suite). If you cache vendor/, invalidate the cache key on composer.lock changes so the trait version stays in sync with what developers run locally.

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.
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle
adachsoft/api-version-bundle
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
cgv/localized-resource