Auto-discover API endpoints in your source code and generate ready-to-run test suites.
npm · GitHub · Dev.to Article
Every API project needs endpoint tests. Writing them is tedious, repetitive, and error-prone: you copy-paste test files, update paths, remember which params go where, and hope you didn't miss a route. When the codebase changes, the tests fall behind.
endpoint-tester scans your source code, discovers every API endpoint automatically, and generates test suites that are ready to run. Point it at your project, get a complete test file in seconds.
Source code in --> [endpoint-tester] --> Test suite out
Express Vitest / Jest
Fastify Pytest
Koa
NestJS
FastAPI
Flask
Django
Spring Boot
- Auto-detection -- Detects your framework automatically from package.json, requirements.txt, pom.xml, or source imports. No config needed.
- 12 framework adapters -- Express.js, Fastify, Koa, NestJS, FastAPI, Flask, Django, Spring Boot, Gin, Echo, Chi, net/http. Extensible for any framework via the Adapter interface.
- 3 test formats -- Vitest, Jest, Pytest. Generated tests include status code assertions, auth header tests, error response tests, and boundary value tests.
- Smart route parsing -- Handles router prefixes, middleware chains,
app.route()chaining, multi-line decorators, class-level annotations, Blueprints, and more. - Zero config -- Works out of the box. One command, one output.
npm install -g endpoint-testerOr use without installing:
npx endpoint-tester scan ./src# Scan for endpoints (auto-detects framework)
endpoint-tester scan ./src
# Scan with explicit framework
endpoint-tester scan ./src --framework fastapi
# Generate test suite
endpoint-tester generate ./src --format vitest --output ./tests/api.test.ts
# Generate with custom base URL
endpoint-tester generate ./src --format jest --base-url http://localhost:8080Given an Express app:
// src/routes/users.ts
router.get('/users', listUsers);
router.post('/users', createUser);
router.get('/users/:id', getUser);
router.put('/users/:id', updateUser);
router.delete('/users/:id', deleteUser);Running endpoint-tester scan ./src outputs:
Auto-detected framework: express (high confidence)
Scanning ./src for express endpoints...
Found 5 endpoint(s):
GET /users
POST /users
GET /users/:id [params: id]
PUT /users/:id [params: id]
DELETE /users/:id [params: id]
Running endpoint-tester generate ./src --format vitest generates a complete test file with:
- Success tests with method-specific status codes (POST expects 201, DELETE expects 204, etc.)
- Auth header tests (Bearer token)
- Error response tests (missing body returns 4xx)
- Boundary value tests for path parameters (empty, negative, nonexistent)
| Option | Description | Default |
|---|---|---|
--framework / -f |
Framework adapter (express, fastapi, spring, django, flask, fastify, koa, nestjs, gin, echo, chi, nethttp). Auto-detected if omitted. | auto-detect |
--output / -o |
Output path -- directory or file path | ./generated-tests |
--format |
Test format (vitest, jest, pytest) | vitest |
--base-url |
Base URL for test requests | http://localhost:3000 |
| Framework | Patterns detected |
|---|---|
| Express.js | app.get(), router.post(), app.route().get().post(), route params, router prefixes via app.use() and router.use(), middleware chains |
| Fastify | fastify.get(), fastify.route({ method, url, handler }), shorthand method registrations |
| Koa | @koa/router with router.get() / router.post(), route params, router.prefix() |
| NestJS | @Controller('prefix') + method decorators (@Get, @Post, ...), @Param, @Query, @Body DTO inference |
| FastAPI | @app.get(), @router.post(), APIRouter prefixes, {param} parameters, multi-line decorators with kwargs |
| Flask | @app.route() with methods list, @app.get() shorthand, Blueprint url_prefix, typed parameters (<int:id>) |
| Django | path(), re_path(), typed parameters (<int:pk>), regex named groups |
| Spring Boot | @GetMapping, @PostMapping, @RequestMapping (both argument orderings), class-level @RequestMapping prefix, @PathVariable, multiline annotations, Kotlin fun syntax |
| Gin | r.GET(), r.POST(), router.Group() prefixes, route params (:id), gin.Default() and gin.New() |
| Echo | e.GET(), e.POST(), e.Group() prefixes, route params (:id), echo.New() |
| Chi | r.Get(), r.Post(), r.Route(), r.Mount() prefixes, route params ({id}) |
| net/http | http.HandleFunc(), mux.HandleFunc(), http.Handle(), route params (custom patterns) |
| Vitest | Jest | Pytest | |
|---|---|---|---|
| Imports | import { describe, it, expect } |
Uses globals (no import) | import requests |
| File | .ts |
.ts |
.py |
| Assertions | expect(response.status).toBe(201) |
Same | assert response.status_code == 201 |
All formats generate:
- Method-specific status code assertions (GET -> 200, POST -> 201, DELETE -> 204)
- Auth header tests with Bearer token
- Error response tests for body-accepting endpoints
- Boundary value tests for path parameters
import { Scanner, TestGenerator, getAdapter, detectFramework } from "endpoint-tester";
// Auto-detect the framework
const detected = await detectFramework("./src");
if (!detected) throw new Error("Could not detect framework");
const adapter = getAdapter(detected.framework);
// Scan for endpoints
const scanner = new Scanner(adapter);
const endpoints = await scanner.scan({ directory: "./src", framework: detected.framework });
// Generate tests
const generator = new TestGenerator();
const tests = generator.generate({
endpoints,
output: "./tests",
format: "vitest",
baseUrl: "http://localhost:3000",
});Implement the Adapter interface to add support for any framework:
import { Adapter, Endpoint, Framework, registerAdapter } from "endpoint-tester";
class HonoAdapter implements Adapter {
framework = "hono" as Framework;
fileExtensions = [".ts", ".js"];
parse(source: string, filePath?: string): Endpoint[] {
// Your parsing logic here
return [];
}
}
registerAdapter(new HonoAdapter());| endpoint-tester | Writing tests manually | Postman export | |
|---|---|---|---|
| Setup time | 0 (auto-detects) | N/A | Import collection |
| Keeps up with code | Re-scan anytime | Manual updates | Re-export |
| Boundary tests | Automatic | Write each one | Manual |
| Auth tests | Automatic | Write each one | Configure per request |
| Multi-framework | 8 built-in | N/A | Framework-agnostic |
| CI friendly | CLI output | Already in repo | Needs Newman |
- Node.js >= 20
- npm
git clone https://github.com/leopechnicki/endpoint-tester.git
cd endpoint-tester
npm installnpm run build # Compile TypeScript to dist/
npm test # Run tests with vitest
npm run lint # Lint with ESLint
npm run dev # Watch mode (tsc --watch)Install as a dependency:
npm install endpoint-testerImport types and classes:
import {
Scanner,
TestGenerator,
getAdapter,
registerAdapter,
detectFramework,
Framework,
type Adapter,
type Endpoint,
type EndpointParam,
type EndpointBody,
type HttpMethod,
type ScanOptions,
type GenerateOptions,
} from "endpoint-tester";Contributions are welcome. Areas with the most impact:
- New framework adapters (Hono, Gin, Actix, Laravel, etc.)
- Smarter body inference from type annotations
- OpenAPI/Swagger output format
- Watch mode for continuous test generation
Commit messages follow Conventional Commits
(feat:, fix:, chore:, ...). Releases are cut automatically by
release-please
based on the commit history.
MIT