Published
- 7 min read
Postman API Contract and Regression tests session
This Postman Collection is private. Some details in this post are also anonymised.
Various Postman API Contract and Regression tests
Description
In this activity, I explore Megaport’s Location endpoint and add some basic API tests using Postman collection.
Write a Postman collection to test the endpoint with the provided information. Include any assumptions made during test script creation.
Used Postman Functions
Below list various postman functions used in this collection.
Test Function | Description |
---|---|
pm.test() | Executes a test script and checks if the specified condition is true. |
pm.expect() | Asserts a value against an expected value using various comparison operators. |
pm.response() | Provides access to the response data and allows extracting specific values for further testing. |
pm.environment() | Provides access to the Postman environment variables for setting and getting values. |
pm.globals() | Provides access to the global variables for setting and getting values. |
Prerequisites
Before using this collection, make sure you have the following:
- Postman installed.
- Megaport API client credentials (client ID and client secret).
How to Use
- Open Postman
- Import provided collection
- Replace client ID and client secret with your actual in the collection’s pre-request script
- Run the collection to see results
Variables
This collection uses the following variables.
Name | Type | Description | Value |
---|---|---|---|
baseURL | Global | Production URL | https://api.megaport.com |
accessToken | Global | Access Token for Endpoints | Auto-generated by pre-request script |
status | Collection | Location Status | Active |
metro | Collection | Metro Area | Brisbane |
marketEnabled | Collection | MarketEnabled (Bool) | False |
mveVendor | Collection | Vendor Name | VMware |
Pre-request Access Token Script
The pre-request script is to automate the process of obtaining an access token from the Megaport authentication server using the client credentials grant
- The script sends a POST request to Megaport’s token endpoint using client credentials.
- It sets the necessary headers and request body parameters.
- The response is logged to the console, and if successful, the access token is saved as a variable in the Postman environment.
pre-request accessToken script..
// Set your credentials
var clientId = 'xxxxxxxxxxxxxxxxxxxxxxxxx'
var clientSecret = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
// Set the URL and request parameters
var url = 'https://xxx-xxx.megaport.com/oauth2/token'
var headers = {
'Content-Type': 'application/x-www-form-urlencoded',
Authorization: 'Basic ' + btoa(clientId + ':' + clientSecret)
}
// Set the request body
var body = {
mode: 'urlencoded',
urlencoded: [{ key: 'grant_type', value: 'client_credentials' }]
}
// Send the POST request
pm.sendRequest(
{
url: url,
method: 'POST',
header: headers,
body: body,
secure: true
},
function (err, res) {
// Handle the error
if (err) {
console.error('Error:', err)
return
}
// Handle the response
console.log(res)
// Extract and save accessToken as a variable
var jsonResponse = res.json()
if (jsonResponse && jsonResponse.access_token) {
pm.environment.set('accessToken', jsonResponse.access_token)
console.log('Access Token saved:', pm.environment.get('accessToken'))
}
}
)
Test Types
This collection demonstrates Contract and Regression Test Types examples. The table below describes various differences.
Aspect | Contract API Testing | Regression Testing |
---|---|---|
Focus | Contracts and agreements between services or APIs | Overall application functionality and features |
Purpose | Ensure adherence to communication contracts | Identify and prevent regression (new defects) |
Scope | Limited to interactions between specific services | Broader, covering the entire application or modules |
Timing | Often during the development of individual services | Typically after code changes, part of release cycle |
Coverage | Specific contracts, request/response formats | Comprehensive, various test cases for diverse features |
Application Stage | During service/component development | After code changes, part of the software release cycle |
Primary Concern | Communication protocols, data structures | Stability and integrity of existing functionality |
Regression Tests
Each request should contain tests that:
- Assert that the response status code is 200 OK
- Assert that the content type is application/json
- Assert that the response body
Data
is not empty - Assert that the response time is less than 5 seconds
Postman general regression test..
//Regression Tests
pm.test('Verify Response status code is 200', function () {
pm.expect(pm.response.code).to.equal(200)
})
pm.test('Verify Response Content-Type is application/json', function () {
pm.expect(pm.response.headers.get('Content-Type')).to.include('application/json')
})
pm.test('Verify response time is less than 5 seconds', function () {
const fiveSecondsMs = 5_000 // 5 seconds in milliseconds
pm.expect(pm.response.responseTime).to.be.below(fiveSecondsMs)
})
pm.test('Verify Data array is present and contains at least one element', function () {
const responseData = pm.response.json()
pm.expect(responseData).to.have.property('data').that.is.an('array').and.not.empty
})
Contract Tests
Metro: Verifies filtering by metro location
- Send a GET request to the endpoint:
https://api.megaport.com/v2/locations?metro=Brisbane
- Set the following headers:
- Content-Type: application/json
- Set the following parameters:
- metro: Brisbane
- Assert that the response body contains the expected metro information
- Assert each location includes latitude and longitude details
Metro Filter Postman tests..
//Contract Tests
pm.test('Verify Metro fields are non-empty strings', function () {
const responseData = pm.response.json().data
responseData.forEach(function (location) {
pm.expect(location.metro)
.to.be.a('string')
.and.to.have.lengthOf.at.least(1, 'Metro should not be empty')
})
})
pm.test('Verify each location includes latitude and longitude details', function () {
pm.response.json().data.forEach(function (location) {
pm.expect(location).to.have.property('latitude').that.is.a('number')
pm.expect(location).to.have.property('longitude').that.is.a('number')
})
})
LocationStatus: Verify filtering by location status and metro
- Send a GET request to the endpoint:
https://api.megaport.com/v2/locations?locationStatus=Active&metro=Brisbane
- Set the following headers:
- Content-Type: application/json
- Set the following parameters:
- locationStatus: Active
- metro: Brisbane
- Assert that the response body contains only locations with the specified status
LocationStatus Filter Postman test..
//Contract Tests
pm.test('Verify Status is Active for each location', function () {
const responseData = pm.response.json().data
// const statusOptions = ["Extended", "Deployment", "Active", "New", "Restricted", "Expired"];
const statusOptions = ['Active']
statusOptions.forEach((option) => {
pm.expect(responseData.every((location) => location.status.includes(option))).to.be.true
})
})
MarketEnabled: Verify filtering by marketEnabled
- Send a GET request to the endpoint:
https://api.megaport.com/v2/locations?locationStatus=Active&metro=Brisbane&marketEnabled=true
- Set the following headers:
- Content-Type: application/json
- Set the following parameters:
- locationStatus: Active
- metro: Brisbane
- marketEnabled: true
- Assert that the respomnse body contains only AU markets that are active
MarketEnabled AU Postman test..
//Contract Tests
pm.test('Verify Market is equal to AU for each location', function () {
const responseData = pm.response.json()
responseData.data.forEach(function (location) {
pm.expect(location.market).to.equal('AU')
})
})
mveVendor: Verify filtering by MVE vendor
- Send a GET request to the endpoint:
https://api.megaport.com/v2/locations?metro=London&mveVendor=VMware
- Set the following headers:
- Content-Type: application/json
- Set the following parameters:
- metro: London
- mveVendor: VMware
- Assert that the response body contains only locations with the specified MVE vendor
- Asserts MVE sizes return response
- Assets MVE details return expected properties
MVE Vendor Filter Postman tests..
//Contract Tests
pm.test('Verify MVE Vendor property to equal VMware for each location', function () {
pm.response.json().data.forEach(function (location) {
pm.expect(location.products.mve[0].vendor).to.equal('VMware')
})
})
pm.test(
"Verify each location's MVE sizes array returns available sizes or is empty if unavailable",
function () {
pm.response.json().data.forEach(function (location) {
if (location.products.mve[0].sizes.length > 0) {
pm.expect(location.products.mve[0].sizes).to.not.be.empty
} else {
pm.expect(location.products.mve[0].sizes).to.be.empty
}
})
}
)
pm.test("Verify location's MVE details object returns all available properties", function () {
pm.response.json().data.forEach(function (location) {
location.products.mve[0].details.forEach(function (detail) {
pm.expect(detail).to.have.property('size').that.is.a('string')
pm.expect(detail).to.have.property('label').that.is.a('string')
pm.expect(detail).to.have.property('cpuCoreCount').that.is.a('number')
pm.expect(detail).to.have.property('bandwidthMbps').that.is.a('number')
pm.expect(detail).to.have.property('ramGB').that.is.a('number')
})
})
})
VerifyLocationsJsonSchema: Verify Locations Endpoint Schema
- Send a GET request to the endpoint:
https://api.megaport.com/v2/locations?metro=Brisbane
- Set the following headers:
- Content-Type: application/json
- Set the following parameters:
- metro: Brisbane
- Assert that the response body matches expected JSON Schema
Locations JSON Schema Postman test..
// Test Megaport Location Response Shape with expected JSON Schema
const expectedSchema = {
type: 'object',
properties: {
message: {
type: 'string',
description: 'List all public locations'
},
terms: {
type: 'string',
description:
'This data is subject to the Acceptable Use Policy https://www.megaport.com/legal/acceptable-use-policy'
},
data: {
type: 'array',
items: {
type: 'object',
properties: {
id: { type: 'integer' },
name: { type: 'string' },
campus: { type: 'string' },
metro: { type: 'string' },
country: { type: 'string' },
siteCode: { type: 'string' },
networkRegion: { type: 'string' },
address: {
type: 'object',
properties: {
street: { type: 'string' },
suburb: { type: 'string' },
city: { type: 'string' },
state: { type: 'string' },
country: { type: 'string' },
postcode: { type: 'string' }
}
},
dc: {
type: 'object',
properties: {
id: { type: 'integer' },
name: { type: 'string' }
}
},
market: { type: 'string' },
vRouterAvailable: { type: 'boolean' },
liveDate: { type: 'integer' },
status: { type: 'string' },
longitude: { type: 'number' },
latitude: { type: 'number' },
products: {
type: 'object',
properties: {
mcr: { type: 'boolean' },
megaport: {
type: 'array',
items: { type: 'integer' }
}
}
},
ordering_message: { type: ['string', 'null'] },
diversityZones: { type: 'object' }
},
required: [
'id',
'name',
'campus',
'metro',
'country',
'siteCode',
'networkRegion',
'address',
'dc',
'market',
'vRouterAvailable',
'liveDate',
'status',
'longitude',
'latitude',
'products',
'ordering_message',
'diversityZones'
]
}
}
},
required: ['message', 'terms', 'data']
}
// Test that the response matches the expected schema using built-in schema verification
pm.test('Verify Locations response matches expected JSON schema', () => {
pm.response.to.have.jsonSchema(expectedSchema)
})
VerifyLocationsContract: Verify Locations Contract Specifications
- Send a GET request to the endpoint:
https://api.megaport.com/v2/locations?metro=Brisbane
- Set the following headers:
- Content-Type: application/json
- Set the following parameters:
- metro: Brisbane
- Asserts various Locations Endpoint specifications
- Location properties
- Address sub properties
- DC sub properties
- Property types
Locations Contract Postman tests..
//Locations Contract Test Collection
pm.test('Verify expected properties are in Locations endpoint', function () {
const data = pm.response.json()
// Check the expected properties exist
pm.expect(data.data[0]).to.have.property('id')
pm.expect(data.data[0]).to.have.property('name')
pm.expect(data.data[0]).to.have.property('campus')
pm.expect(data.data[0]).to.have.property('metro')
pm.expect(data.data[0]).to.have.property('country')
pm.expect(data.data[0]).to.have.property('siteCode')
pm.expect(data.data[0]).to.have.property('networkRegion')
pm.expect(data.data[0]).to.have.property('address')
pm.expect(data.data[0]).to.have.property('dc')
pm.expect(data.data[0]).to.have.property('market')
pm.expect(data.data[0]).to.have.property('vRouterAvailable')
pm.expect(data.data[0]).to.have.property('liveDate')
pm.expect(data.data[0]).to.have.property('status')
pm.expect(data.data[0]).to.have.property('longitude')
pm.expect(data.data[0]).to.have.property('latitude')
pm.expect(data.data[0]).to.have.property('products')
pm.expect(data.data[0]).to.have.property('ordering_message')
pm.expect(data.data[0]).to.have.property('diversityZones')
})
pm.test('Verify Address sub-properties are in Locations endpoint', function () {
const data = pm.response.json()
// Check Address properties exist
pm.expect(data.data[0].address).to.have.property('street')
pm.expect(data.data[0].address).to.have.property('suburb')
pm.expect(data.data[0].address).to.have.property('city')
pm.expect(data.data[0].address).to.have.property('state')
pm.expect(data.data[0].address).to.have.property('country')
pm.expect(data.data[0].address).to.have.property('postcode')
})
pm.test('Verify DC sub-properties are in Locations endpoint', function () {
const data = pm.response.json()
// Check DC properties exist
pm.expect(data.data[0].dc).to.have.property('id')
pm.expect(data.data[0].dc).to.have.property('name')
})
pm.test('Verify value types in Locations endpoint', function () {
const data = pm.response.json()
// Check the values have the expected types
pm.expect(data.data[0].id).to.be.a('number')
pm.expect(data.data[0].name).to.be.a('string')
pm.expect(data.data[0].campus).to.be.a('string')
pm.expect(data.data[0].metro).to.be.a('string')
pm.expect(data.data[0].country).to.be.a('string')
pm.expect(data.data[0].siteCode).to.be.a('string')
pm.expect(data.data[0].networkRegion).to.be.a('string')
pm.expect(data.data[0].address).to.be.an('object')
pm.expect(data.data[0].dc).to.be.an('object')
pm.expect(data.data[0].market).to.be.a('string')
pm.expect(data.data[0].vRouterAvailable).to.be.a('boolean')
pm.expect(data.data[0].liveDate).to.be.a('number')
pm.expect(data.data[0].status).to.be.a('string')
pm.expect(data.data[0].longitude).to.be.a('number')
pm.expect(data.data[0].latitude).to.be.a('number')
pm.expect(data.data[0].products).to.be.an('object')
pm.expect(data.data[0].ordering_message).to.be.null
pm.expect(data.data[0].diversityZones).to.be.an('object')
})
Notes
- Ensure that your Megaport API client credentials are correctly set in the script.
- This collection is intended for educational purposes and may need adjustments based on specific requirements.