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

Versionbasedtestskipper Laravel Package

ciaranmcnulty/versionbasedtestskipper

A PHPUnit extension that skips tests based on the running PHP version, letting you annotate tests with version constraints so they are automatically skipped or run on specific PHP versions, keeping suites passing across environments without manual conditional logic.

View on GitHub
Deep Wiki
Context7

Getting Started

ciaranmcnulty/versionbasedtestskipper is a small dev-only library that lets a test declare “skip me on this PHP version range” without rewriting the test for every entry in your CI matrix.

  1. Install it as a dev dependency:
composer require --dev ciaranmcnulty/versionbasedtestskipper
  1. Look at composer.json and src/ first. The package is small enough that the source is the authoritative documentation; confirm the exact namespace, trait/class name, and annotation spelling for the tag you installed before wiring it into a large suite.

  2. Mix the skipper into your base test case so every test inherits the behaviour:

namespace Tests;

use CiaranMcNulty\VersionBasedTestSkipper\VersionBasedTestSkipper;
use PHPUnit\Framework\TestCase as BaseTestCase;

abstract class TestCase extends BaseTestCase
{
    use VersionBasedTestSkipper;
}
  1. First real use case — a test that exercises syntax or behaviour only available on newer PHP, on a project that still runs PHP 7.4 in CI:
/**
 * @skipOnPhp <8.0
 */
public function testNamedArgumentsAreSupported(): void
{
    // ...
}

On PHP 7.4 the test is marked skipped; on PHP 8.x it runs normally. That is the core value: your matrix stays green while version-specific tests remain in the suite and are visible as skipped rather than silently deleted.

Implementation Patterns

Centralise the trait, annotate locally. Put the skipper on the project’s Tests\TestCase and keep the PHP-version annotations on individual test methods. This avoids repeating setup and makes the version assumptions discoverable next to the code they constrain.

Use it for “known incompatible”, not “hard requirement”. For a genuine requirement (the test cannot possibly run without a feature), prefer PHPUnit’s native @requires PHP >= 8.0 or #[RequiresPhp('>= 8.0')]. The skipper is most useful for the inverse case: the test is valid and should run, but a known bug or behaviour change makes it fail on certain versions.

Pair with a CI matrix. Run the suite on each supported PHP version (e.g. 7.4, 8.0, 8.1, 8.2) and let the annotations carve out the incompatible cells. The output becomes self-documenting: a skipped test on 7.4 and a green test on 8.1 is an explicit statement about your support surface.

Record why a skip exists. Treat each annotation like a TODO with an owner:

/**
 * @skipOnPhp >=8.1
 * @see https://github.com/acme/project/issues/1234
 */
public function testLegacySerialiserOutput(): void
{
    // ...
}

This turns skips into a backlog you can grep, rather than permanent invisible holes.

Keep version-specific files separate. If a test file contains PHP 8 syntax (named arguments, enums, constructor promotion, match), an annotation cannot save it on PHP 7.4: PHP compiles the whole file before PHPUnit ever evaluates the skip. Put those tests in their own file and exclude that file from the older PHPUnit testsuite, or the suite will die with a parse error before any annotation is read.

Beware data providers. PHPUnit resolves data providers before setUp()-style skip hooks in many configurations. If the provider itself uses newer syntax or APIs, the test can fail before the skipper gets a chance to mark it skipped. Keep providers version-neutral and put version-sensitive logic in the test body.

Use it in PhpSpec-style contexts if applicable. The maintainer’s ecosystem is PhpSpec, so check whether the installed tag exposes an extension/example hook as well as a PHPUnit trait. The same constraint concept applies, but the integration point differs.

Prefer partial assertions when only behaviour differs. If a method is merely slower or emits a deprecation on one version, assert conditionally inside the test rather than skipping the whole thing; skipping loses coverage on every other assertion in that method.

Gotchas and Tips

  • Maintenance risk is the headline. Last release was October 2020, with effectively no dependents. Pin the version in composer.json, and treat an upgrade of PHPUnit or PHP as a trigger to re-verify the package. If the API surface you need is two lines of logic, consider inlining a version_compare(PHP_VERSION, ...) guard instead of carrying the dependency.
  • Confirm exact names against the installed source. Single-maintainer packages of this size often have annotation names and namespace casing that are easy to guess wrong. A two-minute read of src/ beats an afternoon of debugging an annotation that was never parsed.
  • Skips are silent. A typo in an annotation, or an unsupported constraint format, usually means the test simply runs and fails — or worse, is skipped everywhere. Add a temporary var_dump(PHP_VERSION_ID) and assert the skip count in CI if you need confidence.
  • Comparators and pre-releases. PHP_VERSION may contain suffixes (8.1.0-dev, 8.0.0RC1). version_compare handles these differently from PHP_VERSION_ID integer comparisons. Decide which semantics you want and verify the package uses the same one; ranges like <8.1 can behave surprisingly on release candidates.
  • 8.0 vs 8.0.0. Constraint strings that look equivalent to a human are not always equivalent to the comparator. Be explicit (<8.0.0) if the package delegates to version_compare.
  • Trait method conflicts. If the skipper hooks setUp() and your base class or a test also defines setUp(), resolve the conflict explicitly with insteadof/as or by calling the trait method. A skipped hook that never runs produces confusing “test not skipped” failures.
  • Don’t let skips mask coverage regressions. On the version you care about most, skipped tests reduce coverage. Track coverage per PHP version and review skip counts when they grow.
  • Distinguish skip from incomplete. Use skip for “this environment cannot run it” and markTestIncomplete for “this is a TODO”. Mixing them makes CI reports misleading.
  • Keep it out of production. It is a require-dev dependency; confirm composer install --no-dev does not autoload it and that your production classmap is unaffected.
  • Static analysis will not validate annotations. PHPStan/Psalm see plain strings. If version constraints matter to correctness, add a lightweight CI grep or a custom rule that checks annotation format, or centralise versions as constants.
  • Debugging checklist: (1) confirm the trait is on the base class actually used by the test, (2) confirm the annotation spelling matches the parser, (3) confirm the file parses on the target PHP version, (4) confirm the data provider ran, (5) dump PHP_VERSION and the parsed constraint. One of those five is almost always the cause.
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.
frankyso/ipaymu
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment