Resource library

QA How-To

Schemathesis vs Dredd API Contract Testing (2026)

A practical guide to schemathesis vs dredd api contract testing with runnable examples, CI patterns, limitations, migration advice, and a 2026 verdict.

18 min read | 2,857 words

TL;DR

Schemathesis is the default choice for new API contract-testing work in 2026 because it supports current OpenAPI versions, generates positive and negative cases, shrinks failures, and remains actively documented. Dredd still fits stable API Blueprint or OpenAPI 2 suites that rely on deterministic examples and mature hooks, but its archived codebase makes it a legacy choice.

Key Takeaways

  • Choose Schemathesis for actively maintained, generative testing against modern OpenAPI or GraphQL schemas.
  • Keep Dredd only when an existing API Blueprint or OpenAPI 2 workflow depends on its deterministic transactions and hooks.
  • Use the same OpenAPI 2 document for a fair side-by-side trial because both tools can consume it reliably.
  • Treat Dredd examples as curated scenarios and Schemathesis cases as systematic exploration of the schema's input space.
  • Pin Dredd 14.1.0 and plan migration because its upstream repository has been archived since November 2024.
  • Run a small deterministic contract gate on each pull request and broader generative testing on a schedule.

For schemathesis vs dredd api contract testing in 2026, choose Schemathesis for a new project and retain Dredd only when you already own a stable API Blueprint or OpenAPI 2 suite. Schemathesis turns a schema into many generated positive, negative, and stateful cases. Dredd compiles documented examples into predictable HTTP transactions and validates the observed responses.

That distinction matters more than syntax. Schemathesis searches an input space and reduces a discovered failure to a useful reproducer. Dredd checks whether selected documented conversations still work. This guide makes both tools exercise the same small API, exposes a defect that an example-only run misses, and shows a migration-safe CI design. For the broader testing model, read the API contract testing guide before deciding where these runners belong in your test pyramid.

TL;DR

Decision signal Schemathesis Dredd
Best 2026 use New schema-driven test automation Maintaining an established legacy suite
Test generation Property-based positive, negative, coverage, fuzzing, and stateful phases Transactions compiled from examples in the API description
Reliable schema scope OpenAPI 2.0, 3.0, 3.1, 3.2, plus GraphQL API Blueprint and OpenAPI 2; OpenAPI 3 support was experimental
Failure diagnosis Minimal generated reproducer, typically including a curl command Named transaction with expected and actual response details
Customization CLI configuration, hooks, checks, Python API, pytest integration Lifecycle hooks that can change requests, fixtures, or validation
Maintenance signal Active documentation and releases Upstream repository archived in November 2024
Default verdict Adopt for modern contracts Freeze, pin, and migrate deliberately

Dredd is not useless because it is old. A deterministic suite with clear examples can provide fast release feedback. The problem is strategic: a new dependency should have a credible path for modern specifications, runtime compatibility, security fixes, and evolving CI platforms. Schemathesis has that path; Dredd no longer has an active upstream project.

What You Will Build

You will create one Express service and one OpenAPI 2 contract that both runners understand. The service manages widgets through GET /widgets/{id} and POST /widgets. Its first implementation deliberately accepts an empty widget name even though the contract requires at least one character.

By the end, you will have:

  • A runnable local API with one seeded widget.
  • A shared openapi.yaml contract with request and response schemas.
  • A deterministic Dredd run and a JavaScript hook.
  • A generative Schemathesis run that tests positive and negative data.
  • A fixed implementation and CI jobs for both migration and long-term use.

Use a disposable directory for the tutorial. The commands assume a POSIX shell on macOS or Linux; PowerShell users can create the same files and run the Node commands unchanged.

Prerequisites

Install Node.js 22 or newer, npm, curl, and uv. The uvx command runs the current Schemathesis package in an isolated environment, so Python package state does not leak into the service repository. Dredd is pinned locally to its final published release, 14.1.0, rather than fetched implicitly on every CI run.

node --version
npm --version
uvx schemathesis --version
curl --version

Verify that each command prints a version and exits with status 0. If uvx is unavailable, install uv using its official platform instructions. Avoid a global Dredd installation because an unpinned global tool makes build reproduction harder.

Create the project and install its runtime and legacy test dependency:

mkdir contract-runner-lab
cd contract-runner-lab
npm init -y
npm install express@5
npm install --save-dev dredd@14.1.0
npx dredd --version

