Skip to content

feat(reporters)!: write json and junit reporter output files to .vitest by default#10621

Merged
hi-ogawa merged 20 commits into
vitest-dev:mainfrom
hi-ogawa:fix/issue-10619
Jun 25, 2026
Merged

feat(reporters)!: write json and junit reporter output files to .vitest by default#10621
hi-ogawa merged 20 commits into
vitest-dev:mainfrom
hi-ogawa:fix/issue-10619

Conversation

@hi-ogawa

@hi-ogawa hi-ogawa commented Jun 19, 2026

Copy link
Copy Markdown
Collaborator

Description

Please don't delete this checklist! Before submitting the PR, please make sure you do the following:

  • It's really useful if your PR references an issue where it is discussed ahead of time. If the feature is substantial or introduces breaking changes without a discussion, PR might be closed.
  • Ideally, include a test that fails without this PR but passes with it.
  • Please, don't make changes to pnpm-lock.yaml unless you introduce a new test example.
  • Please check Allow edits by maintainers to make review process faster. Note that this option is not available for repositories that are owned by Github organizations.

Tests

  • Run the tests with pnpm test:ci.

Documentation

  • If you introduce new functionality, document it. You can run documentation with pnpm run docs command.

Changesets

  • Changes in changelog are generated from PR name. Please, make sure that it explains your changes in an understandable manner. Please, prefix changeset messages with feat:, fix:, perf:, docs:, or chore:.

The `json` and `junit` reporters now write to `.vitest/json/output.json`
and `.vitest/junit/output.xml` when no `outputFile` is configured, instead
of printing to stdout. This aligns them with the `.vitest/` artifact
convention and the `blob` reporter, and produces an on-disk artifact by
default. Explicit `outputFile` is unchanged.

BREAKING CHANGE: json/junit reporters no longer print to stdout by default.
Read the generated artifact file instead (e.g. `jq . .vitest/json/output.json`).

Closes vitest-dev#10619

AI-Agent: Opencode
@netlify

netlify Bot commented Jun 19, 2026

Copy link
Copy Markdown

Deploy Preview for vitest-dev ready!

Built without sensitive environment variables

Name Link
🔨 Latest commit 53c69c4
🔍 Latest deploy log https://app.netlify.com/projects/vitest-dev/deploys/6a3cc9861c72ea0008ac2d0f
😎 Deploy Preview https://deploy-preview-10621--vitest-dev.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

hi-ogawa added 5 commits June 19, 2026 17:03
Add a migration guide section documenting that the json and junit
reporters now write to `.vitest/json/output.json` and
`.vitest/junit/output.xml` by default instead of printing to stdout.
Also revert the outputFile config doc, which is handled separately.

AI-Agent: Opencode
The html reporter location change is handled separately; keep its
existing outputFile behavior and scope the .vitest defaults to the
json and junit reporters only.

AI-Agent: Opencode
Comment thread docs/guide/migration.md Outdated

### Generated Reports and Artifacts Use the `.vitest` Directory

Vitest now uses a single `.vitest` directory at the project root as the shared artifact root. The `json` and `junit` reporters now write to this directory by default instead of printing to stdout:

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.

What is wrong with printing to stdout? Why do we remove this completely?

@hi-ogawa hi-ogawa Jun 19, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

For the use case I understand, they look effectively useless and misguided. See #10619

In practice, "print to stdout" pushes users into awkward workarounds to get the file they actually wanted. Common patterns in the wild:

  • Redirect to a file, then upload as a CI artifact: vitest run --reporter=json > vitest-report.json then upload it (e.g. mizchi/flaker .github/workflows/ci.yml, which redirects → uploads → re-imports the report in a later job).
  • Pipe into a post-processor: vitest --reporter=json | jq '.numFailedTests'.
  • Redirect a bench/report run: vitest bench --run --reporter=json > benchmark-results.json (e.g. thibmeu/act-ts).

A scoped .vitest/ default serves all of these better, with zero config:

  • Artifact upload: just run vitest --reporter=json and upload .vitest/json/output.json — no redirect.
  • Post-analysis: jq '.numFailedTests' .vitest/json/output.json — and it's re-runnable without re-running the tests, since the artifact persists.

So the stdout default isn't a feature these workflows rely on; it's the limitation they work around. Moving to .vitest/ removes the workaround.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Did we discuss maybe supporting outputFile: "-" to mean stdout?

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.

So the stdout default isn't a feature these workflows rely on; it's the limitation they work around. Moving to .vitest/ removes the workaround.

This seems weird - if it's so much better to keep a file, why don't they use --outputFile and read from it? Just because it's not a default?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

So the stdout default isn't a feature these workflows rely on; it's the limitation they work around. Moving to .vitest/ removes the workaround.

This seems weird - if it's so much better to keep a file, why don't they use --outputFile and read from it? Just because it's not a default?

This is just my educated guess and basically my biased opinion.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Also I prefer the file because direct stdout writing such as process.stdout.write can break stdout redirection approach (or console.log in main process like global setup).

hi-ogawa added 2 commits June 19, 2026 18:58
These suites asserted on stdout, which no longer carries the junit
report now that it is written to .vitest/junit/output.xml by default.

AI-Agent: Opencode
The default-mode json/junit reporter tests asserted on the captured
logger output, which now only contains the "report written" log line.
Teach the mock getContext() to provide createReport() backed by a temp
directory and read the generated artifact instead.

