API Testing with Postman Guide
API Testing with Postman Guide
-Comes with powerful JS Editor(Postman Object)-->Helps to perform Assertions(Validates test) -Ready Made features of framework-->variables, environements, workflows, data
driven components and pm object which helps quickly setup automation quickly -Powerful integration with NewMan tool, to run the automated tests from CLI, later can be integrated
with Jenkins for CI/CD integration
Example: -Create Library collection: Base URL: [Link] ([Link] -AddBook Request Base URL + Resource:---
>[Link] Body: { "name":"Java", "isbn":"abn23", "aisle":"1234", "author":"prime" } -GetBook Request Base URL + Resource:---
>[Link] -DeleteBook Request Base URL + Resource:--->[Link]
Body: { "ID": "abn231234" }
--Environments in Postman: -An Environment is a set of variables, you can use in your postman [Link] can use environments to group related set of values together and
manage access to shared postman data, if you are working as a part of team -Variables allow you to store and reuse values in your requests and scripts. By storing a value in a
variable, you can reference it throughout your collection,environements and requests and if you need to update the value, you only have to change it in one place. Using variable
increases your ability to work efficiently and minimize the likelihood of error. -Environments tab-->Create environment-->create variable and set variable in the request by selecting
and double clicking that hardcoded value.
--Variable scopes:-->Postman supports following variable scopes -Global -Collection -Environment -Data (Rarely used) -Local (Rarely used) Environments-->Global(Common
variables to entire postman workspace) Collection-->Variables tab(can be accessed within that collection, request part of this collection will access it) Environment variables-->specific
to environment Data variable-->for data driven testing Local variable-->specific to request Note: If variable with same name is declared in 2 different scopes, the value stored in
variable with narrower scope will be used.
POSTMAN
GLOBAL VARIABLES
COLLECTION VARIABLES
Scripting in Postman:
-Postman contains runtime based NodeJs that allows to add dynamic behavior to requests and collections. This allows us to write Test Suits, buld requests that can contain dynamic
parameters, pass data between requests
===================================
POSTMAN SCRIPT EXECUTION ORDER
(ONE SNAP)
STEP 1: COLLECTION PRE-REQUEST SCRIPT
• Runs first • Executes before every request in the collection • Used for:
Dynamic headers
Timestamp, random values
Updating variables
Common validations
Cleanup
Logging
In Postman, scripts execute in the order: Collection pre-request → Folder pre-request → Request pre-request → Request → Request test → Folder test → Collection test.
--The pm Object--> You will carry out most of POSTMAN JS API functionality using "pm" which provides access to request and response data and variable. [Link]("",)-->Takes two
arguments, description and function where we write code.
const jsonData = [Link](); [Link]("validate status code is 200", function() { [Link](200); [Link](jsonData).[Link]("Msg");
[Link]([Link]).[Link]("successfully added"); });
--Dynamically generate values for variable Rule: isbn should start with RS and then dynamically generate values(Pre Request script)-->RS is constant, we can use as Global varible
as "CompanyCode" At collection level set isbn as new variable
const code = [Link]("CompanyCode"); const val = [Link]('{{$randomInt}}'); [Link]("isbn",code+val); const jsonData = [Link]();
[Link]("validate status code is 200", function() { [Link](200); [Link](jsonData).[Link]("Msg"); [Link]([Link]).[Link]("successfully
added"); }); //checking header contains Content-Type [Link]("Header cookies response time validations",function() { [Link]([Link]("Content-
Type")).[Link]("application/json;charset=UTF-8"); [Link]([Link]).[Link](400); [Link]([Link]()).[Link]("successfully added"); });
const code = [Link]("CompanyCode"); const val = [Link]('{{$randomInt}}'); [Link]("isbn",code+val); const jsonData = [Link]();
const bookId = [Link]; [Link]([Link]); [Link]("book_id",bookId); [Link]("validate status code is 200", function() { [Link](200);
[Link](jsonData).[Link]("Msg"); [Link]([Link]).[Link]("successfully added"); }); [Link]("Header cookies response time validations",function() {
[Link]([Link]("Content-Type")).[Link]("application/json;charset=UTF-8"); [Link]([Link]).[Link](400);
[Link]([Link]()).[Link]("successfully added"); });
-Go to GetBook and in 'params'-->set ID from environment variable-->{{book_id}} -same for DeleteBook -Go to collection level and run
--Validate response with the Input data of other API through Automated Code -AddBook API const code = [Link]("CompanyCode"); const val =
[Link]('{{$randomInt}}'); [Link]("isbn",code+val); [Link]("author_name","Rohit Prime"); const jsonData = [Link]();
const bookId = [Link]; [Link]([Link]); [Link]("book_id",bookId); [Link]("validate status code is 200", function() { [Link](200);
[Link](jsonData).[Link]("Msg"); [Link]([Link]).[Link]("successfully added"); }); [Link]("Header cookies response time validations",function() {
[Link]([Link]("Content-Type")).[Link]("application/json;charset=UTF-8"); [Link]([Link]).[Link](400);
[Link]([Link]()).[Link]("successfully added"); });
-GetBook API const getBookResponse = [Link](); [Link](getBookResponse); [Link]("Validate JSON response logic",function() {
[Link](getBookResponse[0].author).[Link]([Link]("author_name")); });
const getBookResponse = [Link](); [Link](getBookResponse); const schema = { "type": "array", "items": [ { "type": "object", "properties": { "book_name": { "type":
"string" }, "isbn": { "type": "string" }, "aisle": { "type": "string" }, "author": { "type": "string" } }, "required": [ "book_name", "isbn", "aisle", "author" ] } ] }; [Link]("Validate JSON response
logic",function() { [Link](getBookResponse[0].author).[Link]([Link]("author_name")); });
-DeletBook const schema = { "type": "object", "properties": { "msg": { "type": "string" } }, "required": [ "msg" ] }; [Link]("Validate the message after succesful operation",function() {
const jsonData = [Link](); [Link]([Link]).[Link]("book is successfully deleted"); }); [Link]("validating the schema for DeleteBook API",function() {
[Link](schema); });
-For Functional validation--> bookId should be isbn(get from collection variable) + aisle(Present in request-->[Link]() is not present, so we have to access request body in raw
format and then convert to JSON) const code = [Link]("CompanyCode"); const val = [Link]('{{$randomInt}}');
[Link](req).[Link]("isbn");
[Link](req).[Link]("aisle");
});
Alternate way: [Link]("ID Logic validation", function () { const req = [Link] && [Link] ? [Link]([Link]) : ;
[Link](expected_id).[Link](bookId);
});
[Link]("ID Logic validation", function () { //const isbn_val = [Link]("isbn"); const req = [Link]([Link]);
[Link](req).[Link]("isbn");
[Link](req).[Link]("aisle");
});
Now go to collection level -->click on Run-->Click on Select File-->Run Library(i.e Run Collection)
For Delay [Link]("Delay test by 2 seconds", function (done) { setTimeout(function () { [Link]([Link]).[Link](200); done(); }, 1000); // 2000 ms = 2 seconds });
--Error Handling Scenarios: Consider same bookId generated for AddBook request-->It will throw error, Book already exists replace: { "name":"{{book_name}}", "isbn":"{{isbn}}",
"aisle":"8772", "author":"{{author_name}}" }
const jsonData = [Link](); const bookId = [Link]; [Link]("book_id", bookId); function generateBookId() { var req = [Link]([Link]);
const expected_id = [Link] + [Link]; return expected_id; } function cleanupScript() { const book_id = generateBookId(); [Link]("book_id",book_id);
[Link]("DeleteBook"); } [Link]("validate status code is 200", function () { try { [Link](200); [Link](jsonData).[Link]("Msg");
[Link]([Link]).[Link]("successfully added"); } catch(err) { //check if error is due to already book exists if([Link]("Exists")) { cleanupScript(); } } });
[Link]("ID Logic validation", function () { //const isbn_val = [Link]("isbn"); const req = [Link]([Link]);
[Link](req).[Link]("isbn");
[Link](req).[Link]("aisle");
});
// [Link]("Delay test by 2 seconds", function (done) { // setTimeout(function () { // [Link]([Link]).[Link](200); // done(); // }, 1000); // 2000 ms = 2 seconds // });
Note: “Both methods do the same thing. [Link]() is legacy, while [Link]() is the newer, recommended API. Both work only in runner-based
executions.”
const jsonData = [Link](); const bookId = [Link]; [Link]("book_id", bookId); function generateBookId() { var req = [Link]([Link]);
const expected_id = [Link] + [Link]; return expected_id; } function cleanupScript() { const book_id = generateBookId(); [Link]("book_id",book_id);
[Link]("calling DeleteBook"); [Link]("flag",true); [Link]("DeleteBook"); //[Link]("DeleteBook"); } [Link]("validate
status code is 200", function () { try { [Link](200); [Link](jsonData).[Link]("Msg"); [Link]([Link]).[Link]("successfully added"); }
catch(err) { //check if error is due to already book exists if([Link]("Exists")) { cleanupScript(); } } });
[Link]("ID Logic validation", function () { //const isbn_val = [Link]("isbn"); const req = [Link]([Link]);
[Link](req).[Link]("isbn");
[Link](req).[Link]("aisle");
});
// [Link]("Delay test by 2 seconds", function (done) { // setTimeout(function () { // [Link]([Link]).[Link](200); // done(); // }, 1000); // 2000 ms = 2 seconds // });
DeleteBook:
const schema = { "type": "object", "properties": { "msg": { "type": "string" } }, "required": [ "msg" ] }; [Link]("Validate the message after succesful operation",function() { const jsonData
= [Link](); [Link]([Link]).[Link]("book is successfully deleted"); if([Link]("flag")) { [Link]("AddBook");
[Link]("flag",false); } }); [Link]("validating the schema for DeleteBook API",function() { [Link](schema); });
Note: set back request body to { "name":"{{book_name}}", "isbn":"{{isbn}}", "aisle":"8772", "author":"{{author_name}}" } -Run again with [Link]
-Why Applications Rely on other (Google or Facebook) authentication?-->No data breach,no user profile data required,common login
Collection Pre-request ↓ Generate OAuth token (if expired) ↓ Store access_token ↓ Attach token to request ↓ Call protected API ↓ Validate response
When you sign in to an app like BookMyShow using Google, the app uses OAuth 2.0 Authorization Code flow. Step-by-step flow --BookMyShow creates a Google login URL
(Authorization URL) This URL is unique for that application because it contains:client_id (public),redirect_uri, scope (what data is requested: email, profile,
etc.),response_type=code Client Secret is never exposed in the browser. --User is redirected to Google Authorization Server User enters Google credentials then,Google verifies the
user (authentication).Google also asks consent (permissions) based on scope --Google sends Authorization Code back to BookMyShow Google redirects to BookMyShow’s
redirect_uri with:code=AUTHORIZATION_CODE This authorization code is short-lived (like a one-time code).(It’s not exactly OTP, but similar idea.) --BookMyShow exchanges
Authorization Code for Access Token BookMyShow backend (server-side) sends a request to Google Token Endpoint It includes:authorization code,client_id,client_secret (only on
server, not visible to user),redirect_uri,grant_type=authorization_code --Google returns tokens Google responds with:access_token (used to call APIs),expires_in sometimes
refresh_token (to get new access tokens without login again),sometimes id_token (OpenID Connect, contains user identity) --BookMyShow calls Google Resource APIs
BookMyShow uses access_token to fetch user info like:name,email,profile picture(based on scope) --BookMyShow creates its own session BookMyShow stores a session
(cookie/JWT) in the browser For every next operation, BookMyShow uses: its own session token (most common) and/or access token when it needs Google APIs
Client ID
[Link]
Client Secret
erZOWM9g3UtwNRj340YYaK_W
Scope
[Link] ([Link]
State
Any random string (example: abc123xyz)
How to pass OAuth in API Request
Purpose:
Used to authenticate the user and obtain an Authorization Code from the Authorization Server.
Endpoint:
Authorization Server URL
Example:
[Link] ([Link]
Output:
Authorization Code (example: code=4/0AX4XfWj...)
Purpose:
Used by the client application to exchange Authorization Code for Access Token.
Endpoint:
Access Token URL
Example:
[Link] ([Link]
Mandatory Parameters:
code client_id client_secret redirect_uri grant_type=authorization_code
Request Method:
POST
Output:
-Mock Servers: A mock API Server imitates a real API server by providing realistic mock API response to [Link] postman, you can make requests that return mock data
defined if you do not have production API ready, or you do not want to run your requests against real data yet e.g--> {{base_url}}/getapitestingcourses --> If this endpoint is under
development, we have to tell postman to create mock_server {{base_url}}/getcoursedetails?name={{course}} Mock server: {{mock_server_url}}/getapitestingcourses ---->Give
postman sample response you expect(configure it)-->Based on it we can write code, which will be valid for real api
-Automatically environment will be created -to create mock server-->Go to mock server tab(below collection)--> create a new mock server-->create a new colllectiorn->add request
method,Request URL,Response code, response body<-----(configure all these field in table) give name to mock server -->MockAPITesting copy mock server URL--->e.g
[Link] ([Link] { "data": [ { "course": "Postman", "price": 150,
"category": "JavaScript" }, { "course": "SOAPUI", "price": 25, "category": "Groovy" }, { "course": "Rest Assured", "price": 120, "category": "Java" }, { "course": "Selenium", "price": 200,
"category": "Java" }, { "course": "Cypress", "price": 180, "category": "JavaScript" }, { "course": "Playwright", "price": 170, "category": "TypeScript" } ] }
Go to mock server-->click on collection link inside it-->go to set up tab-->click on request link Hit it now when code is ready simply switch environment to QA/UAT, url available in that
environment will be hit -we can write script as well
[Link] ([Link]
[Link] ([Link]
WSDL) [Link] ([Link]
[Link] ([Link]
[Link] ([Link] [Link]
([Link] [Link] ([Link]
[Link] ([Link] [Link]
wsdl ([Link] [Link] ([Link] SOAP
WebServices
Steps to run: Export collection file to local(Collection v2.1)-->select enviroment and then export and also export json files for all environments) Open terminal and navigate to directory
where file located(Also paster csv file which needed at same location) (FileName should be underscore, no spaces should be their) run command: newman run
Library.postman_collection.json -d [Link] -e QA.postman_environment.json -g workspace.postman_globals.json
--Set Up Jenkins:
-Download Generic Java Package(.war): [Link] ([Link] -open cmd as admin and run command: java -jar [Link] -httpPort:9090 -Go to
localhost:9090 in browser and setup username and password -Go to Jenkins Dashboard, select New Item -Freestyle project -On Configuration page-->Build triggers tab-->Build
steps-->Execute windows batch command(For windows)/Execute shell(For Mac or linux)-->Paste commands D: cd Testing Prep\Selenium Practice\Projects newman run
Library.postman_collection.json -d [Link] -e QA.postman_environment.json -g workspace.postman_globals.json -r htmlextra
Parameterize jenkins--> go to job -->configure-->General tab-->Select-->This project is Prameterized-->Click on Add Parameter-->Select choice parameter(From Dropdown) --
>Choice parameter-->Name as 'Environment'-->Choices as QA, UAT -->Go to Build-->Execute windows batch command-->command-->"$Env".postman(new command added this)
D: cd Testing Prep\Selenium Practice\Projects newman run Library.postman_collection.json -d [Link] -e "%Environment%".postman_environment.json -g
workspace.postman_globals.json
--Version control features: -Share collection, push to workspaces -Share public link -Create a fork(Option available for collection)-->Fork label-->Click on Fork Collection -Make
changes and click on create pull request-->Approve and Merge -We can Delete source of changes
--Add Monitor: To run collection periodically to check for its performance and response Create a monitor-->Monitor Name->Smoke test Collection->Library Collection Version Tag-
>Current Environment->QA Run this monitor-->Frequency(e.g->minute,day etc) Select Receive mails Select retry if fials->2 times Click on create
Project:
-Flow:-> Login API-->Create Product-->Purchase Order on created product-->Delete Order -URL: [Link]/client/auth/login --->Register and create login -Inspect
page before and after login to see the network calls, as we don't have documentation we should be able to create documentation from browser onlu. -When we login we get the token
in response, which used in all subsequent calls(Token tells who we are)
--Create API Collection:-->ECOM -Open login page-->Go to Inspect(Network calls)-->see 'login' call-->check Header for request URL-->Add request 'login' in collection which is POST
call URL--> [Link] ([Link] Body: From Payload get it {
"userEmail":"lavatero92@[Link]", "userPassword":"Admin@123" } Copy the token and userId and set it to collection variables
const jsonData = [Link](); const userId = [Link]; [Link](userId); [Link]("userId",userId);
[Link]("token",[Link]); [Link]("Validating Login",function() { [Link]([Link]).[Link]("Login Successfully"); });
-Now let us 'CreateOrder' i.e Place Oreder URL: [Link] ([Link] HTTP
Method: POST { "orders": [ { "country": "India", "productOrderedId": "{{productId}}" } ] }
const jsonData = [Link](); const orderId = [Link][0]; [Link](orderId); [Link]("orderId",orderId); [Link]("Verifying product order
placement",function() { [Link]([Link]).[Link]("Order Placed Successfully"); });