The final command should report 14.1.0. npm may report advisories inherited from Dredd's frozen dependency tree. Do not silence that signal. Record it as part of the migration case, and never expose this tutorial service to the public internet.

Step 1: Build the API Under Test

Create app.js with the following complete service. The Map keeps the example self-contained. The intentional defect is in isWidget: it confirms that name is a string but fails to enforce the contract's minimum length.

const express = require('express');

const app = express();
app.use(express.json());

const widgets = new Map([[1, { id: 1, name: 'starter', quantity: 2 }]]);
let nextId = 2;

function isWidget(value) {
  return (
    value !== null &&
    typeof value === 'object' &&
    Object.keys(value).every((key) => key === 'name' || key === 'quantity') &&
    typeof value.name === 'string' &&
    Number.isInteger(value.quantity) &&
    value.quantity >= 1 &&
    value.quantity <= 100
  );
}

app.get('/widgets/:id', (req, res) => {
  const widget = widgets.get(Number(req.params.id));
  if (!widget) {
    return res.status(404).json({ message: 'Widget not found' });
  }
  return res.status(200).json(widget);
});

app.post('/widgets', (req, res) => {
  if (!isWidget(req.body)) {
    return res.status(400).json({ message: 'Invalid widget' });
  }
  const widget = { id: nextId++, ...req.body };
  widgets.set(widget.id, widget);
  return res.status(201).json(widget);
});

app.listen(4010, '127.0.0.1', () => {
  console.log('Widget API listening on http://127.0.0.1:4010');
});

Start it in a dedicated terminal:

node app.js

Verify the seeded happy path from another terminal:

curl -i http://127.0.0.1:4010/widgets/1

Expect HTTP 200 and a JSON body shaped like {"id":1,"name":"starter","quantity":2}. Keep the server running for every later step. A connection refusal means the process stopped or port 4010 is occupied; change the port in both app.js and the commands if necessary.

Step 2: Define One Contract for Both Tools

Create openapi.yaml. OpenAPI 2 is intentional: Schemathesis supports it, and it is Dredd's dependable OpenAPI format. This avoids giving either runner a different source document. The x-example value supplies Dredd with a concrete path parameter, while schema.example supplies a valid request body.

swagger: '2.0'
info:
  title: Widget API
  version: '1.0.0'
host: 127.0.0.1:4010
basePath: /
schemes:
  - http
consumes:
  - application/json
produces:
  - application/json
paths:
  /widgets/{id}:
    get:
      operationId: getWidget
      parameters:
        - name: id
          in: path
          required: true
          type: integer
          minimum: 1
          maximum: 1
          x-example: 1
      responses:
        '200':
          description: Existing widget
          schema:
            $ref: '#/definitions/Widget'
        '404':
          description: Widget does not exist
          schema:
            $ref: '#/definitions/Error'
  /widgets:
    post:
      operationId: createWidget
      parameters:
        - name: widget
          in: body
          required: true
          schema:
            $ref: '#/definitions/CreateWidget'
      responses:
        '201':
          description: Widget created
          schema:
            $ref: '#/definitions/Widget'
        '400':
          description: Invalid widget
          schema:
            $ref: '#/definitions/Error'
definitions:
  CreateWidget:
    type: object
    additionalProperties: false
    required:
      - name
      - quantity
    properties:
      name:
        type: string
        minLength: 1
      quantity:
        type: integer
        minimum: 1
        maximum: 100
    example:
      name: cable
      quantity: 2
  Widget:
    type: object
    additionalProperties: false
    required:
      - id
      - name
      - quantity
    properties:
      id:
        type: integer
        minimum: 1
      name:
        type: string
        minLength: 1
      quantity:
        type: integer
        minimum: 1
        maximum: 100
  Error:
    type: object
    required:
      - message
    properties:
      message:
        type: string

Verify that the contract and the API agree on the documented example:

curl -i -X POST http://127.0.0.1:4010/widgets -H 'Content-Type: application/json' -d '{"name":"cable","quantity":2}'

Expect HTTP 201 with a positive integer id, the name cable, and quantity 2. If parsing fails, check YAML indentation and confirm the $ref values remain literal strings. For a deeper explanation of response constraints, see OpenAPI schema testing and REST Assured JSON Schema validation.

Step 3: Run Dredd's Example Transactions

First ask Dredd to compile and list transaction names without sending requests. This separates a description problem from an API behavior problem.

