DEV Community

Applying API Testing Frameworks: Real-World Examples with Code

API testing is a critical component of modern software development, ensuring that your application programming interfaces (APIs) function correctly, perform well, and remain secure. In this article, we'll explore practical implementations of popular API testing frameworks with real-world code examples, inspired by insights from Top 10 API Testing Tools for REST & SOAP Services.

1. Postman (Collection Runner + Newman)

Use Case: Testing a RESTful e-commerce API

// postman_test_example.js
const newman = require('newman');

newman.run({
    collection: require('./ecommerce-api-tests.json'),
    reporters: 'cli',
    iterationCount: 1
}, function (err) {
    if (err) { throw err; }
    console.log('Postman collection run complete!');
});

// Example test in Postman collection
pm.test("Status code is 200", function () {
    pm.response.to.have.status(200);
});

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

pm.test("Product has valid structure", function () {
    const jsonData = pm.response.json();
    pm.expect(jsonData).to.have.property('id');
    pm.expect(jsonData).to.have.property('name');
    pm.expect(jsonData).to.have.property('price');
    pm.expect(jsonData.price).to.be.a('number');
});
Enter fullscreen mode Exit fullscreen mode

Real-world application: Run regression tests in CI/CD pipeline using Newman (Postman's CLI tool)

2. RestAssured (Java)

Use Case: Testing a banking API with authentication

// BankingAPITest.java
import io.restassured.RestAssured;
import io.restassured.response.Response;
import org.junit.Test;
import static io.restassured.RestAssured.given;
import static org.hamcrest.Matchers.*;

public class BankingAPITest {

    @Test
    public void testAccountBalanceEndpoint() {
        RestAssured.baseURI = "https://api.bank.example.com";

        given()
            .auth()
            .oauth2("valid-access-token")
            .pathParam("accountId", "12345")
        .when()
            .get("/accounts/{accountId}/balance")
        .then()
            .statusCode(200)
            .body("accountId", equalTo("12345"))
            .body("balance", is(not(empty())))
            .body("currency", equalTo("USD"))
            .time(lessThan(1000L));
    }

    @Test
    public void testTransactionHistory() {
        Response response = given()
            .auth()
            .basic("username", "password")
            .queryParam("from", "2023-01-01")
            .queryParam("to", "2023-12-31")
            .get("/transactions");

        response.then()
            .statusCode(200)
            .body("transactions", hasSize(greaterThan(0)))
            .body("transactions[0].amount", is(notNullValue()));
    }
}
Enter fullscreen mode Exit fullscreen mode

Real-world application: Comprehensive testing of financial APIs with complex authentication requirements

3. PyTest with Requests (Python)

Use Case: Testing a weather API with parameterized tests

# test_weather_api.py
import pytest
import requests

BASE_URL = "https://api.weather.example.com/v1"

@pytest.mark.parametrize("city,country,expected_status", [
    ("London", "UK", 200),
    ("New York", "US", 200),
    ("Invalid City", "XX", 404),
])
def test_get_weather_by_city(city, country, expected_status):
    response = requests.get(
        f"{BASE_URL}/weather",
        params={"city": city, "country": country},
        headers={"Authorization": "Bearer test-api-key"}
    )

    assert response.status_code == expected_status

    if expected_status == 200:
        data = response.json()
        assert "temperature" in data
        assert "humidity" in data
        assert "conditions" in data
        assert isinstance(data["temperature"], float)

@pytest.fixture
def auth_token():
    # Get auth token once for multiple tests
    response = requests.post(
        f"{BASE_URL}/auth",
        json={"username": "testuser", "password": "testpass"}
    )
    return response.json()["token"]

def test_forecast_endpoint(auth_token):
    response = requests.get(
        f"{BASE_URL}/forecast",
        params={"days": 5},
        headers={"Authorization": f"Bearer {auth_token}"}
    )

    assert response.status_code == 200
    forecast = response.json()
    assert len(forecast) == 5
    assert all("date" in day and "high" in day for day in forecast)
Enter fullscreen mode Exit fullscreen mode

Real-world application: Data-driven testing of weather API with different locations and authentication scenarios

4. Karate DSL (BDD Style)

Use Case: Testing a microservices architecture with complex workflows

# user_management.feature
Feature: User Management API Tests

Background:
  * url 'https://api.users.example.com'
  * header Authorization = 'Bearer ' + token
  * def token = call read('get_token.js') { username: 'admin', password: 'admin123' }

Scenario: Create and verify new user
  Given path '/users'
  And request { name: 'Test User', email: 'test.user@example.com', role: 'member' }
  When method post
  Then status 201
  And match response == { id: '#number', name: 'Test User', email: 'test.user@example.com', role: 'member' }

  * def userId = response.id

  Given path '/users/' + userId
  When method get
  Then status 200
  And match response contains { id: '#number', name: 'Test User' }

Scenario: Test user search with parameters
  Given path '/users/search'
  And param role = 'admin'
  When method get
  Then status 200
  And match each response.users contains { role: 'admin' }
  And assert response.users.length > 0
Enter fullscreen mode Exit fullscreen mode

Real-world application: Testing complex user flows in microservices with readable BDD syntax

5. SoapUI (SOAP Service Testing)

Use Case: Testing a legacy SOAP-based inventory system

<!-- inventory_check.xml -->
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
                 xmlns:inv="http://www.example.com/inventory">
   <soapenv:Header/>
   <soapenv:Body>
      <inv:CheckInventoryRequest>
         <inv:productId>1001</inv:productId>
         <inv:warehouse>NYC</inv:warehouse>
      </inv:CheckInventoryRequest>
   </soapenv:Body>
</soapenv:Envelope>
Enter fullscreen mode Exit fullscreen mode
// Groovy Script Assertion in SoapUI
def groovyUtils = new com.eviware.soapui.support.GroovyUtils(context)
def holder = groovyUtils.getXmlHolder("CheckInventoryRequest#Response")

def availableQty = holder.getNodeValue("//*:availableQuantity")
def status = holder.getNodeValue("//*:status")

assert availableQty.toInteger() >= 0
assert status == "IN_STOCK" || status == "OUT_OF_STOCK"

// Performance check
assert context.responseTime < 500
Enter fullscreen mode Exit fullscreen mode

Real-world application: Maintaining and testing legacy SOAP services with complex XML payloads

Best Practices for API Testing Frameworks

  1. Environment Management: Use config files to manage different environments
   // config.js
   module.exports = {
     dev: {
       baseUrl: 'https://dev.api.example.com',
       apiKey: 'dev-key-123'
     },
     staging: {
       baseUrl: 'https://staging.api.example.com',
       apiKey: 'staging-key-456'
     },
     prod: {
       baseUrl: 'https://api.example.com',
       apiKey: process.env.PROD_API_KEY
     }
   };
Enter fullscreen mode Exit fullscreen mode
  1. Test Data Management: Generate test data dynamically
   # test_data.py
   from faker import Faker

   fake = Faker()

   def generate_user_data():
       return {
           'name': fake.name(),
           'email': fake.email(),
           'address': fake.address(),
           'phone': fake.phone_number()
       }
Enter fullscreen mode Exit fullscreen mode
  1. Reporting: Generate comprehensive test reports
   // RestAssured with ExtentReports
   @AfterSuite
   public void tearDown() {
       ExtentReports extent = new ExtentReports();
       ExtentSparkReporter spark = new ExtentSparkReporter("target/Spark.html");
       extent.attachReporter(spark);
       extent.flush();
   }
Enter fullscreen mode Exit fullscreen mode
  1. Performance Checks: Always include performance assertions
   // Postman
   pm.test("Response time is acceptable", function () {
       pm.expect(pm.response.responseTime).to.be.below(300);
   });
Enter fullscreen mode Exit fullscreen mode
  1. Security Testing: Include basic security checks
   # pytest
   def test_secure_headers(response):
       assert 'X-Content-Type-Options' in response.headers
       assert response.headers['X-Frame-Options'] == 'DENY'
       assert 'Content-Security-Policy' in response.headers
Enter fullscreen mode Exit fullscreen mode

Conclusion

Choosing the right API testing framework depends on your tech stack, team skills, and API complexity. Postman is excellent for collaborative manual testing, RestAssured integrates well with Java ecosystems, PyTest offers Python simplicity, Karate provides BDD readability, and SoapUI handles SOAP services effectively.

By implementing these real-world examples and following best practices, you can build a robust API testing strategy that catches bugs early, ensures performance standards, and maintains API reliability throughout your development lifecycle.

Remember to:

  • Test for both happy paths and error cases
  • Validate response schemas
  • Include performance assertions
  • Test security aspects
  • Automate in your CI/CD pipeline
  • Maintain your tests as your API evolves

Top comments (1)

Collapse
 
mariela_estefanyramoslo profile image
MARIELA ESTEFANY RAMOS LOZA

good job!