
Product news and testing tips.
Newman ships five built-in reporters — cli, json, junit, progress and emojitrain — and maps each request to a JUnit `<testsuite>` and each `pm.test()` assertion to a `<testcase>`. The built-in JUnit reporter has no handling for skipped assertions, so a request whose assertions were all skipped can report as passing. Newman still ships, but cannot run the v3 collection format used by Postman v12 and later.
Key takeaways
- Newman's built-in reporters are cli, json, junit, progress and emojitrain — selected with -r.
- Specifying any reporter suppresses CLI output unless you also list `cli` explicitly.
- In JUnit output a request becomes a <testsuite> and each pm.test() assertion becomes a <testcase>.
- The built-in JUnit reporter emits no <skipped> elements — pm.test.skip assertions are counted as pending in stats only.
- Newman cannot run the v3 collection format introduced in Postman v12; Postman points CI users to the Postman CLI.
API tests occupy an awkward position in most CI pipelines. They are usually the fastest meaningful integration signal a team has, and they are usually the least well reported — a wall of green console text that nobody reads, followed by a red build that requires scrolling to understand.
Newman, Postman’s collection runner, does emit structured results. Getting useful ones requires understanding how it maps API concepts onto test-report concepts, because the mapping is not obvious and one part of it is quietly lossy.
How Newman reports results
Newman ships five built-in reporters, selected with -r or --reporters:
| Reporter | Output |
|---|---|
cli | Human-readable console output (the default) |
json | Full run summary as JSON |
junit | JUnit XML |
progress | A progress bar |
emojitrain | Emoji per assertion, exactly as it sounds |
They combine, comma-separated:
newman run collection.json -r cli,junit,json
One thing to get right immediately: specifying any reporter replaces the default, so -r junit alone gives you an XML file and a silent terminal. In CI that usually means a failing build with no visible reason. Include cli explicitly whenever you want console output alongside a machine-readable file.
Request or assertion: what counts as a test?
This is the mental model that makes everything else make sense, and it is worth being precise about because “Newman ran 40 tests” can mean two different things.
A Postman collection contains requests. Each request can have a script attached containing any number of assertions, written as pm.test() blocks:
pm.test("status is 200", function () {
pm.response.to.have.status(200);
});
pm.test("returns a cart id", function () {
pm.expect(pm.response.json()).to.have.property("cartId");
});
The built-in JUnit reporter maps these two levels onto JUnit XML’s two levels:
- A request becomes a
<testsuite>, named after the request, with itstestscount set to the number of assertions it contained. - Each assertion becomes a
<testcase>, named after the assertion string you passed topm.test(). - A failed assertion produces a
<failure>withtype="AssertionFailure".
So the request above appears as one suite containing two test cases named “status is 200” and “returns a cart id”. This is a sensible mapping, and it has a direct consequence for how you write collections: the string you pass to pm.test() becomes the test name in every downstream report. Naming assertions “test 1” and “test 2” produces exactly the report you would expect.
Getting JUnit XML
newman run collection.json \
-e environment.json \
-r cli,junit \
--reporter-junit-export results.xml
--reporter-junit-export sets the output path. Omit it and the file is written as newman-run-report.xml in the working directory.
The result is ordinary JUnit XML, and it inherits all of that format’s well-documented ambiguity — including having no way to express a retry, which matters for API tests more than most, since a flaky API test is very often a genuinely intermittent upstream rather than a bad test.
The skipped-assertion gap
Postman supports skipping an assertion at runtime:
pm.test.skip("requires sandbox credentials", function () {
// not executed
});
The run statistics count these as pending. The built-in JUnit reporter does not emit <skipped> elements at all — there is no code path in it that produces one.
The practical effect is worth stating plainly: a request whose assertions were every one skipped produces a suite with no failures. Depending on what reads that file, it can look indistinguishable from a request that passed. If you gate a release on Newman’s JUnit output, a collection that silently skipped its checks — because an environment variable was missing, say, or a conditional guard was inverted — can sail through green.
Two defences are worth building in:
- Assert on the run statistics, not just the exit code. The JSON reporter carries
run.statswith total, failed, and pending counts for assertions; a pending count you did not expect is a signal. - Treat “zero assertions ran” as a failure in whatever consumes the report. A suite with no test cases is not a pass.
The JSON reporter carries more
When you need detail the JUnit format cannot hold, the json reporter dumps Newman’s full run summary. The shape is worth knowing:
| Path | Contents |
|---|---|
run.stats | Totals, failures and pending counts for requests, assertions, scripts |
run.executions | One entry per request, with its associated activity |
run.failures | Failure objects, each with the assertion that failed and the request |
run.timings | Run-level timing data |
run.transfers | Bytes sent and received |
collection, environment, globals | The inputs the run used |
run.executions is the richest of these — it holds the request and response for each execution, which is what you actually want when debugging a failure three days later and the console output is long gone.
Newman or the Postman CLI in 2026?
The tooling situation changed and the guidance online has not entirely caught up, so it is worth being precise.
Newman still ships. Version 6.2.2 was published in January 2026, the repository is actively pushed, and Postman’s own blog has stated there are no plans to deprecate it.
But Newman cannot run v3-format collections. Postman’s current documentation is explicit that Newman is not compatible with the collection v3 format used in Postman v12 and later, and directs CI users to migrate to the Postman CLI.
The Postman CLI is a separate tool — signed and supported by Postman, with native Postman Cloud integration, support for v3 collections, monitors, and performance tests. It is not a drop-in rename of Newman and is not distributed the same way.
A reasonable reading: if your repository holds an exported collection JSON and you run it in CI, Newman works and will continue to. If you are on newer Postman versions, tied into Postman Cloud, or starting fresh, the Postman CLI is the direction the vendor is pointing. Do not let anyone tell you Newman is abandoned — but do check which collection format you are actually on before planning around it.
A CI setup
- name: Run API tests
run: |
npm install -g newman
newman run collection.json \
-e ci-environment.json \
-r cli,junit,json \
--reporter-junit-export results.xml \
--reporter-json-export results.json
- name: Upload results
if: always()
uses: actions/upload-artifact@v4
with:
name: newman-results
path: results.*
Export both formats. The XML is what CI reporters and dashboards read; the JSON is what you will actually want when a failure needs investigating, because it carries the request and response bodies. The if: always() matters for the same reason it always does — without it the upload is skipped exactly when the tests failed. The other documented limits of GitHub Actions reporting apply here as they do to any framework.
What a single API test report cannot tell you
The same ceiling applies here as to Go test reporting or any other framework, and API tests make it sharper.
An API test that failed once is genuinely ambiguous in a way a unit test is not. It might be a bug in the code. It might be a real intermittent fault in a dependency, which is a finding, not noise. It might be a rate limit, a cold start, or a network blip. A single report cannot distinguish these, because all four look identical: one assertion, one failure, one timestamp.
Distinguishing them requires knowing how often that assertion fails, whether it fails against every environment or only staging, and whether the failures cluster in time. Those are all questions about many runs.
For transparency: Qualflare is our product — a test observability layer that ingests Newman results alongside 25 other formats and analyses them across runs for flaky-test scoring and failure clustering. It does not run your collections and it is not a Postman replacement; it reads what Newman writes. If your current problem is that Newman’s console output is unreadable in CI, adding the junit reporter and a reporter action solves that for free, and that is the right first step.
Frequently asked questions
How do I generate a JUnit report from Newman?
Pass the junit reporter and an export path — newman run collection.json -r junit --reporter-junit-export results.xml. If you also want console output you must list the cli reporter explicitly, because specifying any reporter replaces the default — -r cli,junit. Without an export path the file is written as newman-run-report.xml.
Does Newman report each request or each assertion as a test?
Both, at different levels. In the built-in JUnit reporter each request becomes a <testsuite> named after the request, and each pm.test() assertion inside it becomes a <testcase> named after the assertion string. A failing assertion produces a <failure> element with type AssertionFailure. So one request with four assertions appears as one suite containing four test cases.
Why do skipped Postman tests not appear in the JUnit report?
Because the built-in JUnit reporter has no code path that emits <skipped> elements. Assertions skipped with pm.test.skip are counted as pending in the run statistics, but the JUnit XML simply does not represent them. A request whose assertions were all skipped can therefore appear to have passed, which is worth guarding against if you gate releases on that file.
Is Newman still maintained in 2026?
Yes, with a caveat. Newman is still published — version 6.2.2 shipped in January 2026 and the repository is actively pushed. However, Newman is not compatible with the v3 collection format used in Postman v12 and later, and Postman’s current documentation directs CI users to the Postman CLI instead. Postman has stated it has no plans to deprecate Newman.
What is the difference between Newman and the Postman CLI?
Newman is the long-standing open-source collection runner distributed on npm. The Postman CLI is a separate, signed tool built and supported by Postman with native Postman Cloud integration; it runs v3-format collections, which Newman cannot, and supports monitors and performance tests. For a repository holding an exported collection JSON file, Newman still works; for workflows tied to Postman Cloud or newer collection formats, the Postman CLI is the supported route.