npx dredd openapi.yaml http://127.0.0.1:4010 --names

Verify that the output contains transactions for GET /widgets/{id} and POST /widgets. Dredd may list non-2xx OpenAPI 2 responses as skipped. Its documented default behavior focuses on 2xx response transactions, which is one reason a 400 response in the description does not equal comprehensive negative testing.

Now execute the requests:

npx dredd openapi.yaml http://127.0.0.1:4010 --details

The 200 GET and 201 POST transactions should pass. Dredd obtains id: 1 from x-example and the POST body from the schema example, sends those fixed cases, then compares status, headers, and body structure with generated expectations. It does not infer that every valid or invalid widget name needs exploration.

That behavior is valuable when examples are deliberate acceptance scenarios. A documentation team can review exactly which request is sent. A build failure maps to a stable transaction name. It is weaker when the risk lies between examples, such as boundary values, optional combinations, Unicode, numeric limits, or omitted fields. Add examples manually and the suite grows, but test selection remains authored rather than generative.

Step 4: Add a Dredd Hook Without Hiding the Contract

Dredd hooks can prepare fixtures, attach credentials, alter a transaction, or add validation. Create dredd-hooks.js to add a test-only header to every request and log the observed status after every transaction.

const hooks = require('hooks');

hooks.beforeEach((transaction) => {
  transaction.request.headers['X-Contract-Runner'] = 'dredd';
});

hooks.afterEach((transaction) => {
  hooks.log(`${transaction.request.method} ${transaction.fullPath} -> ${transaction.real.statusCode}`);
});

Run Dredd with the hook file:

npx dredd openapi.yaml http://127.0.0.1:4010 --hookfiles=./dredd-hooks.js

Verify that the run passes and its logs identify executed methods and paths. JavaScript hooks work in-process; other supported hook languages use handlers. In a legacy suite, inspect hooks before trusting the contract because a hook can rewrite a body, URL, expected response, or skip flag. Excessive mutation can turn the schema into a misleading shell around imperative tests.

Use hooks for state that cannot live in the public contract, such as fetching a short-lived token or resetting a fixture. Keep structural expectations in OpenAPI. If the hook contains dozens of endpoint-specific branches, migrate those cases into focused integration tests or richer schema constraints instead of rebuilding an entire test framework inside lifecycle callbacks.

Step 5: Run Schemathesis as a Property-Based Contract Tester

Point Schemathesis at the same file and base URL. Select positive and negative generation, keep all normal checks enabled, and cap the fuzzing work so the local run finishes quickly.

uvx schemathesis run openapi.yaml --url http://127.0.0.1:4010 --mode all --max-examples 100 --continue-on-failure

Verify that Schemathesis collects getWidget and createWidget. The run executes examples and coverage cases, then property-based fuzzing according to the enabled phases. It checks server errors, documented status codes, response content types, headers, response schemas, positive acceptance, and negative rejection unless configuration disables a check. Exact case counts and generated values can vary, so assert the exit code and named findings rather than snapshotting decorative console output.

Schemathesis should expose that the service can return 201 for a body whose name is empty. Its failure output normally includes a reduced request and a reproduction command. Reduction is crucial: instead of handing a developer a large random payload, the runner searches for a simpler case that preserves the failure.

Confirm the defect independently:

curl -i -X POST http://127.0.0.1:4010/widgets -H 'Content-Type: application/json' -d '{"name":"","quantity":1}'

The buggy implementation returns 201 even though minLength: 1 makes that request invalid. If a particular generated run does not select the empty-string case, the direct curl still proves the mismatch; increase --max-examples, use --seed to reproduce a known campaign, or retain the discovered crash for st replay. This is the practical difference between checking chosen examples and searching constraints.

Step 6: Fix the Boundary and Prove the Result

Change only the name condition inside isWidget so the service enforces the declared minimum length.

function isWidget(value) {
  return (
    value !== null &&
    typeof value === 'object' &&
    Object.keys(value).every((key) => key === 'name' || key === 'quantity') &&
    typeof value.name === 'string' &&
    value.name.length >= 1 &&
    Number.isInteger(value.quantity) &&
    value.quantity >= 1 &&
    value.quantity <= 100
  );
}

Stop the running server with Ctrl+C, restart it with node app.js, and verify the exact regression first:

curl -i -X POST http://127.0.0.1:4010/widgets -H 'Content-Type: application/json' -d '{"name":"","quantity":1}'

