Simple to use test engine for Metarhia technology stack
npm install metatests





metatests is an extremely simple to use test framework and runner for Metarhia
technology stack built on the following principles:
- Test cases are files, tests are either imperative (functions) or declarative
(arrays and structures).
- Assertions are done using the built-in Node.js assert module. The framework
also provides additional testing facilities (like spies).
- Tests can be run in parallel.
- All tests are executed in isolated sandboxes. The framework allows to easily
mock modules required by tests and provides ready-to-use mocks for timers and
other core functionality.
- Testing asynchronous operations must be supported.
- Testing pure functions without asynchronous operations and state can be done
without extra boilerplate code using DSL based on arrays.
``javascript`
mt.case(
'Test common.duration',
{ common },
{
// ...
'common.duration': [
['1d', 86400000],
['10h', 36000000],
['7m', 420000],
['13s', 13000],
['2d 43s', 172843000],
// ...
],
// ...
},
);
- The framework must work in Node.js and browsers (using Webpack or any other
module bundler that supports CommonJS modules and emulates Node.js globals).
- See github for full contributors list
- Interface metatests
- case
- DeclarativeTest
- DeclarativeTest.prototype.constructor
- DeclarativeTest.prototype.run
- DeclarativeTest.prototype.runNow
- equal
- strictEqual
- reporters.Reporter
- reporters.Reporter.prototype.constructor
- reporters.Reporter.prototype.error
- reporters.Reporter.prototype.finish
- reporters.Reporter.prototype.log
- reporters.Reporter.prototype.logComment
- reporters.Reporter.prototype.record
- reporters.ConciseReporter
- reporters.ConciseReporter.prototype.constructor
- reporters.ConciseReporter.prototype.error
- reporters.ConciseReporter.prototype.finish
- reporters.ConciseReporter.prototype.listFailure
- reporters.ConciseReporter.prototype.parseTestResults
- reporters.ConciseReporter.prototype.printAssertErrorSeparator
- reporters.ConciseReporter.prototype.printSubtestSeparator
- reporters.ConciseReporter.prototype.printTestSeparator
- reporters.ConciseReporter.prototype.record
- reporters.TapReporter
- reporters.TapReporter.prototype.constructor
- reporters.TapReporter.prototype.error
- reporters.TapReporter.prototype.finish
- reporters.TapReporter.prototype.listFailure
- reporters.TapReporter.prototype.logComment
- reporters.TapReporter.prototype.parseTestResults
- reporters.TapReporter.prototype.record
- runner.Runner
- runner.Runner.prototype.constructor
- runner.Runner.prototype.addTest
- runner.Runner.prototype.finish
- runner.Runner.prototype.removeReporter
- runner.Runner.prototype.resume
- runner.Runner.prototype.runTodo
- runner.Runner.prototype.setReporter
- runner.Runner.prototype.wait
- runner.instance
- speed
- measure
- convertToCsv
- ImperativeTest
- ImperativeTest.prototype.constructor
- ImperativeTest.prototype.afterEach
- ImperativeTest.prototype.assert
- ImperativeTest.prototype.assertNot
- ImperativeTest.prototype.bailout
- ImperativeTest.prototype.beforeEach
- ImperativeTest.prototype.case
- ImperativeTest.prototype.cb
- ImperativeTest.prototype.cbFail
- ImperativeTest.prototype.contains
- ImperativeTest.prototype.containsGreedy
- ImperativeTest.prototype.defer
- ImperativeTest.prototype.doesNotThrow
- ImperativeTest.prototype.end
- ImperativeTest.prototype.endAfterSubtests
- ImperativeTest.prototype.equal
- ImperativeTest.prototype.error
- ImperativeTest.prototype.fail
- ImperativeTest.prototype.is
- ImperativeTest.prototype.isArray
- ImperativeTest.prototype.isBuffer
- ImperativeTest.prototype.isError
- ImperativeTest.prototype.isRejected
- ImperativeTest.prototype.isResolved
- ImperativeTest.prototype.mustCall
- ImperativeTest.prototype.mustNotCall
- ImperativeTest.prototype.notEqual
- ImperativeTest.prototype.notOk
- ImperativeTest.prototype.notSameTopology
- ImperativeTest.prototype.ok
- ImperativeTest.prototype.on
- ImperativeTest.prototype.pass
- ImperativeTest.prototype.plan
- ImperativeTest.prototype.regex
- ImperativeTest.prototype.rejects
- ImperativeTest.prototype.resolves
- ImperativeTest.prototype.run
- ImperativeTest.prototype.same
- ImperativeTest.prototype.sameTopology
- ImperativeTest.prototype.strictEqual
- ImperativeTest.prototype.strictNotSame
- ImperativeTest.prototype.strictSame
- ImperativeTest.prototype.test
- ImperativeTest.prototype.testAsync
- ImperativeTest.prototype.testSync
- ImperativeTest.prototype.throws
- ImperativeTest.prototype.type
- test
- testSync
- testAsync
#### case(caption, namespace, list, runner)
- caption: [][string] case captionnamespace
- : [
Create declarative test
#### class DeclarativeTest extends Test
##### DeclarativeTest.prototype.constructor(caption, namespace, list, options)
##### DeclarativeTest.prototype.run()
##### DeclarativeTest.prototype.runNow()
#### equal(val1, val2)
#### strictEqual(val1, val2)
#### class reporters.Reporter
##### reporters.Reporter.prototype.constructor(options)
- options: [][object]stream
- : optional
##### reporters.Reporter.prototype.error(test, error)
- test: error
- : [][error]
Fail test with error
##### reporters.Reporter.prototype.finish()
##### reporters.Reporter.prototype.log(...args)
##### reporters.Reporter.prototype.logComment(...args)
##### reporters.Reporter.prototype.record(test)
- test:
Record test
#### class reporters.ConciseReporter extends Reporter
##### reporters.ConciseReporter.prototype.constructor(options)
##### reporters.ConciseReporter.prototype.error(test, error)
##### reporters.ConciseReporter.prototype.finish()
##### reporters.ConciseReporter.prototype.listFailure(test, res, message)
##### reporters.ConciseReporter.prototype.parseTestResults(test, subtest)
##### reporters.ConciseReporter.prototype.printAssertErrorSeparator()
##### reporters.ConciseReporter.prototype.printSubtestSeparator()
##### reporters.ConciseReporter.prototype.printTestSeparator()
##### reporters.ConciseReporter.prototype.record(test)
#### class reporters.TapReporter extends Reporter
##### reporters.TapReporter.prototype.constructor(options)
##### reporters.TapReporter.prototype.error(test, error)
##### reporters.TapReporter.prototype.finish()
##### reporters.TapReporter.prototype.listFailure(test, res, offset)
##### reporters.TapReporter.prototype.logComment(...args)
##### reporters.TapReporter.prototype.parseTestResults(test, offset = 0)
##### reporters.TapReporter.prototype.record(test)
#### class runner.Runner extends EventEmitter
##### runner.Runner.prototype.constructor(options)
##### runner.Runner.prototype.addTest(test)
##### runner.Runner.prototype.finish()
##### runner.Runner.prototype.removeReporter()
##### runner.Runner.prototype.resume()
##### runner.Runner.prototype.runTodo(active = true)
##### runner.Runner.prototype.setReporter(reporter)
##### runner.Runner.prototype.wait()
#### runner.instance
- [][runner]
#### speed(caption, count, cases)
- caption: [][string] name of the benchmarkcount
- : [][number] amount of times ro run each functioncases
- : [][array] functions to check
Microbenchmark each passed function and compare results.
#### measure(cases\[, options\])
- cases: [][array] cases to test, each case containsfn
- : [][function] function to check, will be called with eachname
args provided
- : [][string] case name, function.name by defaultargCases
- : [][array] array of arguments to create runs with. Whenfn
omitted will be run once without arguments. Total amount of runs willruns * argCases.length
be .n
- : [][number] number of times to run the test, defaultCount fromoptions
options by default
- : [][object]defaultCount
- : [][number] number of times to run the function byruns
default, default: 1e6
- : [][number] number of times to run the case, default: 20preflight
- : [][number] number of times to pre-run the case forpreflightCount
each set of arguments, default: 10
- : [][number] number of times to run the functionlistener
in the preflight stage, default: 1e4
- : [][object] appropriate function will be called topreflight
report events, optional
- : [][function] called when preflight is starting,name
optional
- : [][string] case namecount
- : [][number] number of times it will be runargs
- : [][array] function argumentsrun
- : [][function] called when run is starting, optionalname
- : [][string] case namecount
- : [][number] number of times it will be runargs
- : [][array] function argumentscycle
- : [][function] called when run is done, optionalname
- : [][string] case nameresult
- : [][object] case resultsdone
- : [][function] called when all runs for givenname
configurations are done, optional
- : [][string] case nameargs
- : [][array] current configurationresults
- : [][array] results of all runs with thisfinish
configuration
- : [][function] called when measuring is finished,results
optional
- : [][array] all case results
_Returns:_ [][array] results of all cases as objects of structure
- name: [][string] case nameargs
- : [][array] arguments for this runcount
- : [][number] number of times case was runtime
- : [][number] time in nanoseconds it took to make count runsresult
- : result of one of the runs
Microbenchmark each passed configuration multiple times
#### convertToCsv(results)
- results: [][array] all results from measure run
_Returns:_ [][string] valid CSV representation of the results
Convert metatests.measure result to csv.
#### class ImperativeTest extends Test
##### ImperativeTest.prototype.constructor(caption, func, options)
##### ImperativeTest.prototype.afterEach(func)
- func: [][function]subtest
- : test instancecallback
- : [][function]
- _Returns:_ [][promise]|
Set a function to run after each subtest.
The function must either return a promise or call a callback.
##### ImperativeTest.prototype.assert(value\[, message\])
- value: value to checkmessage
- : [][string] description of the check, optional
Check if value is truthy.
##### ImperativeTest.prototype.assertNot(value\[, message\])
- value: value to checkmessage
- : [][string] description of the check, optional
Check if value is falsy.
##### ImperativeTest.prototype.bailout(\[err\]\[, message\])
- err: [][error] bailout errormessage
- : [][string] bailout message
Fail this test and throw an error.
If both err and message are provided err.toString() will be appended tomessage.
##### ImperativeTest.prototype.beforeEach(func)
- func: [][function]subtest
- : test instancecallback
- : [][function]context
- : context of the test. It will pe passed as a secondtest.context
argument to test function and is available at
- _Returns:_ [][promise]| nothing or Promise resolved
with context
Set a function to run before each subtest.
The function must either return a promise or call a callback.
##### ImperativeTest.prototype.case(message, namespace, list, options = {})
Create a declarative [case()][case()] subtest of this test.
##### ImperativeTest.prototype.cb(\[msg\]\[, cb\])
- msg: [][string] test.error messagecb
- : [][function] callback function
_Returns:_ [][function] function to pass to callback
Create error-first callback wrapper to perform automatic checks.
This will check for [test.mustCall()][test.mustcall()] the callback and{test.error()} the first callback argument.
##### ImperativeTest.prototype.cbFail(\[fail\]\[, cb\[, afterAllCb\]\])
- fail: [][string] test.fail messagecb
- : [][function] callback function to call if there was no errorafterAllCb
- : [][function] function called after callback handling
_Returns:_ [][function] function to pass to callback
Create error-first callback wrapper to fail test if call fails.
This will check for [test.mustCall()][test.mustcall()] the callback and if thetest.fail()
call errored will use [][test.fail()] andtest.end()
[][test.end()]
##### ImperativeTest.prototype.contains(actual, subObj\[, message\[, sort\[, test\]\]\])
- actual: actual datasubObj
- : expected propertiesmessage
- : [][string] description of the check, optionalsort
- : if true or a sort function sort datacmp
properties, default: false
- : [][function] test function, default: compare.strictEqualactual
- : expected
- :
- _Returns:_ [][boolean] true if actual is equal to expected, false
otherwise
Check that actual contains all properties of subObj.
Properties will be compared with test function.
##### ImperativeTest.prototype.containsGreedy(actual, subObj\[, message\[, sort\[, test\]\]\])
- actual: actual datasubObj
- : expected propertiesmessage
- : [][string] description of the check, optionalcmp
- : [][function] test function, default: compare.strictEqualactual
- : expected
- :
- _Returns:_ [][boolean] true if actual is equal to expected, false
otherwise
Check greedily that actual contains all properties of subObj.
Similar to [test.contains()][test.contains()] but will succeed if at least one
of the properties in actual match the one in subObj.
##### ImperativeTest.prototype.defer(fn, options)
- fn: [][function] function to call before the end of test. Canoptions
return a promise that will defer the end of test.
- : [][object]ignoreErrors
- : [][boolean] ignore errors from fn function,false
default:
Defer a function call until the 'before' end of test.
##### ImperativeTest.prototype.doesNotThrow(fn\[, message\])
- fn: [][function] function to runmessage
- : [][string] description of the check, optional
Check that fn doesn't throw.
##### ImperativeTest.prototype.end()
Finish the test.
This will fail if the test has unfinished subtests or plan is not complete.
##### ImperativeTest.prototype.endAfterSubtests()
Mark this test to call end after its subtests are done.
##### ImperativeTest.prototype.equal(actual, expected\[, message\])
- actual: actual dataexpected
- : expected datamessage
- : [][string] description of the check, optional
Compare actual and expected for non-strict equality.
##### ImperativeTest.prototype.error(err\[, message\])
- err: error to checkmessage
- : [][string] description of the check, optional
Fail if err is instance of Error.
##### ImperativeTest.prototype.fail(\[message\]\[, err\])
- message: failure message or error, optionalerr
- : [][error] error, optional
Fail this test recording failure message.
This doesn't call [test.end()][test.end()].
##### ImperativeTest.prototype.is(checkFn, val\[, message\])
- checkFn: [][function] condition functionval
- : provided value
- _Returns:_ [][boolean] true if condition is satisfied and falseval
otherwise
- : value to check the condition againstmessage
- : [][string] check message, optional
Check whether val satisfies custom checkFn condition.
##### ImperativeTest.prototype.isArray(val\[, message\])
- val: value to checkmessage
- : [][string] check message, optional
Check if val satisfies Array.isArray.
##### ImperativeTest.prototype.isBuffer(val\[, message\])
- val: value to checkmessage
- : [][string] check message, optional
Check if val satisfies Buffer.isBuffer.
##### ImperativeTest.prototype.isError(actual\[, expected\[, message\]\])
- actual: actual error to compareexpected
- : expected error, default: new Error()message
- : [][string] description of the check, optional
Check if actual is equal to expected error.
##### ImperativeTest.prototype.isRejected(input, err)
- input: promise of function returning thenableerr
- : value to be checked with [test.isError()][test.iserror()]
against rejected value
Check that input rejects.
##### ImperativeTest.prototype.isResolved(input\[, expected\])
- input: promise of function returning thenableexpected
- : if passed it will be checked withtest.strictSame()
[][test.strictsame()] against resolved value
Verify that input resolves.
##### ImperativeTest.prototype.mustCall(\[fn\[, count\[, name\]\]\])
- fn: [][function] function to be checked, default: () => {}count
- : [][number] amount of times fn must be called, default: 1name
- : [][string] name of the function, default: 'anonymous'
_Returns:_ [][function] function to check with, will forward all
arguments to fn, and result from fn
Check that fn is called specified amount of times.
##### ImperativeTest.prototype.mustNotCall(\[fn\[, name\]\])
- fn: [][function] function to not be checked, default: () => {}name
- : [][string] name of the function, default: 'anonymous'
_Returns:_ [][function] function to check with, will forward all
arguments to fn, and result from fn
Check that fn is not called.
##### ImperativeTest.prototype.notEqual(actual, expected\[, message\])
- actual: actual dataexpected
- : expected datamessage
- : [][string] description of the check, optional
Compare actual and expected for non-strict not-equality.
##### ImperativeTest.prototype.notOk(value\[, message\])
- value: value to checkmessage
- : [][string] description of the check, optional
Check if value is falsy.
##### ImperativeTest.prototype.notSameTopology(obj1, obj2\[, message\])
- obj1: actual dataobj2
- : expected datamessage
- : [][string] description of the check, optional
Compare actual and expected to not have the same topology.
##### ImperativeTest.prototype.ok(value\[, message\])
- value: value to checkmessage
- : [][string] description of the check, optional
Check if value is truthy.
##### ImperativeTest.prototype.on(name, listener)
##### ImperativeTest.prototype.pass(\[message\])
- message: [][string] message to record
Record a passing assertion.
##### ImperativeTest.prototype.plan(n)
- n: [][number] amount of assertions
Plan this test to have exactly n assertions and end test after
this amount of assertions is reached.
##### ImperativeTest.prototype.regex(regex, input\[, message\])
- regex: [][regexp]|[][string] pattern to matchinput
- : [][string] input to checkmessage
- : [][string]
Test whether input matches the provided RegExp.
##### ImperativeTest.prototype.rejects(input, err)
- input: promise of function returning thenableerr
- : value to be checked with [test.isError()][test.iserror()]
against rejected value
Check that input rejects.
##### ImperativeTest.prototype.resolves(input\[, expected\])
- input: promise of function returning thenableexpected
- : if passed it will be checked withtest.strictSame()
[][test.strictsame()] against resolved value
Verify that input resolves.
##### ImperativeTest.prototype.run()
Start running the test.
##### ImperativeTest.prototype.same(actual, expected\[, message\])
- actual: actual dataexpected
- : expected datamessage
- : [][string] description of the check, optional
Compare actual and expected for non-strict equality.
##### ImperativeTest.prototype.sameTopology(obj1, obj2\[, message\])
- obj1: actual dataobj2
- : expected datamessage
- : [][string] description of the check, optional
Compare actual and expected to have same topology.
Useful for comparing objects with circular references for equality.
##### ImperativeTest.prototype.strictEqual(actual, expected\[, message\])
- actual: actual dataexpected
- : expected datamessage
- : [][string] description of the check, optional
Compare actual and expected for strict equality.
##### ImperativeTest.prototype.strictNotSame(actual, expected\[, message\])
- actual: actual dataexpected
- : expected datamessage
- : [][string] description of the check, optional
Compare actual and expected for strict non-equality.
##### ImperativeTest.prototype.strictSame(actual, expected\[, message\])
- actual: actual dataexpected
- : expected datamessage
- : [][string] description of the check, optional
Compare actual and expected for strict equality.
##### ImperativeTest.prototype.test(caption, func, options)
- caption: [][string] name of the testfunc
- : [][function] test functiontest
- : test instanceoptions
- : run
- : [][boolean] auto start test, default: trueasync
- : [][boolean] if true do nothing, if false auto-end testfunc
on nextTick after run, default: truetimeout
- : [][number] time in milliseconds after which test isparallelSubtests
considered timeouted.
- : [][boolean] if true subtests will be run independentSubtests
parallel, otherwise subtests are run sequentially, default: false
- : [][boolean] if true each subtest will be
executed sequentially in order of addition to the parent test
short-circuiting if any subtest fails, default: false
_Returns:_ subtest instance
Create a subtest of this test.
If the subtest fails this test will fail as well.
##### ImperativeTest.prototype.testAsync(message, func, options = {})
Create an asynchronous subtest of this test.
Simple wrapper for [test.test()][test.test()] setting async option totrue.
##### ImperativeTest.prototype.testSync(message, func, options = {})
Create a synchronous subtest of this test
Simple wrapper for [test.test()][test.test()] setting async option tofalse.
##### ImperativeTest.prototype.throws(fn\[, expected\[, message\]\])
- fn: [][function] function to runexpected
- : expected error, default: new Error()message
- : [][string] description of the check, optional
Check that fn throws expected error.
##### ImperativeTest.prototype.type(obj, type\[, message\])
- obj: value to checktype
- : class or class name to checkmessage
- : [][string] description of the check, optional
Check if obj is of specified type.
#### test(caption, func\[, options\[, runner\]\])
- caption: [][string] name of the testfunc
- : [][function] test functiontest
- : test instanceoptions
- : run
- : [][boolean] auto start test, default: trueasync
- : [][boolean] if true do nothing, if false auto-end testfunc
on nextTick after run, default: truetimeout
- : [][number] time in milliseconds after which test isparallelSubtests
considered timeouted.
- : [][boolean] if true subtests will be run independentSubtests
parallel, otherwise subtests are run sequentially, default: false
- : [][boolean] if true each subtest will berunner
executed sequentially in order of addition to the parent test
short-circuiting if any subtest fails, default: false
- : [][runner] runner instance to use to run this test
_Returns:_ test instance
Create a test case.
#### testSync(caption, func, options = {}, runner = runnerInstance)
Create a synchronous test
Simple wrapper for [test()][test()] setting async option to false.
#### testAsync(caption, func, options = {}, runner = runnerInstance)
Create an asynchronous test
Simple wrapper for [test()][test()] setting async option to true`.
[object]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object
[function]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function
[regexp]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp
[promise]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
[array]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array
[error]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error
[boolean]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Boolean_type
[number]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Number_type
[string]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#String_type
[runner]: #class-runnerrunner-extends-eventemitter
[test()]: #testcaption-func-options-runner
[test.test()]: #imperativetestprototypetestcaption-func-options
[test.strictsame()]: #imperativetestprototypestrictsameactual-expected-message
[test.contains()]: #imperativetestprototypecontainsactual-subobj-message-sort-test
[test.mustcall()]: #imperativetestprototypemustcallfn-count-name
[test.iserror()]: #imperativetestprototypeiserroractual-expected-message
[test.fail()]: #imperativetestprototypefailmessage-err
[test.end()]: #imperativetestprototypeend
[case()]: #casecaption-namespace-list-runner