Three weeks ago I published the first version of endpoint-tester — a CLI that scans your source code, discovers API routes, and generates a ready-to-run test suite with zero configuration. The initial release shipped with Express.js as the fully working adapter plus scaffolded support for FastAPI and Spring Boot.
Today the tool supports 12 frameworks across four languages — and every one of them is fully implemented, not scaffolded.
Here's what changed, why it mattered, and how to use the new adapters.
The 12 frameworks
The adapter list is now:
| Language | Frameworks |
|---|---|
| Node.js | Express.js, Fastify, Koa, NestJS |
| Python | FastAPI, Flask, Django |
| Go | Gin, Echo, Chi, net/http |
| JVM | Spring Boot |
Auto-detection works for all of them. Point the tool at any project and it reads package.json, requirements.txt, go.mod, or pom.xml to pick the right adapter before it scans a single source file.
What the tool does (quick recap)
# Scan — discover every endpoint in your project
npx endpoint-tester scan ./src
# Generate — produce a ready-to-run test file
npx endpoint-tester generate ./src --format vitest --output ./tests/api.test.ts
The generated tests cover:
- Success assertions with method-correct status codes (POST → 201, DELETE → 204, GET → 200)
- Auth header tests (valid Bearer token, missing token, malformed token)
- Error response tests for body-accepting endpoints (missing required field, wrong type)
- Boundary value tests for path parameters (empty string, negative integer, nonexistent ID)
The new adapters in detail
Fastify
The Fastify adapter handles both shorthand registrations and the object-style fastify.route() call, which many Fastify projects mix together:
fastify.get('/users', listUsers);
fastify.route({ method: 'POST', url: '/users', handler: createUser });
Both forms produce identical output in the scan — the generated test doesn't care how the route was registered.
Koa
Koa's router prefix pattern tripped up earlier attempts at parsing because router.prefix('/api/v1') sits on a different line from the actual method registrations. The adapter resolves prefixes before emitting endpoints, so you get /api/v1/users rather than just /users:
const router = new Router();
router.prefix('/api/v1');
router.get('/users', listUsers);
router.post('/users', createUser);
NestJS
NestJS uses class-level controller decorators to define route prefixes. The adapter combines @Controller('users') with method decorators to reconstruct full paths, and it infers parameter names from @Param(), @Query(), and @Body() to improve boundary test generation:
@Controller('users')
export class UsersController {
@Get(':id')
findOne(@Param('id') id: string) { ... }
@Post()
create(@Body() createUserDto: CreateUserDto) { ... }
}
Go frameworks (Gin, Echo, Chi, net/http)
The Go adapters were the biggest addition. All three major Go HTTP routers use similar registration patterns but differ in their group/prefix APIs:
// Gin
r := gin.Default()
api := r.Group("/api")
api.GET("/users", listUsers)
// Echo
e := echo.New()
g := e.Group("/api")
g.GET("/users", listUsers)
// Chi
r := chi.NewRouter()
r.Route("/api", func(r chi.Router) {
r.Get("/users", listUsers)
})
The adapters handle all three group/prefix styles and resolve them correctly. net/http support covers http.HandleFunc(), mux.HandleFunc(), and http.Handle() — the stdlib primitives that underpin most Go services that don't pull in a router dependency.
Auto-detection under the hood
The detection logic reads manifest files first, then falls back to import scanning if the manifest is ambiguous:
-
package.jsondependencies → identifies Node.js framework -
requirements.txt/pyproject.toml→ identifies Python framework -
go.modimports → identifies Go framework (github.com/gin-gonic/gin,github.com/labstack/echo, etc.) -
pom.xml/build.gradle→ identifies Spring Boot
Confidence is returned alongside the framework name. If confidence is low — for example, a project has both Flask and FastAPI listed as dependencies — the CLI warns you and lets you override with --framework.
Programmatic API
If you're integrating the tool into a CI pipeline or build script, the programmatic API gives you full control:
import { Scanner, TestGenerator, detectFramework, getAdapter } from 'endpoint-tester';
const detected = await detectFramework('./src');
const adapter = getAdapter(detected.framework);
const scanner = new Scanner(adapter);
const endpoints = await scanner.scan({ directory: './src', framework: detected.framework });
const generator = new TestGenerator();
generator.generate({
endpoints,
output: './tests',
format: 'vitest',
baseUrl: 'http://localhost:3000',
});
The Adapter interface is also exported — implement it to add any framework the built-in list doesn't cover:
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[] {
// regex-based parsing logic
return [];
}
}
registerAdapter(new HonoAdapter());
What's next
The contributing guide lists the highest-impact open areas:
- OpenAPI/Swagger output — generate a spec file instead of (or alongside) a test suite
- Watch mode — re-scan and regenerate on file change, useful during active development
- Smarter body inference — use TypeScript types and Python type hints to generate more precise field-level tests
- More frameworks — Hono, Actix (Rust), Laravel (PHP) are the most-requested
Pull requests are welcome. The adapter interface is simple on purpose — a new adapter is usually 60–100 lines of regex parsing.
Install and try it
npm install -g endpoint-tester
# or without installing:
npx endpoint-tester scan ./src
GitHub: github.com/leopechnicki/endpoint-tester
If the tool is useful, a star on GitHub helps others find it. And if you're using a framework that isn't on the list yet, open an issue — or better, open a PR.
Top comments (0)