Expect HTTP 400 and the JSON body {"message":"Invalid widget"}. Then repeat the broader tests:

npx dredd openapi.yaml http://127.0.0.1:4010 --hookfiles=./dredd-hooks.js
uvx schemathesis run openapi.yaml --url http://127.0.0.1:4010 --mode all --max-examples 100

Both commands should exit 0. Dredd proves its curated examples still work after the code change. Schemathesis samples the allowed and disallowed spaces again, checking that the newly enforced boundary does not break valid bodies. Neither result proves the API has no defects. It proves the configured properties held for this run against this environment.

Do not fix a generated failure by weakening the schema unless the contract was genuinely wrong. Decide which side owns the truth: if empty names are allowed, remove minLength through normal API review and update consumers; if they are forbidden, correct the implementation. Silent schema relaxation converts a useful test into contract drift.

Step 7: Put the Right Work in CI

During migration, run Dredd and Schemathesis as separate jobs so reviewers can see which safety net failed. Start the service in the background, wait until it answers, execute the runner, and always stop the process. This GitHub Actions job shows the Schemathesis path without assuming a global Python installation.

name: api-contract
on:
  pull_request:
  push:
    branches: [main]
jobs:
  schemathesis:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - uses: actions/setup-node@v6
        with:
          node-version: 22
          cache: npm
      - uses: astral-sh/setup-uv@v9
      - run: npm ci
      - run: |
          node app.js > server.log 2>&1 &
          echo $! > server.pid
      - run: |
          for attempt in {1..20}; do
            curl --fail --silent http://127.0.0.1:4010/widgets/1 && exit 0
            sleep 1
          done
          exit 1
      - run: uvx schemathesis run openapi.yaml --url http://127.0.0.1:4010 --mode all --max-examples 100 --report junit
      - name: Stop API
        if: always()
        run: |
          if [ -f server.pid ]; then kill "$(cat server.pid)" || true; fi
      - uses: actions/upload-artifact@v7
        if: always()
        with:
          name: schemathesis-report
          path: schemathesis-report/

Verification is the workflow result plus an uploaded JUnit artifact. For a legacy Dredd job, replace the final runner command with npx dredd openapi.yaml http://127.0.0.1:4010 --hookfiles=./dredd-hooks.js --reporter=xunit --output=./dredd.xml and upload that file. Pin action majors and dependencies under your organization's update policy. Never run unrestricted generative traffic against production; use an isolated environment, test tenant, rate limits, and disposable data.

8. How to Read Schemathesis vs Dredd API Contract Testing Failures

A Dredd failure starts with a named compiled transaction. Ask whether the example, endpoint URL, expected status, content type, or response shape is wrong. Then inspect hooks because they may have changed the request or expectation after compilation. --details, --inline-errors, --names, and --dry-run narrow that investigation.

A Schemathesis finding starts with a violated check and generated case. Run the emitted reproducer, preserve the seed or crash file, and classify the issue as implementation defect, schema defect, test-data collision, authentication problem, or environmental instability. Use st replay for recorded failures rather than waiting for random generation to rediscover them.

Both tools can reveal contract drift, but the evidence differs. Dredd answers, 'Did this described transaction behave as documented?' Schemathesis answers, 'Did the tested responses preserve these schema-derived properties over generated inputs and sequences?' That is why teams sometimes run curated smoke examples and generative exploration together even after retiring Dredd. The curated layer can be implemented with ordinary API tests, including OpenAPI contract testing with Playwright and TypeScript, while Schemathesis supplies broad exploration.

Which Should You Choose: Schemathesis vs Dredd API Contract Testing

Choose Schemathesis when you are starting fresh, your source contract is OpenAPI 3.x, you need GraphQL coverage, or bugs tend to hide in validation boundaries. It also fits teams that want reproducible generated failures, negative cases, response-schema checks, and optional stateful exploration without authoring a separate case for every value. Pair it with a few hand-written business workflows when the requirement involves money, authorization, or multi-service meaning that the schema cannot fully express.

Keep Dredd temporarily when API Blueprint is still authoritative, existing hook code encodes expensive fixture knowledge, and the suite is stable on a pinned runtime. Its predictable transaction list can remain a useful characterization test during replacement. Put an owner and removal milestone on it. An archived runner should not quietly become permanent infrastructure simply because the last green build was convenient.

