A simple tool for testing JSON/HTTP APIs
Project description
skivvy
Declarative integration testing for HTTP APIs.
Skivvy is a tiny, opinionated CLI tool that lets you write API tests as plain JSON files and run them from the terminal. No JS hooks. No GUI. No snapshots. You declare what you expect, and skivvy tells you if reality disagrees — with readable diffs when it does.
It works with REST, GraphQL, and anything else that speaks HTTP. It's built for CI/CD pipelines but just as useful on your local machine.
The core idea
Most API testing tools push you toward one of two bad patterns: writing imperative code in a language you didn't ask for, or snapshot-testing entire responses so every unrelated field change breaks your suite. Skivvy takes a different approach — assert only what you care about. Check the status code, a single field, a subset of a nested object, or the length of a list. Ignore the rest.
{ "url": "/api/items", "response": { "results": [{ "name": "Widget42" }] } }
That's it. That's a test.
This works especially well with deeply nested responses like GraphQL, where you can match subsets without caring about the full envelope:
{
"url": "/graphql",
"method": "post",
"body": { "query": "{ posts { id title author { name } tags } }" },
"match_subsets": true,
"match_every_entry": true,
"response": {
"errors": null,
"data": {
"posts": [{ "author": { "name": "$text" }, "tags": "$len_gt 0" }],
"totalCount": "$gt 0"
}
}
}
Every post must have a named author and at least one tag. No GraphQL errors. You don't have to spell out the full response shape.
Matchers can reach beyond string comparison — they can enforce constraints across entire collections:
{
"url": "/users/all",
"match_every_entry": true,
"response": {
"images": [{ "thumbnail": "$valid_url", "id": "$unique" }]
}
}
Every user's thumbnail is a live, reachable URL. Every ID is unique across the whole list. Two invariants over an arbitrarily large dataset, in a few lines of JSON.
What you get
- All the HTTP plumbing you'd expect — every verb, headers, cookies, file uploads, form data, response chaining via variables and brace expansion
- Subset matching — assert against deeply nested fields without specifying the full path
- Built-in matchers —
$contains,$regexp,$len,$gt,$between,$valid_url,$date,$store/$fetch, approximate values with$~, and more — plus automatic negation ($!contains) for all of them (full list) - Custom matchers — drop a Python file with a
match(expected, actual)function into a directory and it just works - Readable diffs — when a test fails, you see exactly what went wrong in a human-friendly format, with multiple diff styles to choose from
- Flexible configuration — per-test overrides, environment configs, CLI flags, env vars, with a clear precedence order and sane defaults (full list)
- Setup & teardown — use directory naming and include/exclude filters to control execution order
- Deterministic execution — serial by default, predictable every time
Check out the playground for trying it from the comfort of your browser. It provides a basic unix shell, and allows you to edit and run test suites that examplify the list above. It also contains a running server, with responses you can edit as well.
Install
uvx skivvy --version # no install needed with uv
pipx run skivvy --version # or pipx
pip install skivvy # or plain pip
docker run --rm hyrfilm/skivvy:examples # or docker
Reference
- Settings — all configuration options with defaults and descriptions
- Matchers — all built-in matchers with usage examples
- CLI help also includes
skivvy --help-settingsandskivvy --help-matchersif you want to explore available knobs before enabling more logging
MIT license.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file skivvy-0.811.tar.gz.
File metadata
- Download URL: skivvy-0.811.tar.gz
- Upload date:
- Size: 31.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
dc0a31a2183d1f9108d16dbed93a60c92a832d5e08f3d183efa79add3cdf7413
|
|
| MD5 |
564cc8b358f35e18bee41b9777d3e0aa
|
|
| BLAKE2b-256 |
ed8a43aebf355c9b231a1b97808871317e399de7504b4f9f81624f27de692f97
|
Provenance
The following attestation bundles were made for skivvy-0.811.tar.gz:
Publisher:
on-release.yml on hyrfilm/skivvy
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
skivvy-0.811.tar.gz -
Subject digest:
dc0a31a2183d1f9108d16dbed93a60c92a832d5e08f3d183efa79add3cdf7413 - Sigstore transparency entry: 1109561010
- Sigstore integration time:
-
Permalink:
hyrfilm/skivvy@8141599c1c4a69f5ffa311804d8f437242b3cdf1 -
Branch / Tag:
refs/tags/0.811 - Owner: https://github.com/hyrfilm
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
on-release.yml@8141599c1c4a69f5ffa311804d8f437242b3cdf1 -
Trigger Event:
release
-
Statement type:
File details
Details for the file skivvy-0.811-py3-none-any.whl.
File metadata
- Download URL: skivvy-0.811-py3-none-any.whl
- Upload date:
- Size: 37.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0da2b539655fb568fdab72812fab0cc19c8a321faf41350d1a325001ab189234
|
|
| MD5 |
40ba19362b27e559dd0d4495a1c05b38
|
|
| BLAKE2b-256 |
01360070a486ac2c64ff2bd6ed85a3835135328c1ca3e2816b61e95c3c6b73e3
|
Provenance
The following attestation bundles were made for skivvy-0.811-py3-none-any.whl:
Publisher:
on-release.yml on hyrfilm/skivvy
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
skivvy-0.811-py3-none-any.whl -
Subject digest:
0da2b539655fb568fdab72812fab0cc19c8a321faf41350d1a325001ab189234 - Sigstore transparency entry: 1109561022
- Sigstore integration time:
-
Permalink:
hyrfilm/skivvy@8141599c1c4a69f5ffa311804d8f437242b3cdf1 -
Branch / Tag:
refs/tags/0.811 - Owner: https://github.com/hyrfilm
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
on-release.yml@8141599c1c4a69f5ffa311804d8f437242b3cdf1 -
Trigger Event:
release
-
Statement type: