Open-source project
wellwelwel/poku avatar
wellwelwel/poku

Poku runs the same test file on Node, Bun and Deno with no dependencies

🐷 Poku makes testing easy for Node.js, Bun, Deno, and you at the same time.

1,180 stars29 forksTypeScriptMIT

At a glance

What is it?
Poku is a zero dependency test runner for JavaScript and TypeScript that runs the same suite on Node.js, Bun and Deno, with helpers for starting services, waiting on ports, killing processes and driving containers. It is MIT licensed, at version 4.5.0, and the last push was on 2026-06-18.
Who is it for?
Poku suits a team that ships to more than one JavaScript runtime and wants one test suite and one set of assertions, and it is the wrong tool if you need the mocking, snapshot and transform machinery of a full framework, because the philosophy is deliberately close to the platform defaults. Before adopting it, read the migration notes for 3.x to 4.x, since the README links them as the one upgrade path worth planning around.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The same test file on three runtimes

Poku describes itself as a cross-platform test runner that brings the JavaScript essence back to testing, and the feature list states the goal plainly: run the same test suite for Node.js, Bun and Deno.

That is the whole pitch, and it is narrower than the big frameworks. There is high isolation level per file, performance and lightness, support for ESM, CJS and TypeScript, and a plugin ecosystem for custom and official plugins. And the last of those six is what makes it usable for anything beyond unit tests: easily handle servers, processes, ports, and containers.

The whole installation surface is one dev dependency, and it differs only in the package manager:

sh
npm i -D poku

For TypeScript on Node you also need tsx, and the README gives that as npm i -D poku tsx. Bun uses bun add -d poku, and Deno uses deno add npm:poku.

And the test file itself is deliberately plain:

ts
import { assert } from 'poku';

assert(true, 'Poku will describe it 🐷');

That is the Node.js familiar assert API, and the fact that it is the whole example is the design statement. There is no separate test definition DSL, no transform pipeline, and no configuration file to write before the first test runs.

Running it is the same shape in each runtime, with the runner invoked the way that runtime invokes things: npx poku for Node, bun --bun poku for Bun, and deno run npm:poku for Deno.

The helper set is where the integration testing lives

The essentials table lists the runner and the assert API, and then a long list of common helpers and options that is worth reading as a design brief.

The organising helpers are test, describe and it, described as organise, group and isolate tests. There are beforeEach and afterEach hooks for setup and teardown, and an envFile helper that processes an environment file. So the familiar BDD vocabulary is present, but the README does not present it as a separate style, it presents it as a helper set.

Then come the helpers that make integration and end to end tests possible without a separate framework. startScript and startService run scripts and files in the background, which is how you get a server up for a test to talk to. waitForPort waits for specified ports to become active, and waitForExpectedResult retries until an expected result appears or times out, which together handle the flakiness that comes from a service that is not ready yet. The kill helper terminates ports, port ranges and PIDs, which is the cleanup half of that.

A docker plugin builds, starts, composes, stops and removes containers, and a coverage plugin enables coverage collection. Both are listed as official plugins, alongside the custom plugin support.

Two helpers are for the developer rather than for the test. The skip helper skips tests when necessary, and the only helper enables selective runs for debugging. The watch option re-runs related test files when they change. The debug option shows all logs.

The pattern here is that the parts of a test suite that usually need a plugin ecosystem of their own, spinning up a database, waiting for a port, tearing down a container, are provided as first class helpers in the same package. That is what removes the reason to reach for a heavier framework in the first place.

The performance and size claims come with a benchmark directory

The quick comparisons section makes two sets of claims, and it is worth reading how they are framed.

On performance, Poku is described as about 5.3x faster than Jest at version 30.4.2, and about 4.5x faster than Vitest at version 4.1.6, with a note that you can see how the tests are run and compared in the benchmark directory. On installation size, the packagephobia badge is paired with a claim of about 145x lighter than Jest at 30.4.2, about 124x lighter than Vitest at 4.1.6, and about 2.8x lighter than uvu at 0.5.6, with the note that the size ensures cost-saving CI for services that charge for storage and usage.

The benchmarks are in the repository, which is the right way to make a performance claim checkable. The version numbers are pinned in the claim, so the comparison is against specific releases rather than against whatever is current.

Whether the numbers hold for your project is a separate question, and the reason is in the philosophy. Poku's design is isolation per file and a low overhead runner, so the advantage over Jest comes from Jest doing considerably more. A project that uses none of Jest's mocking, transform and snapshot machinery will see a much smaller difference than 5.3x, and a project that uses all of it will find Poku is not a replacement.

The repository supports the claim in other ways too. There is a codecov.yml, a .nycrc for coverage configuration, a context7.json for documentation tooling, a deno.json, a biome.jsonc for linting and formatting, and a scripts/ directory with build.sh, lint.sh, lint-fix.sh, typecheck.sh and update.sh.

How the package is built and what it ships

The package.json shows a project that is careful about what it ships.

The package is poku at version 4.5.0, MIT licensed, with the type set to module. It publishes a main entry at./lib/modules/index.cjs and a module entry at./lib/modules/index.js, with types at./lib/modules/index.d.ts, and the exports map provides both import and require conditions for the root and for a./plugins subpath, each with a default fallback. The bin entry is lib/bin/index.js, so the CLI ships with the library.

