the following class executes test cases were input arguments and expected output can be specified in a compact format. it is a minimalistic coffeescript, and therefore also javascript, library for automatic testing.
example
tests = [
[
string_indices
[["/a////b//c/d","/"]] # list of input arguments
[0, 2, 3, 4, 5, 7, 8, 10] # expected result
[["abcd","bc"]] # next input argument list
[1] # next expected result, and so on
]
# the next test group and test
[
string_multiply
["a", 0]
""
["a", 3]
"aaa"
]
]the name of the test and the calling "this" context can also be provided by using an array instead of a function..
["name", function] [this_context, function]
test execution with reporting
test_runner = new test_runner_class test_runner.execute tests
the customizable default reporting format
string-indices 1 2 3 4 5 6 7 8 9 string-multiply 1 2 3 string-replace-string 1 2 3 4 5 6 7 8 9 string-quote 1 failure string-quote 2 inp "t'est" exp "\"t'est\"x" out "\"t'est\""
instead of writing to standard output, it can also create an array of test results for each group, which could be processed by other tools.
results = test_runner.execute_tests tests
class test_runner_class
is_string: (a) -> typeof a is "string"
to_json: (a) -> JSON.stringify(a).replace /,(?=\S)/g, ", "
is_plain_object: (x) -> x? and typeof x is "object" and x.constructor is Object
object_merge: (a, b) ->
for k, v of b
if @is_plain_object(v) and @is_plain_object(a[k])
a[k] = @object_merge a[k], v
else
a[k] = v
a
report_compact_failure_strings: (inp, exp, out) -> [((@to_json a for a in inp).join ", "), @to_json(exp), @to_json(out)]
report_compact: (results) ->
for [name, test_results...] in results
process.stdout.write name
for [status, index, name, inp, exp, out] in test_results
if status then process.stdout.write " #{index}"
else
[inp_string, exp_string, out_string] = @report_compact_failure_strings inp, exp, out
process.stdout.write [
"\n failure #{name} #{index}"
"inp #{inp_string}"
"exp #{exp_string}"
"out #{out_string}"
].join "\n "
console.log ""
constructor: (options) ->
default_options =
reporter: @report_compact
@options = @object_merge default_options, options
@options.reporter = @options.reporter.bind @
execute_tests: (tests) ->
status = true
for [f, rest...] in tests
break unless status
[name, context] =
if Array.isArray f
[name_or_context, f] = f
if @is_string(name_or_context) then [name_or_context, null] else [f.name, name_or_context]
else [f.name, null]
results = [name]
for i in [0...rest.length] by 2
inp = rest[i]
exp = rest[i + 1]
out = f.apply context, inp
out_string = @to_json out
exp_string = @to_json exp
status = out_string == exp_string
results.push [status, i / 2, name, inp, exp, out]
break unless status
results
execute: (tests) -> @options.reporter @execute_tests tests