Postman Series - writing assertions and validating responses
Once you can run manual tests for your API endpoints you should start thinking of how to automate them. Automation makes verifying API behaviours straightforward and consistent while saving you much time.
Assertions for your tests are a great way to verify API behaviours. In postman, assertions are a key part of writing automated tests. They do the job of checking if a piece of code returns the expected output.
for example
pm.expect(response).to.equal(learning postman);
});
From the above assertion statement, we are trying to assert that (response) is equal to learning postman
and it is returned as part of your response body.
Postman makes use of the Chai assertion library for creating assertion and BDD syntax to make tests readable and understandable.
The main reason for writing assertions and validating the responses in Postman is to verify that the actual and expected results have matched after the execution of a test. A typical postman assertion returns a Boolean value of either true or false. If the results do not match, the test will fail and we shall get the reason for failure from the output of the test.
Now, let's explore how we can use assertions to validate various aspects of an API response, ensuring its overall health.
Assertions in Postman
In Postman, assertions are checks you write to verify if the responses from your API calls match what you expect. They act like little tests within your larger test scripts.
Here's a breakdown of assertions in Postman:
Verification: Assertions ensure that the actual results returned by the API (like the response body or status code) align with the expected values you define in your tests.
Code-based: Assertions are written in JavaScript using the built-in Chai assertion library. Chai provides a clear and readable syntax for making assertions.
Pass/Fail: Each assertion evaluates to true or false. If the assertion is true (meaning the expected and actual results match), the test passes. If it's false (there's a mismatch), the test fails, indicating an issue with the API response.
Debugging: Failed assertions provide error messages that help pinpoint where the problem lies in the API's response. This aids in debugging and identifying API issues.
Essential Checks for Validating Responses
Status code Validation
Response body Validation
Response Time Validation
JSON schema Validation
Headers Validation
Let's look at how we can use the above in our postman tests
Status code Validation:
Status codes are the foundation for understanding how your API responds to requests. Validating status codes is crucial for ensuring your API behaves as expected. They help identify whether an API call was successful, encountered a client-side error, or resulted in a server-side error.
Importance of Status Code Validation
Identifies Errors: You can quickly identify successful responses (
200 OK
) from errors by checking the status code. Specific error codes404 Not Found or 401 Unauthorized
provide clues about the nature of the problem.Verifies Functionality: Validating different status codes helps verify if your API endpoints handle various scenarios correctly. For instance, you were checking for a
201 Created
status code after aPOST
request confirms successful resource creation.Improves Reliability: By ensuring your API returns the appropriate status codes, you build a more reliable API that applications can interact with predictably.
A typical status code example is:
A successful
GET
requestsend a GET request to retrieve data from an API endpoint
https://jsonplaceholder.typicode.com/posts
pm.test("Status code is 200", function () { pm.response.to.have.status(200); });
Within the test tab input the code above and check your postman test result tab, this assertion indicates that the server successfully processed your request and is returning the requested data in the response body.
However,
pm.test
is the recommended way to create a test case within Postman.pm.response.to
.have.status(200);
also uses the appropriate assertion to check for a status code of 200.
Alternatively, you can usepm.expect(pm.response).to.have.status(200);
Response body Validation:
The response body is where the API returns the actual data you requested or the outcome of your API call in Postman. Validating the response body ensures that the API returns the expected data and structure.
Importance of Response Body Validation:
Data Integrity: This ensures that the API returns the correct response body content, you can verify that the data returned by the API is accurate, complete, and matches your expectations.
Content Verification: Postman assertions allow you to verify the structure of the response body against the expected criteria, ensuring it adheres to a defined format (like JSON). It includes checking for specific data values, verifying the presence of certain fields, or ensuring the absence of undesired information.
Error Messages: writing assertions can help identify errors and unexpected behaviours within the response body. This also helps you debug your APIs better.
A typical response body validation example is:
A successfulGET
request
https://swapi.dev/api/planets/3/
within this request, we will be validating the response body from the API
const jsonData = pm.response.json();
pm.test("Test data type of the response", () => {
pm.expect(jsonData).to.be.an("object");
pm.expect(jsonData.name).to.eql("Yavin IV");
pm.expect(jsonData.rotation_period).to.eql("24");
pm.expect(jsonData.orbital_period).to.eql("4818");
pm.expect(jsonData.diameter).to.eql("10200");
pm.expect(jsonData.climate).to.eql("temperate, tropical");
pm.expect(jsonData.gravity).to.eql("1 standard");
pm.expect(jsonData.terrain).to.eql("jungle, rainforests");
pm.expect(jsonData.surface_water).to.eql("8");
pm.expect(jsonData.population).to.eql("1000");
pm.expect(jsonData.residents).to.eql([]);
pm.expect(jsonData.films).to.be.a("array");
pm.expect(jsonData.created).to.be.a("string");
pm.expect(jsonData.edited).to.be.a("string");
pm.expect(jsonData.url).to.be.a("string");
});
Let's break it down step by step:
const jsonData = pm.response.json();
:This line retrieves the response body from the API call and parses it as JSON data.
The parsed JSON object is then stored in the variable
jsonData
.
pm.test("Test data type of the response", () => { ... });
:
This defines a test case named "Test data type of the response".
The arrow function syntax (
=>
) is used to define the test logic within curly braces{}
.pm.expect
:The test script utilizes multiple assertions using
pm.expect
to verify the structure and content of thejsonData
object:Data types: It checks if specific properties (like
name
,diameter
) are of expected data types (object, string, array).Specific values: It verifies that certain properties (like
name
,rotation_period
) have the expected values ("Yavin IV", "24").Empty array: It confirms that the
residents
property is an empty array ([]
).
Overall, the assertion written above was used to validate the response body that was returned from the API and also verify that they matched what was expected of it.
Response time Validation: Response time is the time in which it takes the API to respond to a call. Validating response is necessary to deliver a good user experience. Also, these allow us to measure the API performance and also identify bottlenecks within the API infrastructure just in case it needs optimization.
A typical response time example is:
Within yourpre-request test tab
, we will write our assertions and also in yourtest tab
.Using this sample
GET
request url https://swapi.dev/api/planets/3/const startTime = new Date().getTime(); function handleResponse(err, response) { const endTime = new Date().getTime(); const responseTime = endTime - startTime; console.log("Response Time:", responseTime, "ms"); pm.test("Response time is less than 400ms", function () { pm.expect(responseTime).to.be.below(400); }); } pm.sendRequest(pm.request, handleResponse);
This validation ensures that the response time of the API request is within acceptable limits (less than 400 milliseconds) and also logs the actual response time within the Postman console as shown in the third image. If the response time exceeds this it logs the exact response threshold, the test will fail.
const startTime = new Date().getTime();
: This line captures the current timestamp in millisecondsnew Date().getTime()
and stores it in thestartTime
variable. This timestamp represents the moment before the request is sent.function handleResponse(err, response) { ... }
: This defines a function namedhandleResponse
that takes two arguments:err
: This will contain any error information if the request fails.response
: This will contain the response object if the request is successful.pm.expect(responseTime).
to.be
.below(400);
: This line uses Chai assertions (pm.expect
) to verify the response time. It checks ifresponseTime
is less than 400 milliseconds (ms).If the response time is indeed below 400ms, the test passes.
If the response time is greater than or equal to 400ms, the test fails, indicating a potentially slow response.
The
handleResponse
function acts as a callback that gets invoked after the response is received from the server. This ensures that the code responsible for processing the response (calculating time, adding assertions) only executes when the actual response is available.
JSON Schema validation:
JSON Schema validation is commonly used in APIs to validate request payloads and response bodies, ensuring that clients send and receive data in the expected format. A JSON Schema is written in JSON format and describes the expected structure of a JSON object.
If the JSON data passes all validation checks, it is considered valid according to the schema. However, if the data fails any validation checkβfor example, if a required property is missing or a property value does not match the expected typeβthe data is considered invalid, and validation errors are reported.
The JSON Schema structure uses keywords like the following:
type: Specifies the data type (string, number, object, array etc.)
properties: Defines the properties expected within an object and their data types.
required: Indicates which properties are mandatory within an object.
additional properties: Allows or disallows additional properties not explicitly defined in the schema.
A typical example of a JSON schema validation is a Successful GET
request with a response body as shown in the Postman suite image below. We will be validating the response body data against the schema written inside this test tab.
https://swapi.dev/api/planets/3/
var schema = {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"data.rotation_period": {
"type": "integer"
},
"data.orbital_period": {
"type": "integer"
},
"diamater": {
"type": "integer"
},
"climate": {
"type": "string"
},
"gravity": {
"type": "string"
},
"terrain": {
"type": "string"
},
"data.surface_water": {
"type": "integer"
},
"data.population": {
"type": "integer"
},
"residents": {
"type": "array"
},
"data.films": {
"type": "string"
},
"created": {
"type": "string"
},
"edited": {
"type": "string"
},
"url": {
"type": "string"
}
},
"required": [
"name",
"rotation_period",
"orbital_period",
"diameter",
"climate",
"gravity",
"terrain",
"surface_water",
"population",
"residents",
"films",
"created",
"edited",
"url"
]
}
pm.test("Validate schema", () => {
pm.response.to.have.jsonSchema(schema);
});
Defining the JSON Schema:
The
var schema
block defines the JSON schema object that specifies the expected structure and data types for the response data.type: "object"
: This indicates that the root level of the data should be an object.properties
: This object defines the expected properties within the response object. Each property name acts as a key, and its value is another object specifying details about the property:Data Type: Keys like
type: "string"
ortype: "integer"
define the expected data type for each property.Nested Properties: Properties like
data.rotation_period
use dot notation to specify nested properties within an object named "data".
required
: This array lists all the mandatory properties that must be present in the response object.The
pm.test("Validate schema", () => { ... });
block defines a Postman test named "Validate schema".Inside the test function:
pm.response.to
.have.jsonSchema(schema);
: This line is the key part for validation. It uses thepm.expect
syntax and theto.have.jsonSchema
assertion from Postman. This assertion checks if the response data (accessed throughpm.response
) conforms to the provided JSON schema (schema
).
Headers Validation:
Headers are essential components of HTTP requests and responses. They carry crucial information about the request, response, and the resources involved. Validating headers in Postman is crucial for ensuring that APIs interact as expected, adhere to communication protocols, maintain security and integrity, and provide the necessary information for proper message handling and interpretation.
Importance of Header Validation:
Verifying Request Headers:
- When a client sends an HTTP request, it includes headers that provide details such as the request method (e.g., GET, POST), content type (e.g., JSON, form data), authentication credentials, and any custom information required by the server. By validating request headers, you can confirm that your requests include necessary headers like authentication tokens or content type information, as mandated by the API.
Validating Response Headers:
- When a server sends back an HTTP response, it includes headers that provide details such as the status code (e.g., 200 OK, 404 Not Found), content type, caching directives, and any additional information relevant to the response. Validating response headers allows you to verify if the server sends back the expected headers, such as content type or status codes. This helps ensure proper data interpretation and handling.
Identifying Communication Issues:
- HTTP headers can also be used to convey custom information specific to the application or API being used. Incorrect or missing headers can sometimes indicate configuration problems or misunderstandings between your application and the API. Header validation helps catch these issues early on.
Here's a typical example of Header Validation
pm.test("Content-Type header is JSON", () => {
pm.expect(pm.response.headers).to.have.property('Content-Type');
pm.expect(pm.response.headers.get('Content-Type')).to.equal('application/json');
});
This script checks for the presence of a
Content-Type
header in the response.It then verifies if the value of the
Content-Type
header is indeedapplication/json
, indicating JSON data.
Here is another example below
pm.test("Verify response headers keys are present ", () => {
pm.response.to.have.header("server");
pm.response.to.have.header("Date");
pm.response.to.have.header("Content-Type");
pm.response.to.have.header("Transfer-Encoding");
pm.response.to.have.header("Connection");
pm.response.to.have.header("Vary");
pm.response.to.have.header("X-Frame-Options");
pm.response.to.have.header("ETag");
pm.response.to.have.header("Allow");
pm.response.to.have.header("Strict-Transport-Security");
});
The script defines a Postman test named "Verify response headers keys are present".
Inside the test function, multiple assertions are chained together using
pm.response.to
.have.header
. This method is used to check for the existence of specific header names in the response.Each assertion targets a particular header name:
server
Date
Content-Type
Transfer-Encoding
Connection
Vary
X-Frame-Options
ETag
Allow
Strict-Transport-Security
Overall, this code snippet contributes to a more robust testing process by ensuring the presence of essential headers in the API response.
Now, let's talk about Error Handling: Debugging Failed Assertions
Understanding Failure Messages:
Postman provides informative error messages when assertions fail. These messages pinpoint the exact line of code where the assertion failed and offer clues about the nature of the mismatch.
There are various reasons why your assertions can fail πππ
Incorrect Assertions: Double-check your assertion syntax and ensure it accurately reflects your validation intent. Did you use the correct comparison operator (e.g.,
to.equal
vs.to.be
.above
)?Unexpected Response Data: The API response might not always conform to your expectations. Consider if the API might return different data structures or values under certain conditions.
Data Parsing Issues: If you're working with JSON data, ensure it's parsed correctly using
pm.response.json()
. Parsing errors can lead to assertion failures.Typos and Missing Properties: Meticulously review your code for typos in variable names or property names within the response body. Missing properties can also cause assertions to fail.
Debugging Tips:
Console Logging: Use
console.log
statements to print out intermediate values like the response body or specific properties. This helps you inspect data using your Postman console at different stages of your test script and identify where things might be going wrong.Test Breakdown: Break down complex assertions into smaller ones. This isolates the failing section and simplifies debugging.
Refer to Documentation: Consult the API documentation to understand the expected response format and data types. This helps you tailor your assertions accordingly.
Leverage Postman Features: Utilize Postman's built-in test runner and the "View Results" tab to visualize assertion failures and their corresponding error messages.
Good news π ππ Postman now has an AI inbuilt tool that you could use to write tests within your test collections or a stand-alone request called Postbot.
Postbot helps streamline your API development workflow in several ways:
Effortless Test Creation: Postbot suggests tests to validate your API's responses, saving you time writing them from scratch.
Smarter Scripting: Need help with scripting complex scenarios? Postbot offers guidance for writing JavaScript scripts within Postman.
Automated Draft Documentation: Say goodbye to manual documentation! Postbot analyzes your API interactions and generates draft documentation for a quick start.
Data Visualization Recommendations: Postbot recommends the most suitable visualizations for your response data, ensuring clear insights.
I have taken the time to record a short video that explains how to use Postbot within Postman to generate scripts, write tests and modify them.
%[https://www.loom.com/share/e08bb47a649343b1a9b22ba9517156cd?sid=dadaf3aa-4365-4b2e-9480-a32db2d29da5]
Tip: if you can't find this feature on your Postman, try to update or relaunch the app on your browser.
Finally, we've explored the power of assertions in crafting robust and efficient API tests. By leveraging assertions for status code validation, response body checks, response time monitoring, JSON schema enforcement, and header verification, you gain a comprehensive understanding of your API's behaviour.
Remember we also talked about the incredible AI assistant, Postbot, to further empower your workflow. Postbot can suggest tests, guide you with scripting complex scenarios, and even generate draft documentation β all to make your API development journey smoother and faster.
So, the next time you want to test your APIs, remember the power of assertions and Postman's comprehensive toolkit. Together, they can help you build exceptional APIs with confidence and efficiency.
Subscribe to my newsletter
Read articles from Esther Okafor directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Esther Okafor
Esther Okafor
Esther Okafor is a Quality assurance engineer passionate about delivering great user experience applications. Prioritizing quality over speed