DevOps 4 min read

Run API Tests in Azure DevOps with Newman

Step-by-step guide to running Postman API test collections in Azure DevOps pipelines using Newman. Covers collection export, environment variables, YAML.

I
InnovateBits
InnovateBits

Postman is the most widely used API testing tool, and Newman is its command-line runner. Together, they integrate cleanly into Azure DevOps pipelines — allowing your Postman test collections to run automatically on every commit.


The Newman + Azure DevOps stack

Postman → Export collection + environment → Git repo
                ↓
Azure Pipelines → Newman runs collection → JUnit XML output
                ↓
PublishTestResults → Azure Test Plans

Step 1: Export your Postman collection

In Postman:

  1. Right-click your collection → Export
  2. Format: Collection v2.1
  3. Save as tests/api/postman-collection.json

Export environment:

  1. Click the environment → Export
  2. Save as tests/api/environments/staging.json

Commit both files to your repository. Never commit environments containing production credentials — use Azure DevOps variable substitution for sensitive values.


Step 2: Prepare the environment file for CI

The exported environment has hardcoded values. Replace secrets with placeholders:

JSON
1{ 2 "name": "staging", 3 "values": [ 4 { "key": "BASE_URL", "value": "{{BASE_URL}}", "enabled": true }, 5 { "key": "API_KEY", "value": "{{API_KEY}}", "enabled": true }, 6 { "key": "TEST_EMAIL", "value": "{{TEST_EMAIL}}", "enabled": true } 7 ] 8}

Newman can override these with --env-var KEY=VALUE flags — values come from Azure DevOps pipeline variables.


Step 3: Pipeline YAML

YAML
1trigger: 2 branches: 3 include: [main] 4 5pool: 6 vmImage: ubuntu-latest 7 8variables: 9 - group: api-test-secrets 10 11steps: 12 - task: NodeTool@0 13 displayName: Setup Node.js 14 inputs: 15 versionSpec: '20.x' 16 17 - script: npm install -g newman newman-reporter-htmlextra 18 displayName: Install Newman 19 20 - script: mkdir -p test-results 21 displayName: Create results directory 22 23 - script: | 24 newman run tests/api/postman-collection.json \ 25 --environment tests/api/environments/staging.json \ 26 --env-var "BASE_URL=$(STAGING_URL)" \ 27 --env-var "API_KEY=$(API_KEY)" \ 28 --env-var "TEST_EMAIL=$(TEST_EMAIL)" \ 29 --reporters cli,junit,htmlextra \ 30 --reporter-junit-export test-results/newman-results.xml \ 31 --reporter-htmlextra-export test-results/newman-report.html \ 32 --reporter-htmlextra-title "API Test Report — $(Build.BuildNumber)" \ 33 --bail 34 displayName: Run Postman/Newman tests 35 env: 36 STAGING_URL: $(STAGING_URL) 37 API_KEY: $(API_KEY) 38 TEST_EMAIL: $(TEST_EMAIL) 39 40 - task: PublishTestResults@2 41 displayName: Publish test results 42 inputs: 43 testResultsFormat: JUnit 44 testResultsFiles: test-results/newman-results.xml 45 testRunTitle: API Tests (Newman) — $(Build.BuildNumber) 46 mergeTestResults: true 47 condition: always() 48 49 - task: PublishPipelineArtifact@1 50 displayName: Upload HTML report 51 inputs: 52 targetPath: test-results/newman-report.html 53 artifact: api-test-report 54 condition: always()

Newman flags explained

FlagPurpose
--bailStop after first failure (remove for full run)
--iteration-count NRun collection N times
--delay-request msAdd delay between requests (rate limiting)
--timeout-request msRequest timeout
--insecureIgnore SSL cert errors (staging only)
--verboseDetailed request/response logging
--env-var KEY=VALUEOverride environment variable

Writing effective Postman tests

In Postman, add tests in the Tests tab of each request:

JAVASCRIPT
1// Status code assertion 2pm.test("Status code is 200", function () { 3 pm.response.to.have.status(200); 4}); 5 6// Response time 7pm.test("Response time under 500ms", function () { 8 pm.expect(pm.response.responseTime).to.be.below(500); 9}); 10 11// Body structure 12pm.test("Response has required fields", function () { 13 const body = pm.response.json(); 14 pm.expect(body).to.have.property('id'); 15 pm.expect(body).to.have.property('status'); 16 pm.expect(body.status).to.equal('active'); 17}); 18 19// Save response value for next request 20pm.test("Extract and save order ID", function () { 21 const body = pm.response.json(); 22 pm.collectionVariables.set("ORDER_ID", body.id); 23});

The saved ORDER_ID is then available in subsequent requests as {{ORDER_ID}}.


Running different collections per environment

YAML
1# Run smoke collection on every PR, full regression nightly 2stages: 3 - stage: SmokeAPI 4 displayName: API Smoke Tests 5 jobs: 6 - job: Smoke 7 steps: 8 - script: | 9 newman run collections/smoke.json \ 10 --env-var "BASE_URL=$(STAGING_URL)" 11 displayName: Smoke API tests 12 13 - stage: RegressionAPI 14 displayName: API Regression 15 condition: eq(variables['Build.Reason'], 'Schedule') 16 jobs: 17 - job: Regression 18 steps: 19 - script: | 20 newman run collections/regression.json \ 21 --env-var "BASE_URL=$(STAGING_URL)" \ 22 --iteration-count 1 23 displayName: Full API regression

Common errors and fixes

Error: newman: command not found in pipeline Fix: The install step (npm install -g newman) must precede the newman run. Check the step order and that Node.js is installed first.

Error: Error: ENOENT: no such file or directory, open 'test-results/newman-results.xml' Fix: Newman only creates the output file if the directory exists. Add mkdir -p test-results before the newman command.

Error: Newman exits with code 1 but PublishTestResults still doesn't run Fix: Add condition: always() to the PublishTestResults task. Without it, the task skips when the previous step fails.

Error: Environment variables show as {{VARIABLE_NAME}} in requests Fix: Check that --env-var "KEY=VALUE" format is correct (no spaces around =). Also verify the variable name in Postman matches exactly (case-sensitive).

Error: newman-reporter-htmlextra: reporter not found Fix: Install both newman and newman-reporter-htmlextra separately: npm install -g newman newman-reporter-htmlextra. They are separate packages.

Tags
#postman#newman#api-testing#azure-devops#azure-pipelines#api-automation

Share this article

Follow for more

Follow me on social media for more developer tips, tricks, and tutorials. Let's connect and build something great together!