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.
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:
- Right-click your collection → Export
- Format: Collection v2.1
- Save as
tests/api/postman-collection.json
Export environment:
- Click the environment → Export
- 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:
JSON1{ 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
YAML1trigger: 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
| Flag | Purpose |
|---|---|
--bail | Stop after first failure (remove for full run) |
--iteration-count N | Run collection N times |
--delay-request ms | Add delay between requests (rate limiting) |
--timeout-request ms | Request timeout |
--insecure | Ignore SSL cert errors (staging only) |
--verbose | Detailed request/response logging |
--env-var KEY=VALUE | Override environment variable |
Writing effective Postman tests
In Postman, add tests in the Tests tab of each request:
JAVASCRIPT1// 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
YAML1# 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.
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!