Skip to content

test_runner: error on test file patterns that do not exist#64345

Open
UditDewan wants to merge 1 commit into
nodejs:mainfrom
UditDewan:fix-test-runner-missing-patterns
Open

test_runner: error on test file patterns that do not exist#64345
UditDewan wants to merge 1 commit into
nodejs:mainfrom
UditDewan:fix-test-runner-missing-patterns

Conversation

@UditDewan

Copy link
Copy Markdown

Currently createTestFileList() only errors when all user-supplied patterns collectively match nothing and none of them contain glob magic. As a result, a nonexistent literal path passed alongside a matching glob is silently dropped:

node --test no-tests-here "spec/*.test.js"   # no-tests-here silently ignored
node --test "spec/*.test.js" --test-reporter tap   # trailing options parsed as patterns, silently ignored

This change adds a per-pattern check: any literal (non-glob) pattern that does not exist on disk is now reported with the existing Could not find '...' error and the run exits with a failure code. Glob patterns that match nothing are intentionally left as-is so existing workflows with optional globs keep working, and the existing all-patterns check is preserved.

Added test cases to test/parallel/test-runner-cli.js covering both repros from the issue, for both --test-isolation=none and process.

Fixes: #64109

Report each literal positional argument that does not match an
existing file instead of silently dropping it.

Fixes: nodejs#64109
@nodejs-github-bot

Copy link
Copy Markdown
Collaborator

Review requested:

  • @nodejs/test_runner

@nodejs-github-bot nodejs-github-bot added needs-ci PRs that need a full CI run. test_runner Issues and PRs related to the test runner subsystem. labels Jul 7, 2026
Comment on lines +165 to +178
if (hasUserSuppliedPattern) {
if (results.length === 0 && ArrayPrototypeEvery(glob.matchers, (m) => !m.hasMagic())) {
console.error(`Could not find '${ArrayPrototypeJoin(patterns, ', ')}'`);
process.exit(kGenericUserError);
}

const missing = ArrayPrototypeFilter(patterns, (pattern, i) => {
return !glob.matchers[i].hasMagic() && !existsSync(resolve(cwd, pattern));
});

if (missing.length > 0) {
console.error(`Could not find '${ArrayPrototypeJoin(missing, ', ')}'`);
process.exit(kGenericUserError);
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (hasUserSuppliedPattern) {
if (results.length === 0 && ArrayPrototypeEvery(glob.matchers, (m) => !m.hasMagic())) {
console.error(`Could not find '${ArrayPrototypeJoin(patterns, ', ')}'`);
process.exit(kGenericUserError);
}
const missing = ArrayPrototypeFilter(patterns, (pattern, i) => {
return !glob.matchers[i].hasMagic() && !existsSync(resolve(cwd, pattern));
});
if (missing.length > 0) {
console.error(`Could not find '${ArrayPrototypeJoin(missing, ', ')}'`);
process.exit(kGenericUserError);
}
if (hasUserSuppliedPattern && results.length === 0) {
console.error(`Could not find '${ArrayPrototypeJoin(patterns, ', ')}'`);
process.exit(kGenericUserError);
}

Wouldn't this suffice?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately not — that check only fires when all patterns collectively match nothing, which is the pre-existing behavior (minus the hasMagic() guard). In the repro from #64109, spec/*.test.js does match files, so results.length > 0 and no-tests-here is still silently dropped. The per-pattern check is what catches a nonexistent literal path even when other patterns match.

I also deliberately kept the hasMagic() guard on both checks so a glob that matches zero files keeps its current no-error behavior — removing it would newly fail runs that pass optional globs. Happy to make globs error too if that's preferred, but it seemed like a separate (and riskier) behavior change.

@UditDewan UditDewan requested a review from avivkeller July 7, 2026 20:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-ci PRs that need a full CI run. test_runner Issues and PRs related to the test runner subsystem.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

test_runner: node --test silently drops options or args in certain cases

3 participants