The files array is just lib, so nothing but the built output is published. That is a deliberate choice, and it pairs with the zero dependency claim in the repository topics.

The engines field says node >=16.x.x, which is a notably old floor for a 2026 project, and it is consistent with a tool that aims to run anywhere the language runs. The build itself is a shell script, scripts/build.sh, and lint, typecheck and format all go through shell scripts too, with Biome as the linter and formatter alongside a Prettier import-sorting plugin, which explains the biome.jsonc and.prettierrc at the top level.

The test scripts are the interesting part, because they dogfood the thing. The default test script runs tsx src/bin/index.ts against test/unit, test/integration and test/e2e, so the project's own suite is run by its own runner, in three directories that map to the three levels it supports. The bun variant swaps tsx for bun, and the deno variant runs deno with -A and a --denoAllow=all flag, because Deno's permission model needs to be told explicitly what the test run is allowed to do. There is a coverage variant, a docker-specific test script, and a codecov configuration to send the results to.

Also worth noting is the.claude/ directory and the AGENTS.md and CLAUDE.md files at the top level, and a tea.yaml at the top level.

Where Poku is the wrong choice

The first limit is the philosophy itself. Poku deliberately brings the JavaScript essence back to testing, which means close to the platform defaults, and the consequence is that a lot of what a full framework provides is absent or is expected to come from elsewhere. There is no transform pipeline in the core, so TypeScript on Node needs tsx installed alongside it, which is visible in the install instructions and is one more moving part in CI. A team whose tests rely on module mocking, on snapshot testing or on a rich assertion matchers has to keep those from somewhere else, and at that point the argument for a single lightweight runner is weaker.

The second is the ecosystem maturity. The releases are 4.3.2 in May 2026, 4.4.0 in June and 4.5.0 on 2026-06-18, with the last push the same day, so the project is active. But the migration note the README links, from 3.x.x to 4.x.x, shows that a major version in a 4.x line is a real migration with a tracked issue, and the version numbers move fast enough that a pinned dependency will need attention.

The third is the platform matrix in the test scripts. The project runs its own suite under tsx, Bun and Deno, which is the point, but a library that claims to run on three runtimes has to keep the semantics identical across them, and any subtle difference in module resolution, in how the runtimes handle permissions, or in timers will show up as a test that passes on one and fails on another. The Deno variant needs -A and --denoAllow=all, which is a reminder that the permission model is different there.

The fourth is that the coverage and container features are plugins rather than core. That keeps the base package small, which is the entire argument for the size claims, and it also means the feature set you depend on may live in a separate package with its own release cadence.

The fifth is the licensing of the ecosystem around it. Poku itself is MIT, and the author is Weslley Araújo with sponsorship through GitHub Sponsors and OpenCollective, so the project is well funded for its size. But the fast-moving version numbers and the wide runtime support mean a project adopting it should expect to track releases, and the CI badge naming a TestCafe logo in the workflow hint suggests the e2e comparisons are done with a different tool, which is a reasonable way to keep the comparison honest.

Editorial conclusion

Poku suits a team that ships to more than one JavaScript runtime and wants one test suite and one set of assertions, and it is the wrong tool if you need the mocking, snapshot and transform machinery of a full framework, because the philosophy is deliberately close to the platform defaults. Before adopting it, read the migration notes for 3.x to 4.x, since the README links them as the one upgrade path worth planning around. Verify first that your test tooling needs match what Poku offers, particularly the coverage plugin and the container helper, and note the runtime floor in package.json is Node 16 or newer while the development scripts use tsx, Bun and Deno directly.

Frequently asked questions

What is Poku?

It is a cross-platform test runner for JavaScript and TypeScript that brings the JavaScript essence back to testing. It runs the same test suite on Node.js, Bun and Deno, supports ESM, CJS and TypeScript, has a Node familiar assert API, and ships helpers for services, ports, processes and containers.

How do I install and run Poku?

Install it as a dev dependency with npm i -D poku, adding tsx for TypeScript on Node, or use bun add -d poku and deno add npm:poku. Run it with npx poku on Node, bun --bun poku on Bun and deno run npm:poku on Deno.

What helpers does Poku provide for integration and end to end tests?

startScript and startService run scripts and files in the background, waitForPort waits for ports to become active, waitForExpectedResult retries until an expected result or timeout, kill terminates ports, port ranges and PIDs, and an official docker plugin builds, starts, composes, stops and removes containers.

How does Poku compare with Jest and Vitest on speed and size?

The README claims about 5.3x faster than Jest v30.4.2 and about 4.5x faster than Vitest v4.1.6, and about 145x lighter than Jest and 124x lighter than Vitest by install size, with the benchmark directory in the repository showing how the tests are run and compared.

What does Poku need to run?

The package engines field requires node >=16.x.x, and it publishes only the lib directory, with no runtime dependencies. The project itself builds with a shell script, lints with Biome, and runs its own suite under tsx, Bun and Deno across test/unit, test/integration and test/e2e.

Official sources

  1. License: MIT
  2. Project website
  3. README
  4. Releases
  5. wellwelwel/poku on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/wellwelwel-poku.svg)](https://hysenlabs.com/projects/wellwelwel-poku)

Was this useful?