Skip to content
/ tape Public

Simple Test Anything Protocol implementation based on tape by @substack

License

Notifications You must be signed in to change notification settings

datkt/tape

Repository files navigation

datkt.tape

TAP [1] output producing test runner for Kotlin mostly ported from @substack's tape module for Node.js [2]. This package is installable with NPM [3], IMS [4], clib [5], GHI [6], and of course, from [source][#install-from-source]

Installation

The datkt.tape package an be installed with various package managers.

From NPM

$ npm install @datkt/tape

Note: This will install tape into node_modules/@datkt/tape

From clib

$ clib install datkt/tape

Note: This will install tape into deps/tape

From GHI

$ ghi install datkt/tape

Install From Source

$ git clone [email protected]:datkt/tape.git
$ cd tape
$ make build # or make klib
$ make install

Compiling

From NPM Installation

$ konanc -r node_modules/@datkt -l tape/tape test.kt -o test

From clib Installation

$ konanc deps/@datkt/tape/*.kt test.kt -o test

From Source Installation

$ konanc -l tape test.kt -o test ## library should be installed in ~/.konan/klib

Usage

import datkt.tape.collect
import datkt.tape.test
import lerp.*

fun main(args: Array<String>) {
  test("lerp(a, b, c)", fun(t: Test) {
    val x = 1.0
    val y = 2.0
    val z = lerp(x, y, 1.0)

    t.plan(1)
    t.ok(2.0 == z, "lerp compute fail :shrug:")
    t.end()
  })

  collect() // collects results and prints to stdout
}

API

The datkt.tape package exports a public API documented in this section.

test(name: String, callback: (t: Test) -> Any?): Test

Creates and returns a new named scoped test. The test callback will not be invoked if null is given.

import datkt.tape.test
test("function test", fun(t: Test) {
  t.plan(1)
  t.ok(true, "we're okay")
  t.end()
})

skip(name: String, callback: Callback?): Test

Creates and returns a new skipped scoped test. The test callback will not be invoked if null is given.

import datkt.tape.skip
skip("skipped test", fun(t: Test) {
  t.end(Error("This should never run"))
})

collect(): Results?

Closes results container and writes results to underlying write stream.

import datkt.tape.collect
val results = datkt.tape.collect()

class Test(name: String?, skip: Boolean, callback: Callback?, stream: Stream?)

The Test class represents a named test that is invoked in a function callback. When a test is running, it will call various function hooks and write TAP formatted output to a stream.

t = Test("thing", false, fun(t: Test) {
  t.end
})

t.run()

t.onBeforeRun(callback: (Test) -> Any?)

Add a callback that will be invoked before the test is ran.

t.onBeforeRun({
  // do something before the tests is ran
})

t.onAfterRun(callback: (Test) -> Any?)

Add a callback that will be invoked after the test is ran.

t.onAferRun({
  // do something after the tests is ran
})

t.onResult(callback: (Test, Any?) -> Any?)

Add a callback that will be invoked when there is a test result. It could be a String or AssertionResult.

t.onResult(fun(_, result: Any?) {
  if (result is String) {
    // do something with result string
  } else if (result is AssertionResult) {
    // do something with assertion result
  }
})

t.onPlan(callback: (Test, Int?) -> Any?)

Add a callback that will be invoked when a plan has been set.

t.onPlan(fun(_, plan: Int?) {
  if (null != plan) {
    // do something with plan
  }
})

t.onEnd(callback: (Test) -> Any?)

Add a callback that will be invoked when the test has ended.

t.onEnd({
  // do something when test ends
})

t.run(): Test

Runs the test runner invoking the runner callback given to the constructor if the test is not skipped.

t.run() // will call test callback, if test is not skipped

t.plan(count: Int): Test

Ensure a planned assertion count for a test. Will throw Error if count is 0.

t.plan(4)

t.comment(comment: String): Test

Emit a comment

t.comment("@TODO(jwerle): Fix this")

t.end(err: Error?): Test

Ends the test runner with an optional error that will generate an error assertion.

t.end()

or with an Error

t.end(Error("oops"))

t.assert(ok: Any?, opts: AssertionOptions?): AssertionResult

Asserts that input is truthy based on some optional assertion options.

t.assert(true)
t.assert(1234)
t.assert("okay")
t.assert(::println)
t.assert({ 1 + 1 })

ok(ok: Any?, msg: String?, opts: AssertionOptions?): AssertionResult

Asserts that input is "ok" based on some optional assertion options.

t.ok(null == err)
t.ok(thing is Thing)
t.ok(string.length)

notOk(ok: Any?, msg: String?, opts: AssertionOptions?): AssertionResult

Asserts that input is "not ok" based on some optional assertion options.

t.notOk(err)
t.notOk(thing is That)
t.notOk(array.count)

error(err: Error?, msg: String?, opts: AssertionOptions?): AssertionResult

Asserts that an error is falsy. If an error is given the message is used in the assertion.

t.error(Error("oops")) // failing assertion
t.error(null) // passing

t.fail(msg: String?, opts: AssertionOptions?) : AssertionResult

Creates a failing assertion with an optional message.

t.fail("well, that didn't work")

t.pass( msg: String?, opts: AssertionOptions?) : AssertionResult

Creates a passing assertion with an optional message.

t.pass("well done!")

t.skip(msg: String?, opts: AssertionOptions?) : AssertionResult

Creates a skipping assertion with an optional message.

t.skip("we'll come back to shit")

`t.equal(a: Any?, b: Any?, msg: String?, opts: AssertionOptions?): AssertionResult

Creates an equality assertion for two values with an optional assertion error message.

t.equal("hello", "hello", "hello == hello")
t.equal("good", "food", "good != food")

`t.throws(fn: () -> Unit, expected: Any?, msg: String?, opts: AssertionOptions?): AssertionResult

Creates an assertion that checks for an error to be thrown inside of a given function.

t.throws({ throw Error("oops") }) // passes
t.throws({ throw Exception("yikes") }, Error, "Expection != Error")

Building

The tape package can be built from source into various targets.

Kotlin Library

tape.klib, a Kotlin library that can be linked with konanc can be built from source.

$ make klib

which will produce build/lib/tape.klib. The library can be installed with klib by running make install

Static Library

libtape.a, a static library that can be linked with konanc can be built from source.

$ make static

which will produce build/lib/libtape.a and C header files in build/include. The library can be installed into your system by running make install. The path prefix can be set by defining the PREFIX environment or make variable. It defaults to PREFIX=/usr/local

Shared Library

libtape.so, a shared library that can be linked with konanc can be built from source.

$ make shared

which will produce build/lib/libtape.so and C header files in build/include. The library can be installed into your system by running make install. The path prefix can be set by defining the PREFIX environment or make variable. It defaults to PREFIX=/usr/local

Tests

  • ✔ assert [pass: 21, fail: 0, duration: 0ms]
  • ✔ constants [pass: 13, fail: 0, duration: 0ms]
  • ✔ context [pass: 6, fail: 0, duration: 0ms]
  • ✔ options [pass: 6, fail: 0, duration: 0ms]
  • ✔ result [pass: 5, fail: 0, duration: 0ms]
  • ✔ results [pass: 0, fail: 0, duration: 1ms]
  • ✔ simple [pass: 0, fail: 0, duration: 0ms]
  • ✔ simple [pass: 2, fail: 0, duration: 0ms]
  • ✔ stream [pass: 8, fail: 0, duration: 0ms]
  • ✔ test [pass: 36, fail: 0, duration: 0ms]
  • ✔ truthy [pass: 11, fail: 0, duration: 3ms]

Summary

  • duration: 4ms
  • planned: 108
  • assertions: 108
  • pass: 108
  • fail: 0

References

  1. TAP - https://en.wikipedia.org/wiki/Test_Anything_Protocol
  2. Node.js - https://nodejs.org/en/
  3. NPM - https://www.npmjs.com/
  4. IMS - https://github.com/mafintosh/ims
  5. clib - https://github.com/clibs/clib
  6. GHI - https://github.com/stephenmathieson/ghi

License

MIT