https://github.com/gr0uch/tapdance
Test harness that emits the Test Anything Protocol (TAP).
https://github.com/gr0uch/tapdance
tap test-harness
Last synced: 4 months ago
JSON representation
Test harness that emits the Test Anything Protocol (TAP).
- Host: GitHub
- URL: https://github.com/gr0uch/tapdance
- Owner: gr0uch
- License: mit
- Created: 2015-07-09T14:44:52.000Z (over 10 years ago)
- Default Branch: master
- Last Pushed: 2019-09-26T22:12:04.000Z (over 6 years ago)
- Last Synced: 2025-08-14T12:37:42.590Z (5 months ago)
- Topics: tap, test-harness
- Language: JavaScript
- Homepage:
- Size: 54.7 KB
- Stars: 4
- Watchers: 2
- Forks: 0
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Tapdance
[](https://travis-ci.org/daliwali/tapdance)
[](https://www.npmjs.com/package/tapdance)
[](https://raw.githubusercontent.com/daliwali/tapdance/master/LICENSE)
Test harness that emits the [Test Anything Protocol (TAP)](https://testanything.org). It runs in Node.js and web browsers, and is written in literate Parenscript (Common Lisp).
```
$ npm install tapdance
```
## Usage
When the test exits, Tapdance will return a `0` exit code if nothing went wrong, and a non-zero exit code otherwise. There is no need to manually call when a test ends.
### tapdance(fn)
Run a function which may return a Promise. Calls to `runTest` get collected synchronously and run in sequential order in the next tick, which is useful when splitting up asynchronous tests in different files. The `fn` accepts two arguments, `assert` and `comment`.
### assert(value, [message])
Check if a value is truthy or not.
### comment([message])
Output a comment line.
### runTest.assert
This can be overridden to use a different assert function.
## Building
You will need a Common Lisp implementation like [SBCL](http://www.sbcl.org), and `wget`. If installing the developer dependencies didn't work the first time, you may need to `cd node_modules/sigil-cli && make`.
## License
This software is licensed under the [MIT License](//github.com/daliwali/tapdance/blob/master/LICENSE).
## Code
Here's the full source code.
"use strict"
(defvar *assert* (require "assert"))
Check if it's running in Node.js, this determines whether or not to call
Node.js specific APIs.
(defvar *is-node*
(and (not (eq (typeof process) 'undefined))
(eq (typeof (@ process exit)) 'function)
(eq (typeof (@ process next-tick)) 'function)))
Initialize the local state of the program which is read & written later.
(defvar *start-time* ((@ *date now)))
(defvar *stack* (array))
(defvar *count* 0)
(defvar *passing* 0)
A bit a ceremony is needed to kick off the TAP output. This kicks off the
running of tests.
(println "TAP version 13")
(if *is-node*
(progn ((@ process on) 'exit exit)
((@ process next-tick) flush))
(set-timeout flush 0))
Define the main public function, it accepts a test function that takes two
arguments, `assert` and `comment`.
(setf (@ module exports) run-test)
(setf (@ run-test assert) *assert*)
(defun run-test (fn)
(defun assert (exp message)
(incf *count*)
(try
(progn ((@ run-test assert) exp)
(incf *passing*)
(println (+ "ok " *count* " " message)))
(:catch (error)
(println (+ "not ok " *count* " " message))
(show-error error))))
(defun comment (message) (println (+ "# " message)))
((@ *stack* push) (lambda () (fn assert comment))))
This is an implementation detail which runs all of the testing functions in
the order that they are declared.
(defun flush ()
((@ ((@ *stack* reduce)
(lambda (chain fn)
((@ ((@ chain then) fn) catch)
(lambda (error)
(progn
(incf *count*)
(println (+ "not ok " *count* " " (@ error message)))
(show-error error)))))
((@ *promise resolve))) then)
(lambda () (if *is-node* ((@ process exit)) (exit)))))
Upon exiting, print the results as well as some useful information such as
how many tests failed and how long it took.
(defun exit ()
(if *is-node*
(setf (@ process exit-code)
(if (and *count* (eq *count* *passing*)) 0 1)))
(if (not *count*)
(progn (incf *count*) (println "not ok 1 no tests found")))
(println (+ "1.." *count*))
(println)
(if (eq *count* *passing*)
(println "# all tests passed")
(let ((failing (- *count* *passing*)))
(println
(+ "# " failing " test" (if (> failing 1) "s" "") " failed"))))
(println
(+ "# test finished in " (- ((@ *date now)) *start-time*) " ms"))
(println))
Internal function to pretty print errors that happen while running tests.
(defun show-error (error)
(println " ---")
(println (+ " name: " (@ error name)))
(if ((@ (regex "\\n") test) (@ error message))
(progn
(println " message:")
((@ ((@ error message split) #\linefeed) map)
(lambda (line)
(println (+ " - " line)))))
(progn
(println (+ " message: " (@ error message)))
(if (@ error stack)
(progn
(println " stack:")
((@ ((@ error stack split) #\linefeed) for-each)
(lambda (line)
(setf line ((@ line trim)))
(if (not (eq ((@ line index-of) (@ error name)) 0))
(println (+ " - " line)))))))))
(println " ..."))
Internal function to print lines while escaping new lines in the input.
(defun println (str)
((@ console log)
(if str ((@ str replace) #\linefeed "") "")))