/ Testing


The builtin unit-testing feature is enabled with -u:

jsish -u tests/test.js 
[PASS] tests/test.js

For a test script to pass, output simply needs to match the expected puts output (contained in an EXPECT* comment), eg:

#!/usr/local/bin/jsish -u %s

function foo(n) {
    return "FOO"+n;



Scripts not having an EXPECT* comment will pass testing as long as they are error-free.

We can also provide expected output from the command-line using -expectFile.


An EXPECT* comment can be updated/inserted in-place using:

jsish -u -update true DIRORFILES

Implicit puts()

In Jsi test-mode (jsish -u) a special reformat is applied to lines starting and ending with ';':

"printf(\"%%s ==> \",\"%s\"),puts(%s);\n"

This echos the expression, then evaluates it and echos the result to stdout:

#!/usr/local/bin/jsish -u %s

function a(n) {
    var sum = 0;
    for (var i = 0; i < n; i++)
        sum = sum + i;
    return sum;

;'===Begin Test===';

'===Begin Test==='
a(10) ==>  45
a(100) ==>  4950
a(1000) ==>  499500

The transformed code becomes:

puts("'===Begin Test==='");
puts("a(10) ==> ", a(10));
puts("a(100) ==> ", a(100));
puts("a(1000) ==> ", a(1000));

(Note the special case are lines of the form ";'...';", which are output verbatim)

To see this output we can use the -U option:

jsish -U tests/func.js
'===Begin Test==='
a(10) ==>  45
a(100) ==>  4950
a(1000) ==>  499500

Implicit and explicit puts can freely be intermixed.

#!/usr/local/bin/jsish -u %s

function foo() { return true; }
function bar() { return true; }

puts('foo() ==> ', foo());

bar() ==>  true
foo() ==>  true

The following rules apply to implicit puts:

  • Double-quotes are illegal.
  • An expression starting and ending with a single-quote is output verbatim (unevaluated).
  • Leading spaces after the first ';' are stripped from the expression (eg).
  • Functions definitions will be scoped within the puts argument.
  • Side-effect output may appear prior to the "==>" line (eg. from function calls).

Test Results

By default, a test result is either PASS (when output matches) else a FAIL followed by a description of the differences:

jsish -u prob/testfail.js
[FAIL] prob/testfail.js
at line 2 of output:
    output: <bar failed>
    expect: <bar passed>
 foo passed
-bar passed
+bar failed
 baz passed

The return code is zero if the test did not failed.

Multiple Tests

Arguments to jsish -u can either be one or more files, or a single directory in which to look for .js or .jsi files:

jsish -u tests/
[PASS] tests/49.js
[PASS] tests/99bottles.js
[PASS] tests/alias.js
[PASS] tests/apply.js
[FAIL] tests/arg.js
at line 9 of output:
    output: <4>
    expect: <5>
[FAIL] tests/arg2.js
at line 9 of output:
    output: <1>
    expect: <2>
[PASS] tests/alias.js
Test tests/array.js
[PASS] tests/yhsj.js
2 FAIL, 97 PASS: runtime 21551 ms
echo $?

The return code is the number of failed tests (up to a maximum of 127). There is a summary when multiple test are run, but no DIFF (unless context>3).

Script Input

A scripts requiring test input (to read from stdin) it can be specified as follows:


This can also be provided from the command-line using -inStr or -inFile. The default is no input.

Script Arguments

A may script may specify arguments with:

-debug 1 able baker charlie

This should be on a single line: newlines will be stripped.

This can also be provided from the command-line using -args. The default is no arguments.


During unit-testing Interp.assert is set to true, which means asserts are enabled.

This can result in test scripts failing when assert throws an uncaught error.

There are various ways to adjust the behaviour of assert when working with test scripts, eg. assert.jsi:

#!/usr/local/bin/jsish -u %s
"use asserts";

assert(2*3 == 6,'math');
try {
} catch(e) {
    puts('caught error');
var x = 1;

var i=1, j=2;
;assert(function () { return (i<j); },'fail');

try {
} catch(e) {
    puts('caught error2: '+e);
try {
;   assert(false,'false');
} catch(e) {
    puts('caught error2: '+e);

;assert(false,'this assert failed',{mode:'puts', noStderr:true});

;Interp.conf({assertMode:'puts', noStderr:true});

;assert(false,'assert also failed');


Option help can be dump with:

 jsish -u -h:
Run script(s) as unit-tests setting return code to number of failed tests.

	-args	 	""		// Argument string to call script with
	-context 	3		// Number of context lines for DIFF (>3 forces dir diff).
	-debug	 	false		// Enable debugging messages.
	-echo	 	false		// Run with puts/assert output showing file:line number, but don't test.
	-evalFile 	""		// File to source in subinterp before test.
	-exec	 	false		// Use exec instead of running test in a sub-interp.
	-expectFile 	null		// File to use for expected output.
	-failMax 	0		// Quit after this many failed tests.
	-inFile	 	null		// File to use for stdin input.
	-silent	 	false		// Run quietly, showing only failures.
	-update	 	false		// In-place update or create of EXPECT* from a run of test file(s).
	-verbose 	false		// Show gory detail: inputs/outputs/args.

A script can detect unit-test mode using:

if (Interp.conf('unitTest') > 0)
    puts("We are testing...");


When a test fails, -echo can show the source line associated with output:

jsish -u -echo true prob/testfail.js
jsish -u -echo true prob/testfail.js 
Test prob/testfail.js 
/home/user/src/jsi/jsi/tests/prob/testfail.js:7:   "foo passed", 
/home/user/src/jsi/jsi/tests/prob/testfail.js:8:   "bar failed", 
/home/user/src/jsi/jsi/tests/prob/testfail.js:9:   "baz passed", 

Edit the script as follows to run from Geany with F9, so as to click-to-navigate the output:

#!/usr/local/bin/jsish -u -echo true %s

You can also try -verbose for even more detail.

Builtin Tests

Following are links to the javascript test-files.

49.jsi 99bottles.jsi alias.jsi apply.jsi arg.jsi arg2.jsi arguments.jsi argumentshared.jsi array.jsi array2.jsi assert.jsi b64.jsi badfunc.jsi bind.jsi brainfuck.jsi call.jsi callee2.jsi class.jsi construct.jsi delete.jsi do.jsi eval.jsi eval2.jsi eval3.jsi evalthrow.jsi excpt.jsi excpt2.jsi excpt3.jsi excpt4.jsi excpt5.jsi exec.jsi expr.jsi ffi.jsi fib.jsi file.jsi file2.jsi float.jsi foreach.jsi forin.jsi forinstack.jsi format.jsi func.jsi grep.jsi hexnames.jsi in.jsi info.jsi inherit.jsi inherit2.jsi instance.jsi interp.jsi interp2.jsi invoketime.jsi io.jsi json.jsi json2.jsi labeled.jsi lambda.jsi local.jsi logging.jsi map.jsi math.jsi module.jsi number.jsi obj.jsi person1.jsi person2.jsi prime.jsi property.jsi proto2.jsi proto3.jsi prototypes.jsi recurse.jsi redefine.jsi ref.jsi regex.jsi scope.jsi signal.jsi simple.jsi sqlite.jsi strict.jsi string.jsi switch.jsi switch2.jsi syntax.jsi test.jsi test2.jsi this.jsi this2.jsi this3.jsi time.jsi trim.jsi tryreturn.jsi update.jsi util.jsi value.jsi while.jsi while2.jsi with.jsi yhsj.jsi

Note: the self-test run by make test in Jsi uses a bash script testjs.sh, not jsish -u:

Failure In Testing Jsi Itself

There are 4 basic types of failures (in decreasing order of preference) in Jsi:

  • Seg Fault.
  • Abort, due to assert failure.
  • Hang, incorrect or unexpected result.
  • Memory leak.

Following in given to failures in Jsi (in decreasing order of preference):

  1. Nominal script execution.
  2. Interactive mode.
  3. Errors not in try/catch that result in program termination.

Note, the script tools/randtest.jsi calls all functions with various arguments.