Do not introduce Dredd for a new OpenAPI 3 project. Experimental historical support is not a sound foundation in 2026, especially when the upstream repository is read-only. Converting a modern schema backward to OpenAPI 2 solely for the runner discards useful semantics and creates another artifact to synchronize.

A sensible migration is incremental: inventory Dredd transaction names, classify hooks, reproduce each critical example in the replacement layer, add Schemathesis on the canonical contract, compare failures for several releases, then remove Dredd from CI. If consumer-provider compatibility is the real need, compare this workflow with Pact API contract testing. Pact verifies consumer expectations; these schema-driven runners validate HTTP behavior against an API description.

Common Mistakes

  • Calling every schema check consumer-driven contract testing. An OpenAPI runner checks provider behavior against a shared description. It does not automatically prove that a particular consumer's assumptions remain compatible.
  • Comparing different contracts. Feeding OpenAPI 3.1 to Schemathesis and a manually downgraded OpenAPI 2 copy to Dredd mixes tool behavior with document drift. Use one compatible file for evaluation.
  • Assuming examples cover boundaries. A valid body with quantity 2 says nothing about 0, 1, 100, 101, missing fields, wrong types, or unexpected properties.
  • Treating generated traffic as harmless. POST, PATCH, and DELETE can mutate data repeatedly. Test an isolated service, cap concurrency, and reset fixtures.
  • Hiding failures with permissive schemas. If every property is optional and most responses lack schemas, a runner has little to enforce. Improve the contract instead of celebrating a green report.
  • Letting hooks replace design. Authentication and fixture setup belong in hooks; endpoint-specific response rules usually belong in the schema or focused tests.
  • Ignoring Dredd's archive status. Lockfile reproducibility does not deliver future security patches or compatibility updates. Track the risk openly.
  • Expecting one runner to cover business semantics. A response can match JSON Schema yet charge the wrong amount. Keep domain assertions in purpose-built integration tests.

Review how to choose API testing tools when assigning each risk to a layer. Tool count is not coverage; distinct, observable failure modes are coverage.

Troubleshooting

Dredd reports no usable request for a path parameter -> Add an OpenAPI 2 x-example to that non-body parameter. Confirm the compiled value with --names or --dry-run before executing the service.

Dredd installs but fails on a modern Node runtime -> Reproduce with the pinned 14.1.0 package in a locked container, then prioritize migration. Do not upgrade arbitrary transitive packages inside the archived tool and assume validation semantics stayed intact.

Schemathesis says the base URL is missing -> A local schema file cannot supply a reachable environment in every setup. Pass --url http://127.0.0.1:4010, matching the current CLI.

Generated cases damage shared test data -> Use an isolated database or tenant, seed it before the run, and restore it afterward. Exclude destructive operations only as a temporary safeguard because exclusion leaves a real coverage gap.

The runner rejects valid responses as undocumented -> Check the actual status code and content type first. Add legitimate alternatives to the canonical contract through review; do not disable conformance checks globally.

A Schemathesis failure will not recur on a new run -> Execute the printed reproducer or use st replay with the recorded crash. Preserve CI artifacts and the schema revision so the case is diagnosable after the branch changes.

Interview Questions and Answers

Strong interview answers distinguish deterministic example execution from property-based generation, explain why an archived dependency changes a 2026 recommendation, and describe how to reproduce a generated defect before changing code. The structured Q&A below covers schema scope, negative testing, shrinking, hooks, CI safety, and migration. Practice explaining the widget boundary defect aloud in the QA interview practice workspace, focusing on evidence rather than tool popularity.

Where To Go Next

Start by running Schemathesis against a non-production environment with the canonical schema and a low request budget. Triage every finding instead of immediately suppressing checks. Strengthen missing constraints, make authentication explicit, and add examples that convey important business scenarios. The API testing roadmap can help place this work beside exploratory, integration, security, and performance testing.

If your team already uses Dredd, export its transaction names and map each one to a replacement owner. Preserve business-critical examples as hand-written smoke tests, use Schemathesis for schema-derived exploration, and retire hook branches only after their fixture or assertion purpose is covered elsewhere. Teams designing consumer guarantees should continue with API contract testing with Pact, not assume OpenAPI alone models every client dependency.

Conclusion

