An asynchronous, nesting, composable testing framework for TypeScript [zero-dependency]
Go to file
Justin Collier e6bc73bdeb
Merge branch 'release-0.4.0'
2021-06-18 17:46:47 -07:00
test release preparation 2021-06-18 17:24:14 -07:00
.gitignore Initial code commit 2020-09-18 15:45:05 -07:00
.npmignore added dev files to .npmignore 2021-06-18 17:45:30 -07:00
.testts.json switched to file settings for priority 2021-06-18 17:09:59 -07:00 release preparation 2021-06-18 17:24:14 -07:00
LICENSE GPL -> LGPL 2021-06-14 17:08:36 -07:00
Makefile minor fixes + rewrite initiated for "priority" feature 2021-06-18 13:29:06 -07:00 updated deleteStacks instructions 2021-06-18 17:37:22 -07:00
package-lock.json release preparation 2021-06-18 17:24:14 -07:00
package.json release preparation 2021-06-18 17:24:14 -07:00
testts.d.ts release preparation 2021-06-18 17:24:14 -07:00
testts.js updated "prioritized" instructions 2021-06-18 17:33:50 -07:00
testts.ts formatting 2021-06-18 17:24:50 -07:00
tsconfig.json Initial code commit 2020-09-18 15:45:05 -07:00

testts 0.4.0


testts is an asynchronous, nesting, composable testing framework for TypeScript.

  • Intended to be minimal, testts will always be dependency-free
  • Tests execute code and are witten to either expect no throw or to describe an expected throw
  • Use alongside an assertion library


testts facilitates composition within the type system:

  • tests are registered and executed asynchronously
  • they may be nested indefinitely
  • and they return typed promises that resolve to the test body return value


There are two test registrars, test(descr, body) and test.throws(...?)?(descr, body)

  • any test statement, if executed, will be outputted to the console
  • promises returned from test registration will resolve or reject when the test passes or fails


From anywhere in the test files:

  • test.deleteStacks(setting=true, passToChildren=true): void
    • Deletes stack traces from Error instances thrown during failures.
    • If output is congested with errors, this will improve readability.
    • deleteStacks applies to the test parent and all of its children (unless passToChildren is false).

Using the configuration file $PWD/.testts.json:

  prioritized: string[]
  • prioritized
    • Allows for specifying certain test paths for independent, ordered execution.
    • If some of your tests require timing and you don't want the event loop populated during execution, be sure to list them here.
    • Prioritized tests happen first, and are each completed before the next execution.
      • (By default, tests execute all of their children and then wait for each one afterwards).


In order to achieve nesting, test parents must provide a test parameter.

  • If a test parameter is not written, test statements will create siblings instead.

Although promises returned by test statements can reject, a process listener is used to catch unhandled promises.

  • test statements do not require .catch blocks
  • If an unhandled rejection belongs to a test it is passed on to the report.
  • Any other unhandled rejections cause a non-zero exit.

See the usage examples for more info


Node.js >=10.0.0


npm i --save-dev @jpcx/testts
npx @jpcx/testts dist/ # recursively runs tests from any nested *.test.js files

# any number of files/folers may be used as arguments
# manually specified files do not need to conform to the *.test.js requirement
# npx @jpcx/testts dist/my.compiled.test.js dist/my.other.compiled_test.js dist/other/

# there is only one setting available: `npx @jpcx/testts -m(--match) [ECMAScript regex]`
# the default match regex is "\\.test\\.js"
import { test } from "@jpcx/testts";
import * as assert from "assert";

import { getSampleDB } from "../";

test("simple test", () => {
  // assert(false); // fails test

// all tests return promises (their execution is deferred). In the absence of an
// await statement, tests below will be registered even if the above test fails

test("asynchronous test", async () => {
  await new Promise((resolve) => setTimeout(resolve, 100));

// use a parameter to allow `test` to refer to a parent context
test("nested tests", (test) => {
  test("failure fails parent", () => {

test("dependent testing", async (test) => {
  // tests return promises!!
  const waitforme = await test("nested tested value", () => "yay");

  // TS `typeof waitforme`: 'string'
  test("dependent test", () => assert(waitforme === "yay"));

test.throws("unspecified throw expected", () => {
  throw new Error();
test.throws("bad")("error message specified", () => {
  throw new Error("bad");
test.throws(TypeError)("error constructor specified", () => {
  throw new TypeError();
test.throws(TypeError, "bad")(
  "error constructor and messsage specified",
  () => {
    throw new TypeError("bad");
test.throws((e: number) => e === 42)("predicate-based specification", () => {
  throw 42;


Contribution is welcome! Please make a pull request.


Copyright (C) 2021 Justin Collier <>

  This program is free software: you can redistribute it and/or modify
  it under the terms of the GNU Lesser General Public License as
  published by the Free Software Foundation, either version 3 of the
  License, or (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the internalied warranty of
  GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with this program.  If not, see <>.