Early access The free plan is live — unlimited tests, no card, yours to keep Get started →
Resources

API testing: what it can and cannot tell you

Testing the layer under the interface: what it is good at, what it cannot tell you, and the tools worth knowing.

8 resources4 from official documentationTools

An API test skips the browser. That single fact accounts for both its advantages — it is faster by an order of magnitude, it fails for exactly one reason, and it can assert on things a page never displays — and its limitation, which is that a perfectly correct API tells you nothing about whether anyone can use the product.

The browserrendering, clicks, layout — the part a customer touchesThe HTTP APIstatus codes, payload shape, auth, error handlingStatewhat survives the request: rows, queues, filesUI testslow, broadAPI testfast, exact
The same system, two kinds of coverage. Neither replaces the other; one is much cheaper per assertion.

The most valuable use of an API in a browser suite is not testing it at all. It is arriving at the state a test needs. Creating an order through fourteen UI steps tests the order-creation journey once and then pays for it in every test that needs an order to exist. Creating it with one HTTP call, and testing the journey in the one test that is about the journey, is usually the largest single speed-up available to a mature suite.

import { test, expect } from '@playwright/test';

// Arrange over HTTP, act in the browser. The setup costs milliseconds
// and cannot fail for a reason that has nothing to do with this test.
test('an existing order can be cancelled', async ({ page, request }) => {
  const created = await request.post('/api/orders', {
    data: { sku: 'ESP-01', qty: 1 },
  });
  await expect(created).toBeOK();
  const { id } = await created.json();

  await page.goto(`/orders/${id}`);
  await page.getByRole('button', { name: 'Cancel order' }).click();
  await expect(page.getByText('Order cancelled')).toBeVisible();
});
The request fixture shares the browser's cookies, so an authenticated session works for both halves.
An API test is not a contract test

Asserting that your service returns the shape you expect proves your service agrees with your test. It does not prove it agrees with its consumers, who wrote their own expectations somewhere you cannot see. That is what contract testing is for, and it is a different tool.

Inside the browser test runner

2 entries
  1. Issue requests with or without the browser's session, assert on responses, and use HTTP for setup and teardown. Includes the standalone request context, for tests with no page at all.

    playwright.dev
  2. Intercept what the page requests, stub a response, modify one in flight, or record a session and replay it. The reliable way to test the error state your staging backend refuses to produce.

    playwright.dev

Dedicated tools

4 entries
  1. The fundamentals, explained clearly: requests, environments, collections, assertions, and running a collection in a pipeline. Even if you end up somewhere else, the vocabulary here is the industry's.

    learning.postman.com
  2. Bruno

    Tool

    An open-source API client that stores collections as plain files in your repository rather than in a vendor's cloud. Worth knowing about if “our API tests live in someone's personal workspace” is a sentence you have said out loud.

    docs.usebruno.com
  3. The long-standing Java DSL for HTTP tests, with a given/when/then shape that reads well in a report. Still the default in most JVM shops.

    rest-assured.io
  4. Generates test cases from an OpenAPI or GraphQL schema and throws them at your service, including the inputs nobody writes by hand. Property-based testing for APIs, and it finds 500s in almost every service it is pointed at.

    schemathesis.readthedocs.io

Contracts and specifications

2 entries
  1. The document your API should already have. Once it exists it stops being documentation and starts being something tools can generate clients, mocks and test cases from.

    spec.openapis.org
  2. The consumer records what it actually depends on; the provider proves it still supplies it. The answer to integration-testing a system whose services deploy independently, without standing the whole thing up.

    docs.pact.io

What to take away

  • Arrange over HTTP, act in the browser.Usually the largest available speed-up, and it removes a whole class of unrelated failures from every test.
  • Fast and exact is not the same as sufficient.A green API suite over a broken interface is a real and common outcome.
  • Mock the backend you cannot make misbehave.A tested error state beats an untested one, and route interception is not cheating.
Missing something? If there is a resource you send to every new tester on your team, tell us and we will read it. The list stays short on purpose; each entry has to earn its place, and entries that stop earning it get removed rather than left to rot.

Reading is the slow way to learn how a suite behaves. Record one against your own app, free, and watch what the report says.

Get started free See how it works