npm run test --workspaces --if-present runs every workspace, but gives you no
aggregated summary and no way to fail fast, no way to catch an early failure that scrolled off screen.
Sumlyzer gives you all those possibilities and even more like concurrency or JUnit reports.
- Node.js >= 22.0.0
- An npm workspaces project (
package.jsonwith aworkspacesfield)
This tool is intentionally narrow: npm workspaces running node:test.
It orchestrates npm run <script> --workspace=<path> for every workspace that
declares the target script, and it parses node test's own output to build
the global and per workspace summary.
It does not support pnpm/yarn workspaces or other test runners (Jest, Vitest, Mocha etc.). (for the moment)
sumlyzer forces its own node:test reporter onto every workspace via
NODE_OPTIONS, so a workspace's test script should just run node --test
without configuring its own --test-reporter.
sumlyzer detects this ahead of time and skips that workspace instead of running into it.
npm install --save-dev sumlyzer
npx sumlyzer [options]
Run from the root of an npm workspaces project (where package.json has a
workspaces field).
Options:
| Flag | Default | Description |
|---|---|---|
--script <name> |
test |
npm script to run per workspace |
--ff |
off | fail fast: stop at the first failing workspace |
--junit <path> |
off | write an aggregated JUnit XML report to <path> |
-c, --concurrency <n> |
1 |
run up to <n> workspaces at once |
-h, --help |
print usage |
Exit code is 1 if any workspace fails (even if every workspace's tests passed), 0 otherwise, wire it straight into CI without extra parsing.
This also applies when --junit can't write its report.
- Aggregated pass/fail summary table.
- Fail-fast (
--ff): stop at the first failing workspace - Aggregated JUnit XML report (
--junit), merging every workspace's own results - GitHub Actions log folding: each workspace's output collapsed into an expandable group, automatically, no flag needed
- Concurrent runs (
--concurrency <n>): run several workspaces' test scripts at once instead of one by one
- Watch mode: walking the workspace dependency graph (topological sort) so a change in one workspace also re-runs the workspaces that depend on it.
| Column | Meaning |
|---|---|
(index) |
Workspace name |
status |
PASS, FAIL, or SKIPPED (reached when --ff stopped scheduling before this workspace ran) |
duration |
Wall-clock time for the whole npm run <script> --workspace=<path> process, including npm/spawn overhead |
testsDuration |
duration_ms as reported by node's own test runner |
tests |
Total number of tests node:test ran in that workspace |
pass |
Number of passing tests |
fail |
Number of failing tests |
skip |
Tests reported as skipped (ℹ skipped), e.g. t.skip() or { skip: true } |
todo |
Tests reported as todo (ℹ todo), e.g. t.todo() |
cancelled |
Tests reported as cancelled (ℹ cancelled), unlike skip/todo this usually signals a real problem |
--junit <path> writes a single aggregated JUnit XML report to <path>, merging
every workspace's own node:test results. Each workspace runs with node:test's
built-in junit reporter enabled alongside the terminal one, and sumlyzer combines
the resulting files into one document, prefixing every <testsuite> name with the
workspace it came from so CI test-report UIs (GitLab, Jenkins, Azure DevOps, ...)
can tell them apart.
npx sumlyzer --junit reports/junit.xml
npx sumlyzer --junit reports/ # writes reports/junit.xml
<testsuites>
<testsuite name="contact › contact tests">...</testsuite>
<testsuite name="scanner">...</testsuite>
</testsuites>A workspace whose script never produces a junit file is left out of the aggregated report and sumlyzer prints a warning naming it.
On GitHub Actions (detected via GITHUB_ACTIONS=true), each workspace's full
node:test output is wrapped in a collapsible ::group::/::endgroup::
section instead of the terminal's formal.
This is automatic, no flag needed, and keeps the job log short by default while still letting you expand any workspace, passing or failing, to see its full suite output.
No other CI provider is currently supported: GitHub is the only one whose log folding sumlyzer has actually verified end-to-end.
--concurrency <n> runs up to <n> workspaces' scripts at the same time
instead of one after another, which can noticeably cut wall-clock time on
projects with many workspaces.
Since workspaces can now finish in any order, their output interleaves in
whatever order they complete, rather than following the workspaces list
order.
With --ff, a failure only stops workspaces that haven't started yet; any
workspace already running when the failure is detected runs to completion
(sumlyzer doesn't kill in-flight processes).
This fail-fast behavior at the --workspaces level has been requested from
npm more than once: npm/rfcs#575
(open) and npm/rfcs#602 (closed).
Until it lands, sumlyzer's --ff flag gets you there, see also this
Stack Overflow answer
on the same problem.
See CONTRIBUTING.md for setup, conventions, and how to submit changes.
MIT


