Skip to content

API Testing — Complete Guide to Validating Endpoints

DodaTech Updated 2026-06-28 4 min read

In this tutorial, you will learn about API Testing. We cover key concepts, practical examples, and best practices to help you master this topic.

API testing validates that endpoints return correct responses under expected and unexpected conditions, covering functional tests, security tests, performance tests, and contract validation for every API.

What You'll Learn

  • The four main categories of API testing
  • How to write functional, security, and performance tests
  • Tools and frameworks for automated API testing

Why It Matters

An untested API that fails in production breaks every consumer. Automated API testing catches regressions before deployment and ensures contracts are honored under all conditions.

Real-World Use

Doda Browser's bookmark sync API runs 500+ automated tests per deployment: functional tests verify each endpoint, security tests check authentication bypass attempts, and performance tests ensure under 200ms response time under load.

flowchart LR
    A["API Testing"] --> B["Functional"]
    A --> C["Security"]
    A --> D["Performance"]
    A --> E["Contract"]
    B --> F["Status Codes"]
    B --> G["Response Body"]
    C --> H["Auth Bypass"]
    C --> I["Injection"]
    D --> J["Latency"]
    D --> K["Throughput"]
    style A fill:#dbeafe,stroke:#2563eb

Code Examples

import requests
import pytest

BASE = "https://api.example.com/v1"

def test_get_users_returns_200():
    resp = requests.get(f"{BASE}/users", headers={"Authorization": "Bearer test-token"})
    assert resp.status_code == 200
    assert "users" in resp.json()

def test_get_users_requires_auth():
    resp = requests.get(f"{BASE}/users")
    assert resp.status_code == 401

def test_create_user_validates_body():
    resp = requests.post(
        f"{BASE}/users",
        json={"name": ""},
        headers={"Authorization": "Bearer test-token"}
    )
    assert resp.status_code == 422
    assert "name" in resp.json().get("errors", {})

Expected output: Tests pass if endpoints return correct status codes and response bodies.

const request = require('supertest');
const app = require('./app');

describe('GET /api/users', () => {
  it('returns 200 with users array', async () => {
    const res = await request(app)
      .get('/api/users')
      .set('Authorization', 'Bearer test-token');
    expect(res.status).toBe(200);
    expect(Array.isArray(res.body.users)).toBe(true);
  });

  it('returns 401 without auth header', async () => {
    const res = await request(app).get('/api/users');
    expect(res.status).toBe(401);
  });
});

Expected output: Jest reports passing and failing test suites with clear error messages.

from locust import HttpUser, task, between

class ApiUser(HttpUser):
    wait_time = between(1, 5)

    @task
    def get_users(self):
        self.client.get("/users", headers={"Authorization": "Bearer test-token"})

    @task
    def create_user(self):
        self.client.post("/users", json={"name": "Test User", "email": "test@example.com"},
                         headers={"Authorization": "Bearer test-token"})

Expected output: Locust reports average response time, requests per second, and error rate under simulated load.

Common Mistakes

1. Only Testing the Happy Path

APIs break most often on edge cases. Test empty inputs, missing fields, invalid types, and duplicate submissions.

2. Ignoring Security Tests

Functional tests that pass can still leave authentication bypass vulnerabilities. Always test unauthorized access.

3. Not Testing Error Responses

Clients depend on error format and status codes. Test that 400, 401, 403, 404, 422, and 500 responses match the spec.

4. Skipping Performance Tests

An API that works for one user may fail at 1000 concurrent users. Load test before every major release.

5. Hardcoding Test Data

Tests that depend on specific database state become fragile. Use factories, fixtures, or API seeding for reproducible tests.

Practice Questions

  1. What four categories of API testing should every project include?
  2. Why should you test error responses in addition to success responses?
  3. What is the difference between functional and contract testing?
  4. Why is hardcoded test data problematic?
  5. How does performance testing differ from functional testing?

Answers:

  1. Functional, security, performance, and contract testing.
  2. Clients depend on error response formats; undefined errors cause fragile parsing.
  3. Functional testing validates behavior; contract testing validates the API matches its specification.
  4. Tests become brittle and fail when seed data changes.
  5. Performance testing measures response times and throughput under load, not correctness.

Challenge: Write a test suite for a payment API that includes functional tests for creating a charge, security tests for missing auth, and a load test simulating 100 concurrent checkout flows.

FAQ

What is contract testing in APIs?

: Contract testing verifies that an API responses match its specification (OpenAPI, RAML), ensuring provider-consumer compatibility.

Should API tests be in the same repo as the API code?

: Yes, colocating tests with the API code encourages developers to run them before every commit.

What is the difference between unit and integration tests for APIs?

: Unit tests test individual functions; integration tests test the full request-response cycle against a running server.

How often should API tests run?

: Every commit via CI/CD pipeline. Slow performance tests can run nightly or before releases.

What tools are commonly used for API testing?

: pytest, supertest (Node.js), Postman/Newman, REST Assured (Java), and k6 or Locust for performance.

Mini Project

Build a test suite for a RESTful task management API covering: 5 functional tests (CRUD operations), 3 security tests (unauthenticated access, role-based access), and a locust performance test with 50 concurrent users.

What's Next

Review API monitoring strategies to detect issues in production, or explore API security patterns for preventing common vulnerabilities.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro