Deno (a modern Rust based TypeScript runtime) comes with code coverage measurement built in. Unfortunately, right now, its only supported for deno test
but not for deno run
.
This seems unnecessarily limiting, since it makes measuring coverage in a running Deno server by running API tests against it convoluted - but not impossible. This blog outlines a workaround that lets you achieve just this. Thanks to an idea from zachauten.
Let's say you had a bunch of Postman API tests written up for testing a Deno HTTP REST API server that you execute using the excellent newman CLI collection runner. Further, lets say you wanted to measure code coverage from running these API tests.
You would think you would be able to do something like this:
# Start Deno HTTP server and put it in background
deno run --coverage ./main.ts &
export PID=$!
# Run Postman API tests using newman
npx newman run ./api-tests.postman.json
# Kill server to generate coverage
kill $PID
Unfortunately, the above does not work because deno run --coverage
is not supported.
Instead, the trick is to do all these steps (start server, run API tests, stop server) inside a Deno test and then use deno test --coverage
. Sigh 😞. Seems labyrinthine but here is how to do it.
Step 1: Make your server a testable module
Make sure that your server is in a form that can be consumed from a Deno test and started and stopped there. For example a simple server can look like:
// server.ts
export function requestHandler(_req: Request): Promise<Response> {
return Promise.resolve(new Response("Hello, world!"));
}
This server can also be consumed from your main entry point thus:
// main.ts
import { serve } from "std/http/server.ts";
import { requestHandler } from "./server.ts";
serve(requestHandler);
Step 2: Write a test that calls the server
Now write a test that does the following:
- Start server with abort controller
- Shell out to run
newman
API tests - Stop server using abort controller
For example:
// server_test.ts
import { assert } from "std/testing/asserts.ts";
import { serve } from "std/http/server.ts";
import { requestHandler } from "./server.ts";
Deno.test("API Tests", async () => {
// Start server (with abort controller)
const controller = new AbortController();
const { signal } = controller;
const server = serve(requestHandler, { signal });
// Run API tests
const p = Deno.run({
cmd: ["npx", "newman", "run", "./api-tests.postman.json"],
});
const { success } = await p.status();
p.close();
assert(success);
// Stop server (using abort controller)
controller.abort();
// Wait for server to be closed
await server;
});
Step 3: Run test in coverage mode
Finally, we can run the server test with the --coverage
flag.
deno test --allow-net --allow-run --coverage=coverage ./server_test.ts
This will run the outer server_test.ts
in coverage mode, generating code coverage in the coverage
folder which can be further processed. See help on Deno coverage.
Conclusion
Hopefully, in the long run, Deno will introduce a deno run --coverage
option. Till then, this workaround will have to do.
For a more fleshed out version of the code in this post, please see:
anishkny / deno-api-tests-coverage
Measure code coverage of a Deno server when running Postman (newman) API tests
Deno API Tests Coverage
Demonstrates code coverage measurement of a Deno server when running Postman (newman
) API tests.
See accompanying blog post for more details.
Requirements
Deno v1.26 (or higher) installed and available on path.
Usage
Clone this repository and execute:
deno task test
This runs the test file ./test/server_test.ts
and collects resulting code coverage.
The test file takes the following steps:
- Start the Deno server to be tested (
src/server.ts
). - Run Postman API tests using
newman
in a subprocess. - Stop the server.
Background
Deno lacks a way to measure code coverage of a server when running API tests. See this discussion on the Deno repo.
Ideally, there would be a way to start a server thus:
deno run --coverage=coverage src/server.ts # Doesn't work
# Run API tests
# Kill server
Instead you have to start the server, run API tests by shelling out to a process…
Top comments (0)