@versatechnology/pestcontrol
v0.2.0
Published
Open-source AI test generation — discovers your app, writes committable tests INTO your repo (pytest/Playwright/Flutter), runs them, and triages failures. Works across stacks: REST (OpenAPI), web + React Native (live-DOM), Flutter.
Maintainers
Readme
PestControl
Open-source AI testing agent. It reads your code, generates tests, runs them against your running
app, triages the failures, and writes the tests into your repo — plain pytest / Playwright /
Flutter integration_test, no vendor lock-in. The generator + local runner are open source and
bring-your-own-Anthropic-key; a hosted cloud (parallel execution, localhost tunnels, dashboard, CI
gating) is the paid layer.
Status: local OSS engine, stack-agnostic by design. The trick to working across frameworks is to ground on the app's runtime self-description, not framework-specific source:
apigrounds on the app's OpenAPI spec →pytest+httpx(FastAPI, Express, NestJS, Spring, Flask, DRF, … — verified on FastAPI; source scan as fallback);webgrounds on the live rendered DOM → Playwright Python +pytest(any web framework, incl. client-rendered SPAs and React Native apps via Expo / react-native-web — theirtestIDs render as DOMdata-testids, verified inexamples/demo-rn-web); each web run captures a screenshot per test plus a video + Playwrighttrace.zipon failure into.pestcontrol/artifacts/, embedded/linked in the report;flutter→ Dartintegration_teston macOS. Native-only mobile (a Maestro/Detox runner on a simulator/emulator) is the next stack. Each generates committable tests, runs them live, and produces a triaged Markdown report.
📖 Full capabilities & usage guide → docs/GUIDE.md — every target, command, flag, and example.
Install
npm i -g @versatechnology/pestcontrol # then: pestcontrol run --repo <path> ...
# or run without installing:
npx @versatechnology/pestcontrol run --repo <path> --target web --base-url <url>Bring your own Anthropic key — set ANTHROPIC_API_KEY (in .env or the environment). The CI gate
(pestcontrol ci) needs no key. The examples below use the local build (node dist/cli.js); with a global
install substitute pestcontrol.
Try it on any URL (no repo needed)
npx @versatechnology/pestcontrol try https://your-app.example.comPoint it at any web app you own — including apps built with AI tools (Lovable, v0, Bolt). PestControl
sets up its own Python + browser the first time (one-time, a few minutes), walks the app, generates real
Playwright tests into ./pestcontrol-<host>/, runs them, and explains the results in plain English —
then opens the dashboard. It guides you through pasting an Anthropic key on first run (saved to
~/.pestcontrol/.env). Only run it against apps you own or have permission to test.
Add --deep to go beyond page/render checks: the agent performs and verifies real multi-step
workflows (search→open a result, navigate deep, even self-cleaning create→verify→delete) and commits the
verified ones as functional tests. --deep writes to the app, so it's opt-in and for your own apps only;
without it, runs never mutate.
Quick start (web demo, ~2 min)
A self-contained demo web app lives in examples/demo-web/. Dogfood the web adapter against it:
npm install && npm run build
# 1) serve the demo app
node examples/demo-web/serve.mjs 4321 &
# 2) one-time: a venv with Playwright for the demo to run its generated tests
python3 -m venv examples/demo-web/.venv_pestcontrol
examples/demo-web/.venv_pestcontrol/bin/pip install -q pytest-playwright
examples/demo-web/.venv_pestcontrol/bin/playwright install chromium
# 3) generate + run tests against the live demo (needs ANTHROPIC_API_KEY in .env)
node dist/cli.js run --repo examples/demo-web --target web \
--base-url http://127.0.0.1:4321 \
--email [email protected] --password demo1234You'll get examples/demo-web/pestcontrol_tests/test_web.py (grounded on the app's real locators) and a
report at examples/demo-web/.pestcontrol/report.md.
CLI
node dist/cli.js run --repo <path> [--target api|flutter|web] [--base-url <url>]
[--scope codebase|diff] [--base <git-ref>]
[--python <interpreter>] [--email <user>] [--password <pw>]--target is auto-detected when omitted (a confidence-scored registry: manage.py → api,
pubspec.yaml with flutter → flutter, a web framework / index.html → web).
Diff/PR scope — --scope diff tests only the surface a change touched: it reads the changed
files (via simple-git, --base <ref> to compare against e.g. main) plus each stack's structural
anchors (routes / entry HTML / pubspec), so a PR generates tests for exactly what it changed.
Requirements-driven planning — run --prd <file|dir> (or drop docs in .pestcontrol/prd/) normalizes your
requirements into a structured PRD (.pestcontrol/standard_prd.json) and traces generated test cases to those
requirements (shown in the report's requirement grouping). Without it, planning stays surface-only.
CI gate — run committed tests on PRs
generate (above) is the inner-loop half. The run half is a deterministic gate — no LLM, no API key:
node dist/cli.js ci --repo <path> [--target api|web|flutter] --base-url <preview-url> [--no-gate]It runs the tests already committed in the repo against --base-url (generated web/api tests read
PESTCONTROL_BASE_URL, so the same committed tests retarget to any PR preview URL), writes a PR-ready
.pestcontrol/ci-summary.md, and exits non-zero on failure to block merge (--no-gate to report only).
A ready-to-copy GitHub Actions workflow is in examples/github-actions/pestcontrol-ci.yml.
Dashboard — review a run, re-run, regenerate
pestcontrol dashboard --repo <path> [--target] [--base-url <url>] [--python <p>] [--port 0] serves a local
web UI for the latest run: the requirement→test grid, each test's screenshot/video/trace, and the
triaged findings — plus re-run a single test (web/api) or all, and regenerate a test (web). No
account, zero extra dependencies, served straight from .pestcontrol/.
The run is one pipeline, the same for every stack:
discover surface → plan cases → generate tests (self-heal) → execute → triage failures → report- Grounded generation, the stack-agnostic way — discovery grounds on the app's runtime
self-description, so it generalizes across frameworks instead of parsing each one's source:
- api fetches the running app's OpenAPI (
/openapi.json,/api/schema/, …) and derives the surface deterministically — no LLM, any stack that publishes a spec. (examples/demo-api, a FastAPI app, is discovered with zero source parsing.) Falls back to a source scan when no spec is exposed. Discovery then probes the running app (login + read-only GETs) so plans are grounded on what actually exists — real resource ids, empty collections, working auth — instead of assumed data. Resource-dependent endpoints are tested as chained scenarios — create a resource, act on it (forwarding the returned id), assert, then best-effort clean it up — with shared module-scoped fixtures for resources multiple scenarios reuse. - web agentically explores the running app (Playwright): it logs in with the seeded creds and
clicks through the primary nav, grounding on the real rendered DOM of each state it reaches — so it
works on client-rendered SPAs whose source is a
<div id="root">shell, and reveals post-auth surfaces a static snapshot can't see.examples/demo-spamounts its dashboard only after login; the explorer logs in to find it and generates 8/8. The multi-page demo generates 9/9.
- api fetches the running app's OpenAPI (
- Self-heal ×3 — (1) a fast static gate at generate time (
flutter analyze/py_compile); (2) a build/collection-error repair at execute time (feed the build output back, regenerate, re-run once); and (3)pestcontrol fix— a bounded verify→heal→re-verify loop that surgically repairs brittle (false-positive) tests and re-runs until the suite converges, so every remaining failure is a real finding. - Triage — every failure is classified product_bug / test_fragility / environment /
contract_violation with a suggested fix (the brain of the self-repair loop). Each run also writes
.pestcontrol/report_prompt.json— a machine-readable fix bundle (per-failure triage + suggested fix + artifacts) a coding agent can apply directly.pestcontrol fixconsumes that triage to auto-heal thetest_fragilityfailures itself (editing only the generated test file), leaving real app findings for you.
Architecture — the TargetAdapter seam
The core orchestration is stack-agnostic. Supporting a new stack = implementing one interface and registering it; nothing else changes. This is the seam that lets PestControl grow without rewrites.
| Piece | What it does |
|---|---|
| src/adapters/types.ts | TargetAdapter<S,P> interface + shared types (RunResult, AdapterContext, …) |
| src/adapters/registry.ts | createRegistry + detectBest + runTarget (the generic 6-stage driver) |
| src/adapters/{api,flutter,web}-adapter.ts | the three target adapters (detect + the six stages) |
| src/{pipeline,flutter-pipeline,web-pipeline}.ts | each stack's stage functions (collect / discover / plan / codegen / run) |
| src/generation/llm.ts | Claude client: model routing (fast=Sonnet, frontier=Opus), structured output, retry |
| src/triage.ts, src/report.ts | shared failure triage + Markdown report — serve all three stacks unchanged |
| src/index.ts | MCP server (stdio) + next_action tool chain — adapter-driven, drives any registered target |
Develop
npm install
npm run build # tsup → dist/ (cli.js + the MCP binary index.js)
npm run typecheck # tsc --noEmit
npm test # vitest (registry, detectBest, per-adapter detect, build-failure predicate)ANTHROPIC_API_KEY in .env (BYO key). Point an IDE's MCP config at node /abs/path/dist/index.js.
The MCP server exposes: bootstrap → generate_code_summary → generate_standardized_prd →
generate_test_plan → generate_and_run → report → open_test_result_dashboard, plus
check_account_info. (Open-source, BYO Anthropic key — no account or credits.)
License: Apache-2.0.