The 2026 verdict is clear: Schemathesis is the stronger default because it supports modern schemas, explores inputs beyond examples, produces reduced reproducers, and has an active path forward. Dredd remains understandable in a pinned legacy workflow, but its archived upstream and older specification center make adoption a poor new investment.

Run both against one shared contract if you need migration evidence. Keep Dredd's deterministic cases until replacements prove equivalent, then let Schemathesis and focused business tests divide the work according to the risks each can actually observe.

Interview Questions and Answers

What is the core difference between Schemathesis and Dredd?

Schemathesis derives many test cases from schema constraints using property-based generation and checks general response properties. Dredd compiles concrete examples from an API description into named HTTP transactions and validates actual responses against their expectations. I would describe the first as exploration of a contract-defined input space and the second as deterministic execution of documented conversations.

Why would you choose Schemathesis for a new API project in 2026?

It supports modern OpenAPI versions and GraphQL, exercises positive and negative data, reduces failing inputs, and integrates with current CI reporting. Its active project status also matters for runtime compatibility and security maintenance. I would still add focused domain tests because schema conformance cannot prove business correctness.

When can keeping Dredd still be reasonable?

Keeping it can be reasonable when a stable API Blueprint or OpenAPI 2 suite already provides useful release evidence and hooks contain costly fixture setup. I would pin Dredd 14.1.0, isolate its runtime, document the archived-upstream risk, and create a phased replacement plan. I would not expand it as the default framework for new endpoints.

How do you make a fair Schemathesis versus Dredd evaluation?

Use the same reachable service, schema revision, credentials, and compatible OpenAPI 2 file. Separate deterministic examples from generated coverage, record which defect class each runner detects, and compare diagnosis quality and operational cost rather than raw request counts. Different source contracts would invalidate the comparison.

What is shrinking in property-based API testing?

After finding a failing generated request, the engine searches for a simpler input that still triggers the failure. A small reproducer, such as an empty string rather than a complex random payload, makes root-cause analysis and regression testing easier. The reduced case should be replayed against the same schema and service revision before a fix is accepted.

How would you migrate an archived Dredd suite?

I would export transaction names, classify hooks by authentication, fixtures, state transfer, mutation, and custom assertion, then identify the business risk behind each. I would run Schemathesis against the canonical contract and recreate critical curated scenarios in a maintained integration framework. After parallel CI runs show equivalent protection, I would remove Dredd and its pinned runtime.

What are the main CI safety controls for generative API testing?

Use an isolated environment, least-privilege credentials, disposable fixtures, request and time limits, and explicit control over destructive operations. Preserve the schema, seed, crash files, and reports so failures can be reproduced. Production endpoints should not receive unrestricted generated mutations.

Frequently Asked Questions

Is Schemathesis better than Dredd for API contract testing in 2026?

Yes for most new projects. Schemathesis supports current OpenAPI versions and GraphQL, generates positive and negative cases, shrinks failures, and remains actively developed, while Dredd's upstream repository is archived.

Can Schemathesis and Dredd test the same OpenAPI file?

Yes, if the shared document uses a format both reliably support, with OpenAPI 2 being the safest common choice. This is useful for migration evaluation, but a modern OpenAPI 3 contract should not be downgraded permanently just to retain Dredd.

Does Dredd support OpenAPI 3?

Dredd's repository described OpenAPI 3 support as experimental, while its established documentation and workflows center on API Blueprint and OpenAPI 2. Because the repository was archived in 2024, do not choose Dredd as the foundation for a new OpenAPI 3 suite.

What kinds of bugs does Schemathesis find that Dredd may miss?

Schemathesis explores schema boundaries, invalid types, missing or extra fields, status-code conformance, response schemas, and sequences when configured for those phases. Dredd usually executes concrete examples, so an unrepresented boundary can remain untouched.

Should an existing Dredd suite be deleted immediately?

No. Freeze its versions, inventory transactions and hooks, add the replacement runner alongside it, and compare results over several releases. Remove each legacy case only after its business purpose and fixtures are covered elsewhere.

Is OpenAPI schema testing the same as consumer-driven contract testing?

No. Schema testing validates provider HTTP behavior against an API description, while consumer-driven testing verifies expectations contributed by specific consumers. A team may need both because they answer different compatibility questions.

Can Schemathesis run safely against production?

Generative tests can send unexpected values and mutate resources, so production is a poor default target. Prefer an isolated environment with disposable data, scoped credentials, explicit rate limits, and exclusions reviewed as known coverage gaps.

Related Guides