Skip to content
Lauri Rooden edited this page Feb 9, 2023 · 3 revisions

Simple test framework with structure, assertions, mocks, and snapshots.

  • no external dependencies, writen in ES5, under 10kB when minified

Get Started

  1. Install LiteJS command line tools to get command line utility lj.
    npm install -g @litejs/cli
  2. Write your first unit test.
  3. Run tests.
    lj test

Structure

See structure test for more examples.

// All methods are attached to describe,
describe("My first TestSuite", function() {
    // this === describe
    it ("should have first test case")         // without a function is a pending test
    it ("_should have a second test case")     // starting with `_` also pending
    .it("should pass more tests", function(assert) {
        assert.setTimeout(5000)       // Set testcase timeout to 5sek (default 1sek)

        assert                        // Assertions can be chained
        .equal(1, 1)
        .throws(function() {
            throw Error("Test")
        })

        assert.end()                  // Without a plan you have to call `end` explicitly
    })
})

Data tables

LiteJS test framework offers built-in support for data tables at every level, making it easy to generate test suites and cases with your own data.

var suitesTable = [
	[ "sqlite", function() { return Promise.resolve() } ],
	[ "mysql", function() { return Promise.resolve() } ]
]
, casesTable = [
	[ "INSERT", 3 ],
	[ "DELETE", 4 ]
]

describe("Test on {0}", suitesTable, function(suiteName, suiteSetup) {
	it("connects to " + suiteName, suiteSetup)

	// provided values are spread to beginning of callback
	it("tests {0}", casesTable, function(query, value, assert) {
		// test here
		assert.end()
	})
})
Test on sqlite
  ✔ 1. it connects to sqlite [0/0]
  ✔ 2. it tests INSERT [0/0]
  ✔ 3. it tests DELETE [0/0]
Test on mysql
  ✔ 4. it connects to mysql [0/0]
  ✔ 5. it tests INSERT [0/0]
  ✔ 6. it tests DELETE [0/0]
1..6
# pass  6/6 [0/0] in 4 ms at 15:56:02

Assertions

  • assert.equal(actual, expected[, message]) - deep strict equality between the actual and expected parameters
  • assert.notEqual(actual, expected[, message]) - not deeply and strictly equal
  • assert.notOk(value[, message]) - check that value is falsy
  • assert.notStrictEqual(actual, expected[, message]) - actual !== expected
  • assert.ok(value[, message]) - check that value is truthy
  • assert.strictEqual(actual, expected[, message]) - actual === expected
  • assert.throws(fn[, message]) - check that a function throws
  • assert.type(value, expected[, message]) - check typeof value
    Types: arguments, array, boolean, date, function, nan, null, number, object, regexp, string, undefined

Assert controll

  • assert.end() - End testCase
  • assert.plan(count) - Specify the number of assertions
  • assert.setTimeout(ms) - Override default 1sek timeout for testCase
  • assert.wait() - Returns a callback for resuming assertions

Mocks

Mock functions allow you to verify an invocation and replace behavior. Mock functions have special .called, .calls, .errors, .instances and .results properties.

it ("should mock", function(assert, mock) {
    assert.own(cb, {
        called: 4,
        errors: 0,
        results: [1, 10, 100]
    })
    assert.end()
})
  • mock.fn([behaviorFn|resultsArray|resultsMap|value]) - create a function to record invocations
  • mock.rand([seed]) - freeze time, time=now when omitted.
  • mock.spy(object, name, newFn) - replace a method on an object
  • mock.swap(object, name, newFn) - replace a method on an object
  • mock.tick([ms]) - tick time ahead ms milliseconds or till next timer when omitted
  • mock.time([time]) - freeze time, time=now when omitted.
    time can be string for Date.parse() or milliseconds since the Epoch.

Mocking time will overwrite global setTimeout and friends to allow easier synchronous testing.

All mocks are restored on end of testCase.

Mock Return Values

Snapshots

See example implementation

Example

it ("should test", function(assert, mock) {
    var fake = mock.fn()                // create a fake without behavior
    , spy = mock.fn(function() {})      // wrap existing function for behavior
    , results = mock.fn([1, 3, 4])      // return one member from an array in loop
    , mapped = mock.fn({
        '1': 'got number one',          // map call arguments to value
        '"1"': 'got string one',
        '1,"1"': 'got two arguments',
        '': 'called without arguments',
        '*': 'any other call'
    })

    mock.time("2018-01-02T13:45:51.001Z")
    setTimeout(fake, 100)
    setImmediate(fake)

    assert.equal(fake.called, 0)
    mock.tick(1)                   // tick 1 ms, setImmediate will be fired
    assert.equal(fake.called, 1)
    mock.tick()                    // tick till next timer
    assert.equal(fake.called, 2)   // setTimeout has been fired
    assert.end()
})

Coverage

This module does not have a built-in test coverage as existing tools just magically work. :)
Prefix your test command with c8 or nyc.

c8 lj test

Options

lj test accepts several options.

  • --globals=describe,it - Expose methods in global scope.

    --no-globals --globals=describe,it,test,should

  • --seed=1234 - Use specified seed in mocked Math.random(), otherwise it is random.
  • --stack=4 - Show 4 lines is stacktrace.
  • --status=1 - Exit with status code showing failed tests.

    --no-status

  • --timeout=999 - Default timeout for all test cases in ms.

Configuration in package.json

All command line options can be written to package.json

{
  "litejs": {
    "test": "test/index.js"
  }
}

Clone this wiki locally