AI-Agent: Opencode
Comment thread test/e2e/test/rollup-error.test.ts
hi-ogawa added 4 commits June 19, 2026 19:07
# Conflicts:
#	docs/guide/migration.md
#	docs/guide/reporters.md
The rollup-error e2e suite only needed a sink to grep the surfaced
resolve errors; the default reporter prints them to stderr, so drop
the junit reporter dependency (and the .vitest report file read) and
assert the unescaped error text directly.

AI-Agent: Opencode
@hi-ogawa
hi-ogawa marked this pull request as ready for review June 20, 2026 08:09
AriPerkkio
AriPerkkio previously approved these changes Jun 23, 2026

@AriPerkkio AriPerkkio left a comment

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.

Looks good to me. I don't think stdout as JSON or Junit output ever made sense. The output could have contained Node's and Vitest's deprecation warnings, so parsing the XML/JSON from there would be difficult.

Comment thread docs/guide/reporters.md Outdated
- `junit` writes `.vitest/junit/output.xml`
- `html` writes `.vitest/index.html`

The `json` and `junit` locations can be overridden with the `outputFile` [configuration option](/config/outputfile) either in your Vite configuration file or via CLI; the `html` reporter uses its [`outputDir`](#html-reporter) option instead.

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.

Do we mention outputFile reporter option anywhere?

export interface JUnitOptions {
outputFile?: string

I would rather start pointing users to configure this via reporter options and remove whole top level outputFile in future.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

It looks like there was never a mention of ['json', { outputFile: ... }] nor junit. Will add some in the doc.

I agree that curent ouptutFile option system are rather scattered, but not sure we can drop whole top level one. Before dropping it, probably we need reporter option from cli like --reporter.json.outputFile=... somehow.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

tweaked docs and created cli reporter option request #10650

Comment on lines +268 to +273
this.baseLog = async (text: string) => {
if (!this.fileFd) {
this.fileFd = await fs.open(this.reportFile!, 'w+')
}
}
else {
this.baseLog = async (text: string) => this.ctx.logger.log(text)

await fs.writeFile(this.fileFd, `${text}\n`)

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.

Out-of-scope of this PR, but probably good refactoring for future:
I'm not exactly sure why this reporter was built to stream its results into the output file, while everything is still handled in onTestFinished. Maybe to avoid OOMs? Anyway, we could move this whole fileId initialization in onTestFinished and keep it in function scope there.

@sheremet-va

Copy link
Copy Markdown
Member

I don't think stdout as JSON or Junit output ever made sense

warnings are in stderr though. jest actually forwards every log to stderr so that json reporter is parsable

@hi-ogawa

Copy link
Copy Markdown
Collaborator Author

I don't think stdout as JSON or Junit output ever made sense

warnings are in stderr though. jest actually forwards every log to stderr so that json reporter is parsable

How comprehensive is this though? Does any user code on main process stdout gets collected and redirected to stderr like global setup?

@AriPerkkio

Copy link
Copy Markdown
Member

Does any user code on main process stdout gets collected and redirected to stderr like global setup?

No, not even from test runner workers. If you have process.stdout.write('\n\n\n\nHello world\n\n\n\n') in a test file, the final JSON will be broken:

image

@sheremet-va

Copy link
Copy Markdown
Member

This argument feels weird to me thought. I am not against changing the default, but I am unsure why we need to take away the stdout output. It feels like a natural programmatic way to use it in a terminal - just because user can manually break it doesn’t mean it’s vitest fault. We allow custom reporters even though they can throw an error.

@sheremet-va

Copy link
Copy Markdown
Member

I would keep it as —stdout flag or something. Maybe —reporter.json.stdout like Ari wanted for other reporter options

@AriPerkkio AriPerkkio left a comment

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.

If reading JSON and XML from terminal output is expected use case, let's keep it. I cannot see when it would be useful though.

@hi-ogawa

Copy link
Copy Markdown
Collaborator Author

I also suggested this thing outputFile: "-" to mean stdout #10621 (comment). This feels too stretched overload, so will go with new stdout option then.

Allow opting back into printing the json/junit report to the terminal
via a per-reporter `stdout` option, now that the default writes to a
file under `.vitest/`. Ignored when `outputFile` is set.

Co-authored-by: OpenCode (claude-opus-4-8) <[email protected]>
Comment thread test/e2e/test/rollup-error.test.ts Outdated
Comment thread test/e2e/test/reporters/utils.ts Outdated
Comment thread test/e2e/test/reporters/json.test.ts
hi-ogawa and others added 3 commits June 24, 2026 09:32
Revert the createReport temp-dir plumbing in getContext() now that the
json/junit reporters support a `stdout` option, and drop the redundant
explicit default reporter in rollup-error e2e tests.

Co-authored-by: OpenCode (claude-opus-4-8) <[email protected]>
sheremet-va
sheremet-va previously approved these changes Jun 24, 2026
@hi-ogawa
hi-ogawa requested a review from AriPerkkio June 24, 2026 08:14
AriPerkkio
AriPerkkio previously approved these changes Jun 25, 2026
Comment thread docs/guide/reporters.md Outdated
@hi-ogawa
hi-ogawa dismissed stale reviews from AriPerkkio and sheremet-va via 53c69c4 June 25, 2026 06:24
@hi-ogawa
hi-ogawa merged commit 5857729 into vitest-dev:main Jun 25, 2026
17 of 18 checks passed
@hi-ogawa
hi-ogawa deleted the fix/issue-10619 branch June 25, 2026 06:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Make json and junit reporters default output use .vitest as the report artifact root

3 participants