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