Traditional scripts share database states, hardcode tokens, and leak data. TDS mandates strict isolation and dynamic verification.
Tests must never assume existing data. Every test creates its own entities (e.g. creating a test product in setup) and processes them in isolation. This allows 1,000+ tests to run concurrently without colliding or generating duplicate primary keys.
No hardcoded values. If Test B requires an ID generated by Test A, the system chains them dynamically. The output of POST /orders is captured, parsed, and injected as the path parameter in GET /orders/{id} in real time.
Every write operation registers a corresponding cleanup transaction. Even if assertions fail mid-test, the runner executes teardown callbacks (e.g. deleting seeded users, charges, or product rows), keeping sandbox DBs entirely clean.
We assert more than just 200 OK. Every response undergoes strict schema verification. We validate performance latency budgets (e.g. response < 200ms), headers (e.g. correct content-types), and match body payloads against OpenAPI models.
TDS v1.0 is also our pricing honesty mechanism: because "one test" is publicly defined and auditable, coverage can't be padded and invoices can't be gamed.
Verifies exactly one behaviour of one endpoint. When it fails, you know precisely what broke — no forensic debugging sessions.
Creates its own data and cleans up after itself. Any test can run alone, in any order, on any of 1,000 parallel workers.
Same input, same result, every run. No random waits, no shared tokens, no "re-run it and see" — the root causes of flakiness are designed out.
Asserts a meaningful outcome — schema compliance, state change, latency budget — not just a 200 status code that hides real failures.
Traceable to a specific endpoint and scenario in your API surface — so coverage is a checklist you can audit, not a vibe.
Kept green as your API evolves — in-scope changes and self-healing are part of the service, not a change-request invoice.
Each endpoint typically carries 3–5 outcome tests: happy path, auth/permission, validation/error, and boundary — counted per the TDS conventions.
Toggle below to compare traditional, fragile Java test scripts with our isolation-hardened, schema-validated RestAssured code. By choosing Java & RestAssured, we guarantee a single unified test suite that can scale and grow across the web, mobile, and API layers (Playwright is still available on request).
// ❌ Flaky: relies on static database state & shared auth tokens
import org.testng.annotations.Test;
import static io.restassured.RestAssured.*;
import static org.hamcrest.Matchers.*;
public class FlakyApiTest {
// Hardcoded global authentication token
private static final String AUTH_TOKEN = "Bearer token_xyz_98765";
@Test
public void testGetOrder() {
given()
.header("Authorization", AUTH_TOKEN)
.when()
.get("https://api.staging.example.com/v1/orders/1205")
.then()
// ❌ Fragile: order 1205 can be deleted by other runs, causing random CI failures
.statusCode(200)
// ❌ Brittle: matches only static value, no schema contract check
.body("status", equalTo("pending"));
}
}
// TDS v1.0 Compliant: Isolated setup, Dynamic chaining & Cleanup
import org.testng.annotations.Test;
import static io.restassured.RestAssured.*;
import static io.restassured.module.jsv.JsonSchemaValidator.matchesJsonSchemaInClasspath;
import static org.hamcrest.Matchers.*;
import java.util.UUID;
public class TdsApiTest {
@Test
public void testIsolatedOrderWorkflow() {
// 1. Setup: Seed isolated customer authentication credentials
String uniqueId = UUID.randomUUID().toString();
String token = AuthUtils.generateTempToken("user_" + uniqueId);
// 2. Setup: Seed isolated product context to isolate order inventory
String productId = ProductUtils.createProduct("Widget_" + uniqueId, 49.99);
// 3. Chaining: Pass runtime product_id & Auth header into POST /orders
Response orderRes = given()
.header("Authorization", "Bearer " + token)
.contentType("application/json")
.body(Map.of("product_id", productId, "quantity", 1))
.when()
.post("/v1/orders");
// 4. Contract validation: check latency, response code, and schema compliance
orderRes.then()
.statusCode(201)
.time(lessThan(250L)) // SLA latency check
.body("id", notNullValue())
.body(matchesJsonSchemaInClasspath("order-schema.json")); // Schema check
String orderId = orderRes.path("id");
// 5. Teardown: Register cleanups so DB state remains untouched on failure
TearDownManager.registerCleanup(() -> {
given().header("Authorization", "Bearer " + token).delete("/v1/orders/" + orderId);
ProductUtils.deleteProduct(productId);
});
}
}