Nickolay - Test.Run-0.10
Name
Test.Run.Test - Class, representing the individual test file
SYNOPSIS
t.ok(1 == 1, 'Indeed')
t.is(2 * 2, '4', 'Indeed')
t.pass('Some assertion is correct')
t.done()
DESCRIPTION
Test.Run.Test
is a base testing class in Test.Run hierarchy. Its not supposed to be created manually, instead,
the harness will create it for you.
USAGE
Below is the list of methods, intended for usage in the individual tests.
plan
void plan(Number tests)
This method setups test's plan. When used, it should be called before any assertions were checked.
tests - a number of planned assertions in this test file.
done
void done()
This method indicates that you've done testing and all assertions have been ran. It should be called after any assertions were checked.
diag
void diag(String text)
This method output the diagnostic message. The actual presentation logic of the message is delegated to harness.
text - The text of diagnostic message
pass
void pass(String text)
This method add the passed assertion into results queue.
text - The description of the assertion
fail
void fail(String text)
This method add the failed assertion into results queue.
text - The description of the assertion
ok
void ok(Boolean condition, String text)
This assertion passes when the supplied
condition
evalutes totrue
and fails otherwise.condition - The boolean condition, indicating wheter assertions is passed or failed
text - The description of the assertion
notOk
void notOk(Boolean condition, String text)
This is a reverse of
ok
(test passes when condition is false)
is
void is(Object value1, Object value2, String text)
This assertion passes when comparison of 1st and 2nd arguments shows that they are equal. Comparison is performed with '==' operator
value1 - The 1st value for comparison
value2 - The 2nd value for comparison
text - The description of the assertion
isnt
void isnt(Object value1, Object value2, String text)
This method is a reverse of
is
(passes when the operands are different).
beginAsync
Number beginAsync(Number? maxTime)
This method starts the "asynchronous frame". The test will not finished, until the frame will not be finished with endAsync call. endAsync will be automatically called after specified
maxtime
.maxTime - the maximum time (in ms) to wait until explicitly finalize this async frame. Default time is 10000 ms.
return - The timeoutId, which can be used in endAsync call
endAsync
void endAsync(Number timeoutId)
This method finalize the "asynchronous frame" started with beginAsync.
timeoutId - The timeoutId, returned by beginAsync call
like
void like(String str, String|RegExp regex, String text)
This assertion passes when the passed
str
(1st argument) matches to a regular expressionregex
(2nd argument)str - The string to test
regex - The regex against which to test the string, can be also a plain string
text - The description of the assertion
unlike
void unlike(String str, String|RegExp regex, String text)
This method is the opposite of 'like', it adds failed assertion, when the string matches the passed regex.
str - The string to test
regex - The regex against which to test the string, can be also a plain string
text - The description of the assertion
throwsOk
void throwsOk(Function func, String|RegExp expected, String text)
This assertion is passed, when the
func
function throws the exception during executing, and the stringified exception passes the 'like' assertion (with 'expected' parameter). This method has a synonym: throws_okfunc - The function which supposed to throw an exception
expected - The regex against which to test the stringified exception, can be also a plain string
text - The description of the assertion
livesOk
void livesOk(Function func, String text)
This assertion passes, when the supplied
func
function doesn't throw the exception during execution. This method has a synonym: lives_okfunc - The function which supposed to not throw an exception
text - The description of the assertion
isaOk
void isaOk(Object value, Function/String class, String text)
This assertion passes, when the supplied
value
is the instance of theclass
. The check is performed withinstanceof
operator. Theclass
parameter can be supplied as class constructor or as string, representing the class name. In this case theclass
will eval'ed to receive the class constructor.
This method has a synonym: isa_ok
value - The value to check for 'isa' relationship
class - The class to check for 'isa' relationship with
value
text - The description of the assertion
skipIf
void skipIf(Boolean condition, String why, Function code, Number? howMany)
This methods check the supplied
condition
and if its true then do not executes the supplied code. Instead, it addshowMany
pseudo-passed assertions to the test suite. If the condition is false, then it just run thecode
function.
This method is useful for skipping parts of the test suite, for example if the functionality being tested is not supported on the current platform.
condition - The boolean condition, indicating whether to run or skip the
code
why - The reason for the skip
code - A function, wrapping the assertions which needs to be skipped
howMany - Optional. A number of pseudo-passed assertions to add, when skipping real ones. Defaults to 1.
skip
void skip(String why, Function code, Number? howMany)
Unconditional
skipIf
(always skips the code).
todo
void todo(String why, Function code)
With this method you can mark part of the test suite as "todo", assuming it most probably will fail, but its still worth to try run them.
The supplied
code
function will be run, it will receive a new test instance as the 1st argument, which must be used for assertions checks (not the primary test instance, received fromStartTest
).Assertions, failed inside the
code
block will be treated by harness normally. Assertions, passed inside thecode
block will be treated by harness as bonus ones and highlighted.why - The reason/description for the todo
code - A function, wrapping the "todo" assertions. This function will receive a special test class instance which should be used for assertions checks.
SEE ALSO
General documentation for Joose: http://openjsan.org/go/?l=Joose
BUGS
All complex software has bugs lurking in it, and this module is no exception.
Please report any bugs through the web interface at http://github.com/SamuraiJack/test.run/issues
AUTHORS
Nickolay Platonov nplatonov@cpan.org
COPYRIGHT AND LICENSE
Copyright (c) 2010, Nickolay Platonov
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
- Neither the name of Nickolay Platonov nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Class('Test.Run.Test', { does : [ Test.Run.Test.More ], have : { url : null, assertPlanned : null, assertCount : 0, results : null, run : null, harness : null, failed : false, failedException : null, startDate : null, endDate : null, topScope : null, transparentEx : false, passThroughEx : false, isDone : false, timeoutsCount : 0, timeoutIds : null, processed : false, callback : null }, after : { initialize : function (config) { if (Object.prototype.toString.call(this.run) != "[object Function]") throw "The body of test absent" this.results = [] this.timeoutIds = {} } }, methods : { toString : function() { return this.url }, plan : function (value) { if (this.assertPlanned != null) throw "Test plan can't be changed" this.assertPlanned = value }, addResult : function (result) { if (this.isDone || this.isFinished()) throw "Adding assertions after the test has been already done" if (result instanceof Test.Run.Result.Assertion) result.index = ++this.assertCount this.results.push(result) this.harness.onTestUpdate(this, result) }, diag : function (desc) { this.addResult(new Test.Run.Result.Diagnostic({ description : desc })) }, pass : function (desc) { this.addResult(new Test.Run.Result.Assertion({ passed : true, description : desc })) }, fail : function (desc) { this.addResult(new Test.Run.Result.Assertion({ passed : false, description : desc })) }, eachAssertion : function (func, scope) { scope = scope || this var index = 0 Joose.A.each(this.results, function (result) { if (result instanceof Test.Run.Result.Assertion) func.call(scope, result, index++) }) }, ok : function (condition, desc) { if (condition) this.pass(desc) else this.fail(desc) }, notOk : function (condition, desc) { this.ok(!condition, desc) }, is : function (got, expected, desc) { this.ok(got == expected, desc) }, isnt : function (got, expected, desc) { this.ok(got != expected, desc) }, beginAsync : function (time) { var me = this // in NodeJS `setTimeout` returns an object and not a simple ID, so we try hard to store that object under unique index var timeoutId = this.topScope.setTimeout(function () { me.endAsync(timeoutId) }, time || 1e4) var index = this.timeoutsCount++ this.timeoutIds[ index ] = timeoutId return index }, endAsync : function (index) { var counter = 0 if (index == null) Joose.O.each(this.timeoutIds, function (timeoutId, indx) { index = indx if (counter++) throw "Calls to endAsync without argument should only be performed if you have single beginAsync statement" }) var timeoutId = this.timeoutIds[ index ] this.topScope.clearTimeout(timeoutId) delete this.timeoutIds[ index ] var me = this if (this.processed) // to allow potential call to `done` after `endAsync` setTimeout(function (){ me.finalize() }, 1) }, clearTimeouts : function () { var me = this Joose.O.each(this.timeoutIds, function (value, id) { me.topScope.clearTimeout(value) }) this.timeoutIds = {} }, skipIf : function (condition, why, code, howMany) { howMany = howMany || 1 if (condition) { for (var i = 1; i <= howMany; i++) this.addResult(new Test.Run.Result.Assertion({ passed : true, isSkipped : true, description : 'SKIPPED: ' + why })) } else code() }, skip : function (why, code, howMany) { this.skipIf(true, why, code, howMany) }, todo : function (why, code) { var todo = new Test.Run.Test.Todo({ parent : this, run : function () {} }) this.topScope.__EXCEPTION_CATCHER__(function(){ code(todo) }) }, start : function (callback) { this.callback = callback this.startDate = new Date() this.harness.onTestStart(this) var me = this var run = this.run if (this.transparentEx) run(me) else var e = this.topScope.__EXCEPTION_CATCHER__(function(){ run(me) }) if (e) { this.failed = true this.failedException = e this.harness.onTestFail(this, e) this.finalize(true) if (this.passThroughEx) throw e return } this.finalize() }, finalize : function (force) { if (this.isFinished()) return this.processed = true if (force) this.clearTimeouts() if (!Joose.O.isEmpty(this.timeoutIds)) return this.endDate = new Date() this.harness.onTestEnd(this) this.callback && this.callback() }, getSummaryMessage : function (lineBreaks) { var res = [] var passCount = this.getPassCount() var failCount = this.getFailCount() var assertPlanned = this.assertPlanned var total = failCount + passCount res.push('Passed: ' + passCount) res.push('Failed: ' + failCount) if (!this.failed) { if (assertPlanned != null) { if (total < assertPlanned) res.push('Looks like you planned ' + assertPlanned + ' tests, but ran only ' + total) if (total > assertPlanned) res.push('Looks like you planned ' + assertPlanned + ' tests, but ran ' + (total - assertPlanned) + ' extra tests, ' + total + ' total.') if (total == assertPlanned && !failCount) res.push('All tests successfull') } else if (this.isDone && !failCount) res.push('All tests successfull') } else { res.push('Test suite threw an exception: ' + this.failedException) } return res.join(lineBreaks || '') }, done : function () { this.isDone = true if (this.processed) this.finalize() }, getPassCount : function () { var passCount = 0 this.eachAssertion(function (assertion) { if (assertion.passed && !assertion.isTodo) passCount++ }) return passCount }, getFailCount : function () { var failCount = 0 this.eachAssertion(function (assertion) { if (!assertion.passed && !assertion.isTodo) failCount++ }) return failCount }, isPassed : function () { var passCount = this.getPassCount() var failCount = this.getFailCount() var assertPlanned = this.assertPlanned return !this.failed && !failCount && ( (assertPlanned != null && passCount == assertPlanned) || (assertPlanned == null) && this.isDone ) }, isFinished : function () { return this.endDate != null }, getTimeLength : function () { return this.endDate - this.startDate } } }) //eof Test.Run.Test /** Name ==== Test.Run.Test - Class, representing the individual test file SYNOPSIS ======== t.ok(1 == 1, 'Indeed') t.is(2 * 2, '4', 'Indeed') t.pass('Some assertion is correct') t.done() DESCRIPTION =========== `Test.Run.Test` is a base testing class in Test.Run hierarchy. Its not supposed to be created manually, instead, the harness will create it for you. USAGE ===== Below is the list of methods, intended for usage in the individual tests. ### plan > `void plan(Number tests)` > This method setups test's plan. When used, it should be called before any assertions were checked. > **tests** - a number of planned assertions in this test file. ### done > `void done()` > This method indicates that you've done testing and all assertions have been ran. It should be called after any assertions were checked. ### diag > `void diag(String text)` > This method output the diagnostic message. The actual presentation logic of the message is delegated to harness. > **text** - The text of diagnostic message ### pass > `void pass(String text)` > This method add the passed assertion into results queue. > **text** - The description of the assertion ### fail > `void fail(String text)` > This method add the failed assertion into results queue. > **text** - The description of the assertion ### ok > `void ok(Boolean condition, String text)` > This assertion passes when the supplied `condition` evalutes to `true` and fails otherwise. > **condition** - The boolean condition, indicating wheter assertions is passed or failed > **text** - The description of the assertion ### notOk > `void notOk(Boolean condition, String text)` > This is a reverse of `ok` (test passes when condition is false) ### is > `void is(Object value1, Object value2, String text)` > This assertion passes when comparison of 1st and 2nd arguments shows that they are equal. Comparison is performed with '==' operator > **value1** - The 1st value for comparison > **value2** - The 2nd value for comparison > **text** - The description of the assertion ### isnt > `void isnt(Object value1, Object value2, String text)` > This method is a reverse of `is` (passes when the operands are different). ### beginAsync > `Number beginAsync(Number? maxTime)` > This method starts the "asynchronous frame". The test will not finished, until the frame will not be finished with [endAsync] call. [endAsync] will be automatically called after specified `maxtime`. > **maxTime** - the maximum time (in ms) to wait until explicitly finalize this async frame. Default time is 10000 ms. > *return* - The timeoutId, which can be used in [endAsync] call ### endAsync > `void endAsync(Number timeoutId)` > This method finalize the "asynchronous frame" started with [beginAsync]. > **timeoutId** - The timeoutId, returned by [beginAsync] call ### like > `void like(String str, String|RegExp regex, String text)` > This assertion passes when the passed `str` (1st argument) matches to a regular expression `regex` (2nd argument) > **str** - The string to test > **regex** - The regex against which to test the string, can be also a plain string > **text** - The description of the assertion ### unlike > `void unlike(String str, String|RegExp regex, String text)` > This method is the opposite of 'like', it adds failed assertion, when the string matches the passed regex. > **str** - The string to test > **regex** - The regex against which to test the string, can be also a plain string > **text** - The description of the assertion ### throwsOk > `void throwsOk(Function func, String|RegExp expected, String text)` > This assertion is passed, when the `func` function throws the exception during executing, and the stringified exception passes the 'like' assertion (with 'expected' parameter). This method has a synonym: throws_ok > **func** - The function which supposed to throw an exception > **expected** - The regex against which to test the *stringified* exception, can be also a plain string > **text** - The description of the assertion ### livesOk > `void livesOk(Function func, String text)` > This assertion passes, when the supplied `func` function doesn't throw the exception during execution. This method has a synonym: lives_ok > **func** - The function which supposed to not throw an exception > **text** - The description of the assertion ### isaOk > `void isaOk(Object value, Function/String class, String text)` > This assertion passes, when the supplied `value` is the instance of the `class`. The check is performed with `instanceof` operator. The `class` parameter can be supplied as class constructor or as string, representing the class name. In this case the `class` will eval'ed to receive the class constructor. This method has a synonym: isa_ok > **value** - The value to check for 'isa' relationship > **class** - The class to check for 'isa' relationship with `value` > **text** - The description of the assertion ### skipIf > `void skipIf(Boolean condition, String why, Function code, Number? howMany)` > This methods check the supplied `condition` and if its *true* then *do not* executes the supplied code. Instead, it adds `howMany` pseudo-passed assertions to the test suite. If the condition is *false*, then it just run the `code` function. This method is useful for skipping parts of the test suite, for example if the functionality being tested is not supported on the current platform. > **condition** - The boolean condition, indicating whether to run or skip the `code` > **why** - The reason for the skip > **code** - A function, wrapping the assertions which needs to be skipped > **howMany** - Optional. A number of pseudo-passed assertions to add, when skipping real ones. Defaults to 1. ### skip > `void skip(String why, Function code, Number? howMany)` > Unconditional `skipIf` (always skips the code). ### todo > `void todo(String why, Function code)` > With this method you can mark part of the test suite as "todo", assuming it most probably will fail, but its still worth to try run them. >The supplied `code` function will be run, it will receive a new test instance as the 1st argument, which *must* be used for assertions checks (not the primary test instance, received from `StartTest`). >Assertions, failed inside the `code` block will be treated by harness normally. Assertions, passed inside the `code` block will be treated by harness as bonus ones and highlighted. > **why** - The reason/description for the todo > **code** - A function, wrapping the "todo" assertions. This function will receive a special test class instance which should be used for assertions checks. SEE ALSO ======== General documentation for Joose: <http://openjsan.org/go/?l=Joose> BUGS ==== All complex software has bugs lurking in it, and this module is no exception. Please report any bugs through the web interface at <http://github.com/SamuraiJack/test.run/issues> AUTHORS ======= Nickolay Platonov [nplatonov@cpan.org](mailto:nplatonov@cpan.org) COPYRIGHT AND LICENSE ===================== Copyright (c) 2010, Nickolay Platonov All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Nickolay Platonov nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. [Test.Run.Result]: Result.html [Test.Run.Harness]: Harness.html */