under-the-sun
TypeScript icon, indicating that this package has built-in type declarations

2.1.1 • Public • Published

Under the Sun

A nothing-new-under-the-sun testing framework.

This testing framework was inspired by the likes of uvu. It is intended to be as fast as possible yet as simple as possible.

Installation

npm install --save-dev under-the-sun

Usage

// examples/my.test.js
import assert from "node:assert"
import { test } from "under-the-sun"

test("something synchronous", () => {
  assert(2 === 2, "2 should be 2")
})

test("something asynchronous", async () => {
  await new Promise((resolve) => setTimeout(resolve, 1000))
  assert(2 === 3, "2 should still be...2")
})

Execute tests in a directory via CLI:

npx under-the-sun examples
# or with alias
npx uts examples

Execute a filtered set of tests via CLI:

npx under-the-sun examples my asynchronous

In this case, only files in the examples directory matching the regex my will be considered. Within those files, only tests whose descriptions match the regex asynchronous will be executed.

Output

If you're unsatisfied with the default test reporter, you can override it.

// examples/test-reporter.js
import { setTestReporter } from "under-the-sun"

let failure = false
setTestReporter({
  reportResult(testDescription, result) {
    if (!result.error) {
      // Do something about test success.
      return
    }

    // Do something about test failure.
    failure = true
    console.error("FAIL: " + testDescription)
  },
  reportFinish() {
    // Finalize the test run.
    process.exit(failure ? 1 : 0)
  },
})

Then just load this file alongside your tests:

uts -r examples/test-reporter.js examples

You can check out the default implementation for ideas.

CLI

The CLI is available via under-the-sun or uts.

uts [-p <file pattern>] [-i <ignore pattern>] [options] [<dir> [<file filter> [<description filter>]]]

Tests will be discovered automatically within the dir directory. Test files must match both file pattern and file filter to be executed. Only tests within those files matching description filter will be executed.

  • dir is the current directory by default.
  • file pattern is /\.test\.(j|t)s$/ by default.
  • ignore pattern is /(^|\/)(node_modules($|\/)|\.)/ by default.
    • i.e. ignores node_modules/ and dot files
  • file filter matches all files by default.
  • description filter matches all tests by default.

The file pattern, file filter, and description filter CLI arguments are passed directly to new RegExp(<pattern>).

If this seems confusing, start by just running uts without any arguments.

Options

  • -r/--require - Load a module/script prior to test execution.
  • -m/--magic - Make test and defineTestGroup globally available (no need to import/require).
  • -s/--serial - Run tests sequentially rather than in parallel (default). Note: This is only intended as a debugging mechanism for when your tests are failing intermittently in parallel. Tests will not run in deterministic order even with this flag.

API

The library exposes a couple items for programmatic usage, but it's a small enough surface area it will just be easier for you to check them out on your own.

Examples

See the examples/ directory for specific working examples.

Why should I use this?

You probably don't want to. That being said, here are some aims of this library:

  • Fast - This library pretty much just runs your JavaScript with as much async as possible. There's nothing fancy that could possibly slow things down. The only way make it meaningfully faster would be to use some alternative runtime (e.g. native code, process-level multithreading, caching).
  • Simple - This library doesn't provide a large API, so you're not tightly coupling your code to it in a way you can't easily change later.

I think this testing library is best for pure JavaScript/TypeScript Node.js libraries.

It's entirely possible someone has already written a library that does exactly what this does, better and with more features. I didn't find it though.

Why Not uvu?

You said this is like uvu. Why not just use that?

uvu doesn't do any kind of parallelization.

This library is still single-threaded, but it leverages the asynchronous concurrency built into JavaScript. This strategy is particularly helpful when you have a lot of tests with a significant I/O-bound component.

Why Not Jest?

You reference Jest's assertion library. Why not use it wholesale?

Jest is slow. It's pretty great to work with, but my experience has shown that it takes multiple seconds to run basic tests.

Why Not Vitest?

Vitest is focused on the web application ecosystem, not so much the Node library ecosystem.

Why Not AVA?

AVA has fallen out of favor, and I didn't want to waste time figuring out why. I'm guessing it has something to do with the opinionated-ness of it. Also, uvu's author claims that uvu is faster.

Why Not Mocha?

Mocha has also fallen out of favor. I've never used it, so maybe it's completely superior. ¯\(ツ)

Why Not Tape?

Also never used it.

TypeScript

If you're using TypeScript, you may want to run your tests with some kind of TypeScript module loader like esbuild-register, @swc-node/register, or ts-node.

under-the-sun -r esbuild-register examples
under-the-sun -r @swc-node/register examples
under-the-sun -r ts-node/register examples

Assertions

This library does not ship with any assertions. You'll have to find your own.

Here are some options for you:

Node's assert Module

Node's assert module comes with Node out of the box, so you don't have to install anything. It has a little bit of flexibility, but the reporting may not be as nice as you're used to.

import assert from "node:assert"

test("...", async () => {
  assert(2 === 2, "2 should be 2")
  assert.strictEqual(2, 3, "2 should still be 2")
  assert.deepStrictEqual({}, {}, "More complex equality")
})

Jest's expect Library

If you're coming from Jest, you may feel most comfortable picking up it's expect library.

import { expect } from "expect"

test("...", async () => {
  expect(2).toBe(2)
  expect({}).toStrictEqual({})
})

Chai

For a more traditional JS approach, you may want to use Chai.

import { assert } from "chai"

test("...", async () => {
  assert.equal(2, 3, "2 should still be 2")
})

Watching

To run tests in watch mode, follow a strategy like uvu's.

{
  "scripts": {
    "test:watch": "watchlist src -- uts examples"
  },
  "devDependencies": {
    "under-the-sun": "^1.0.0",
    "watchlist": "^0.2.1"
  }
}

Package Sidebar

Install

npm i under-the-sun

Weekly Downloads

29

Version

2.1.1

License

MIT

Unpacked Size

21.4 kB

Total Files

10

Last publish

Collaborators

  • grantdennison