pestphp/pest · error · TestAlreadyExist
A test named [%s] already exists in [%s]. Please give this t
Error message
A test named [%s] already exists in [%s]. Please give this test a different description.
What it means
Within a single test file, Pest registers each test by its description; addMethod throws TestAlreadyExist when a description already exists in that file's test case. The check is an exact array_key_exists on the description string, so two tests with the identical description collide even if their bodies differ.
Source
Thrown at src/Factories/TestCaseFactory.php:187
eval($classCode);
} catch (ParseError $caught) {
throw new RuntimeException(sprintf(
"Unable to create test case for test file at [%s]. \n %s",
$filename,
$classCode
), 1, $caught);
}
}
public function addMethod(TestCaseMethodFactory $method): void
{
if ($method->description === null) {
throw new TestDescriptionMissing($method->filename);
}
if (array_key_exists($method->description, $this->methods)) {
throw new TestAlreadyExist($method->filename, $method->description);
}
if (
$method->closure instanceof \Closure &&
new \ReflectionFunction($method->closure)->isStatic()
) {
throw new TestClosureMustNotBeStatic($method);
}
if (! $method->receivesArguments()) {
if (! $method->closure instanceof \Closure) {
throw ShouldNotHappen::fromMessage('The test closure may not be empty.');
}
$arguments = Reflection::getFunctionArguments($method->closure);
if ($arguments !== []) {View on GitHub (pinned to 1af74a215c)
Solutions
- Rename the second test to a unique description in that file.
- Make duplicated cases data-driven instead of copy-pasted: one test + ->with([[...], [...]]).
- Prefix titles inside describe blocks if you intentionally repeat inner names (check the file's other descriptions first — the message names both file and description).
Example fix
// before
it('validates email', fn () => ...);
it('validates email', fn () => ...); // duplicate
// after
it('validates email format', fn () => ...);
it('validates email domain', fn () => ...); Defensive patterns
Strategy: validation
Validate before calling
// guard in test-generator helpers:
static $seen = [];
if (isset($seen[$description])) {
throw new LogicException("Duplicate test description [{$description}]");
}
$seen[$description] = true;
test($description, $closure); Prevention
- When copy-pasting a test, change the description in the same edit.
- Prefer datasets over duplicated near-identical tests.
- Use descriptive, scenario-specific titles; generic ones ('works') collide easily within a file.
When it happens
Trigger: Two it('creates a user', ...) blocks in the same file (classic copy-paste); dataset-driven tests where the same description template is reused without interpolation; describe() blocks in one file reusing the same inner test name across different describes (Pest namespaces describes in output but the factory keys per file).
Common situations: Copy-paste test growth; merging branches that both added a test with the same title; refactoring big files by duplicating a block and intending to edit the title later; non-descriptive titles ('works', 'test 1') colliding.
Related errors
- A test in [%s] is missing its description. Please give every
- Test closures may not be static. Please remove the [static]
- The test [%s] in [%s] expects [%d] argument(s) ([%s]), but n
- The test directory [%s] does not exist.
- Cached failure
AI-assisted analysis of pestphp/pest@1af74a215c (2026-08-21).
Data as JSON: /api/errors/89432bb3641c888f.
Report an issue: GitHub.