Philosophy
Poku's philosophy consists of simplicity and efficiency, removing complexities and boilerplate requirements to make testing accessible for the simplest to the most complex projects.
JavaScript Essence for Tests π‘β
The JavaScript's native syntax for tests is what makes it possible to use Poku on multiple platforms.
Imagine you want to execute asynchronous functions, where one runs after the other, and display a message at the beginning and end of the execution:
console.log('Started');
await funcA();
await funcB();
console.log('Done');
Normally, we can't do this with most test runners. See this fictional example:
A popular term for this is "boilerplate", which are extra requirements for structuring and configuring the tests.
describe('My Test', { concurrency: 1 }, () => {
// You need to explicitly state what should be run before the tests
beforeAll(() => {
console.log('Started');
});
// The last step of the script is called before the tests themselves
afterAll(() => {
console.log('Done');
});
// Asynchronous tests, but they will be executed sequentially even without the use of `await`
it(async () => {
// async test
});
it(async () => {
// async test
});
});
Also, you can't run this like node test.js
due to evaluations, global state, or test transformations, where you need to run your test using the test runner.
Poku brings back the JavaScript essence to tests:
import { describe, it } from 'poku';
describe('My Test', async () => {
console.log('Started');
await it(async () => {
// async test
});
await it(async () => {
// async test
});
console.log('Done');
});
Poku doesn't use a global state, allowing you to use it how and where you want:
- Node.js + Poku
- Bun + Poku
- Deno + Poku
- Node.js
- Bun
- Deno
- Yarn + Poku
- pnpm + Poku
npx poku test.js
bunx poku test.js
deno run npm:poku test.js
node test.js
bun test.js
deno run test.js
yarn poku test.js
pnpm poku test.js
- Same idea for TypeScript.
Making Tests Really Easy π±β
In many cases, tests lead to the same common objective: the assertion of an expected value with a dynamic value.
But tests usually don't show enough logs and details if you only focus on assertions. Even if they work, you might easily encounter an error message like "at least one test is necessary" with some test runners.
An example using the native Node.js assert
:
import assert from 'node:assert';
const one = 1;
assert.equal(one, 1, '1 needs to be equal to 1');
- The assert message in this example will not be displayed and the test will pass silently.
Instead of, you will need to use test
or describe
and it
:
import assert from 'node:assert';
import test from 'node:test';
test('one is equal to 1', () => {
const one = 1;
assert.equal(one, 1, '1 needs to be equal to 1');
});
Poku allows a test following the BDD/TDD approach using only the assert
method:
β οΈ Please, it's not a recommendation, but yes, it would be possible for simpler tests.
- test/file.test.mjs
import { assert } from 'poku';
const one = 1;
assert.equal(one, 1, 'one is equal to 1');
Then:
- Node.js and TypeScript (Node.js)
- Bun
- Deno
npx poku
bunx poku
deno run npm:poku
This will generate a complete log, both in case of success or failure, maintaining the exact Node.js development style and being compatible with Node.js, Bun, and Deno.
Each case can be different. For this, Poku has a completely modular way of using it, allowing you to use test
, describe
, it
, beforeEach
, afterEach
, --watch
mode and more, according to your needs for more complex tests or tests that follow a specified pattern.
Special Features π«β
Poku offers integrated support for common testing challenges, such as starting services, servers and containers needed to run tests and terminating them at the tests' end, in addition to flexibility to handle ports and processes.
Development Priorities π§β
- Human-friendly usage.
- Cross-platform compatibility (Node, Bun, and Deno).
- Performance improvements.
- All functionalities must be documented and have at least a minimum example of use.
Compatibility with legacy environments whenever possible, documenting when a specific feature only works from a version of the runtime/platform.
Why Not Install External Dependencies? π¦β
In order of relevance
- By requiring all possible dependencies to be fully compatible with Node.js, Bun and Deno.
- To keep the final installation size as lightweight as possible
- To avoid compatibility issues with legacy environments.
TypeScriptβ
For Node.js + TypeScript, Poku uses tsx to run the files. Why? Because it follows the same principle as Poku: zero configurations for common needs.
Why Maintain Backward Compatibility? π΄πΌβ
This topic doesn't concern Bun and Deno.
Several projects still use or support legacy versions. The requirement for legacy versions isn't a strict rule and can change with major releases due to specific features that may require polyfills and impact performance directly.
That's why the limit chosen was Node.js version 12.x.x
.
Current Polyfillsβ
fs
: promisify callback methodsObject
:entries
andfromEntries
(used only when not available natively)- Support for direct runs for CommonJS on Deno
Poku always recommends using supported versions of each runtime.
Future Plans πβ
Although not a priority, there are plans to integrate the following features into Poku:
- Stub
- Mock
- Spies
See mock examples for both CJS and ESM using Poku + quibble.
Versioning π·οΈβ
They aren't considered breaking changes:
- Formatting and style changes to outputs (including reporters β soon).
- New functionalities that depend from a specific platform version:
- As long as it doesn't affect basic usability.
- E.g., when using Node.js previous to
v15.x.x
, thestrict
method isn't available.
- If a feature is no longer useful due to a new approach (as long as it doesn't affect the end user).
- JSON intellisense schema changes (config files).
Which Poku doesn't Pretend to be π€π»β
- A replacement for native test runners
- Try and use Poku as an alternative π·
- The lightest or the fastest
- Although these points are taken into consideration, the main aim is to maintain a balance between good practices.
Note that Poku has a different way of being used, inspired entirely by the essence of native JavaScript, which can be both an advantage and a disadvantage for those who are used to the traditional hooks of other test runners.