API Testing using Postman
Tags: postmanapi, testing, tutorial
Published: 2023-11-18 02:24:50

In the dynamic world of API testing, versatility is key. With Postman, a leading API testing tool, there's no one-size-fits-all approach to test codes. The significance of each test hinges on the unique demands and context of your API. But fear not! Whether you're a seasoned developer or just starting out, understanding the landscape of API testing is crucial. In this insightful guide, we'll delve into the diverse and vital types of tests. Get ready to enhance your API testing skills and bring precision and efficiency to your projects!

## Types of Test

There isn't a single "most important" test code, as the importance of a test depends on the specific requirements and context of the API you are testing. However, there are several common and crucial types of tests that are often used in API testing with Postman:

- **Status Code Verification:** Ensuring that the API returns the expected HTTP status code. For example, a 200 OK for successful requests, 404 Not Found for invalid endpoints, or 500 Internal Server Error for server issues. 

```javascript
pm.test("Status code is 200", function () {
    pm.response.to.have.status(200);
});

```

---

- **Response Time Validation:** Checking that the API responds within an acceptable time frame. This is crucial for performance testing.

```javascript
pm.test("Response time is less than 500ms", function () {
    pm.expect(pm.response.responseTime).to.be.below(500);
});

```

---

- **Data Validation:** Ensuring that the response body contains the correct data. This could involve checking the structure of the response JSON or XML, and verifying that the values are as expected. 

```javascript
pm.test("Response body has correct data", function () {
    var responseJson = pm.response.json();
    pm.expect(responseJson.name).to.eql("John Doe");
    pm.expect(responseJson.id).to.eql(123);
});

```

---

- **Header Checks:** Verifying that the HTTP headers in the response are correct. This can include checks for content type, security headers, etc. 

```javascript
pm.test("Content-Type header is present and application/json", function () {
    pm.response.to.have.header("Content-Type", "application/json");
});

```

---

- **Authentication and Authorization Tests:** Ensuring that requests are properly authenticated and that users have the correct authorization level for different requests. 

```javascript
pm.test("Response should be unauthorized", function () {
    pm.response.to.have.status(401);
});

```

---

- **Error Handling Tests:** Verifying that the API handles errors gracefully and returns appropriate error messages and codes. 

```javascript
pm.test("Error message is as expected", function () {
    var responseJson = pm.response.json();
    pm.expect(responseJson.error).to.eql("Invalid request parameters");
});

```

---

- **Business Logic Verification:** Testing the actual business logic that the API implements, to ensure it meets the specified requirements. 

```javascript
pm.test("Discount is applied correctly", function () {
    var responseJson = pm.response.json();
    pm.expect(responseJson.total).to.eql(responseJson.subtotal - responseJson.discount);
});

```

---

- **Schema Validation:** Ensuring that the response follows a defined schema or structure, which is particularly important for RESTful APIs. 

```javascript
const schema = {
    "type": "object",
    "required": ["name", "id"],
    "properties": {
        "name": {"type": "string"},
        "id": {"type": "number"}
    }
};

pm.test("Schema is valid", function() {
    pm.response.to.have.jsonSchema(schema);
});

```

---

- **Integration Tests:** Checking how the API interacts with other services and databases. 

```javascript
pm.test("User profile data matches with database", function () {
    // Here you'd typically use pm.sendRequest to query another API or database
    // For demonstration, assuming a static check
    var responseJson = pm.response.json();
    pm.expect(responseJson.username).to.eql("user_from_db");
});

```

---

- **Security Tests:** Identifying vulnerabilities in the API, like SQL injection, Cross-Site Scripting (XSS), and other security threats. 

```javascript
pm.test("No SQL Injection vulnerability", function () {
    // This would ideally involve sending a potentially malicious SQL code in the request and checking the response
    pm.response.to.not.have.status(500); // Simple check for server error
    pm.response.to.not.have.body("SQL"); // Ensure response does not contain SQL error messages
});

```

---

## GET Test

Let's consider a more complex and tailored test for a hypothetical GET API request. This API, for example, could be for retrieving user profile information. The test will cover various aspects, including status code verification, response time, data validation, schema validation, and some custom logic related to the data returned.

### Hypothetical API Details:

- **Endpoint: /api/users/{userId}**
- **Method: GET**
- **Response Structure:**

```json
{
    "userId": "string",
    "name": "string",
    "email": "string",
    "roles": ["string"],
    "isActive": "boolean",
    "lastLogin": "string" // Date in ISO format
}

```
### Sample Test Code in Postman:

```javascript
// Test for Status Code and Response Time
pm.test("Status code is 200 and response time is acceptable", function () {
    pm.response.to.have.status(200);
    pm.expect(pm.response.responseTime).to.be.below(1000); // assuming 1000ms as the threshold
});

// Data Validation with Multiple Checks
pm.test("Response body has correct data structure", function () {
    let responseJson = pm.response.json();
    pm.expect(responseJson).to.have.keys("userId", "name", "email", "roles", "isActive", "lastLogin");
    pm.expect(responseJson.userId).to.be.a('string');
    pm.expect(responseJson.name).to.be.a('string');
    pm.expect(responseJson.email).to.match(/^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$/); // Email format validation
    pm.expect(responseJson.roles).to.be.an('array');
    pm.expect(responseJson.isActive).to.be.a('boolean');
    pm.expect(new Date(responseJson.lastLogin)).to.be.a('date');
});

// Schema Validation (assuming a predefined schema variable)
const userProfileSchema = {
    "type": "object",
    "required": ["userId", "name", "email", "roles", "isActive", "lastLogin"],
    "properties": {
        "userId": {"type": "string"},
        "name": {"type": "string"},
        "email": {"type": "string", "format": "email"},
        "roles": {
            "type": "array",
            "items": {"type": "string"}
        },
        "isActive": {"type": "boolean"},
        "lastLogin": {"type": "string", "format": "date-time"}
    }
};

pm.test("Schema is valid", function() {
    pm.response.to.have.jsonSchema(userProfileSchema);
});

// Custom Logic Check
pm.test("User is active and has logged in within the last month", function () {
    let responseJson = pm.response.json();
    pm.expect(responseJson.isActive).to.be.true;
    let lastLoginDate = new Date(responseJson.lastLogin);
    let aMonthAgo = new Date();
    aMonthAgo.setMonth(aMonthAgo.getMonth() - 1);
    pm.expect(lastLoginDate).to.be.above(aMonthAgo);
});

```
In this example, we have created a more comprehensive set of tests that not only check the basic aspects like status code and response time but also validate the data structure, ensure the response matches a predefined schema, and include a custom logic check to validate business rules (e.g., the user's active status and recent login).

## PUT Test

Let's consider a PUT API request that updates user details. This type of request often requires careful testing to ensure data integrity and adherence to business rules.

### Hypothetical API Details:

- **Endpoint: /api/users/{userId}**
- **Method: PUT**
- **Request Body:**

```json
{
  "name": "string",
  "email": "string",
  "isActive": "boolean"
}

```

- **Expected Response:** Status code 200 for successful update, with a JSON body containing the updated user details.

### Sample Test Code in Postman:

```javascript
// Variables for Request Data
const requestData = pm.request.body.toJSON();

// Test for Status Code
pm.test("Status code is 200 for successful update", function () {
    pm.response.to.have.status(200);
});

// Response Time Validation
pm.test("Response time is within acceptable limits", function () {
    pm.expect(pm.response.responseTime).to.be.below(2000); // 2000ms as a threshold
});

// Data Validation
pm.test("Response body matches updated data", function () {
    let responseJson = pm.response.json();
    pm.expect(responseJson.name).to.eql(requestData.name);
    pm.expect(responseJson.email).to.eql(requestData.email);
    pm.expect(responseJson.isActive).to.eql(requestData.isActive);
});

// Email Format Check
pm.test("Email format is valid", function () {
    let responseJson = pm.response.json();
    pm.expect(responseJson.email).to.match(/^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$/); // Simple regex for email validation
});

// Check for Required Fields in Response
pm.test("Response has all required fields", function () {
    let responseJson = pm.response.json();
    pm.expect(responseJson).to.have.all.keys("userId", "name", "email", "isActive");
});

// Custom Business Rule Check (Example: isActive should not be true if user's email is not verified)
pm.test("Active status should not be true for unverified email", function () {
    let responseJson = pm.response.json();
    if (responseJson.isActive) {
        // Assuming there's a field in response that indicates email verification status
        pm.expect(responseJson.isEmailVerified).to.be.true;
    }
});

// Additional Security Check (e.g., Checking for unexpected modifications)
pm.test("Response should not contain sensitive data", function () {
    let responseJson = pm.response.json();
    pm.expect(responseJson).to.not.have.keys("password", "securityQuestionAnswers");
});

```

In this example, the tests are tailored to verify not only the basic functionality of the PUT request (like status code and response structure) but also to ensure that the update adheres to business rules and security standards. The tests check if the response data matches the update request, validate the email format, ensure no sensitive data is exposed, and include a custom check related to the business logic (like the user's active status in relation to their email verification status).

Remember, the specifics of your tests will vary based on the exact nature of your API, its business logic, security considerations, and other factors unique to your application.