diff options
| author | Xavier Morel <xmo@openerp.com> | 2012-11-16 08:17:12 +0100 |
|---|---|---|
| committer | Xavier Morel <xmo@openerp.com> | 2012-11-16 08:17:12 +0100 |
| commit | a9645151b6f070d23d2f35810aee562c1354aba9 (patch) | |
| tree | 04a4265b454d75291001a49ee4285b1faab63f92 /addons/web/static/test/testing.js | |
| parent | 8e85f4e0bd0b1fbbf401686b85d7282f8991454d (diff) | |
[IMP] setup & teardown of test runner
simplify code and make setup & teardown processes more reliable
add testing.Stack tools which stacks promise-returning functions
around the actual promise-returning function to execute (the test case
itself).
testing.Stack returns an object with 3 methods, ``push([setup][,
teardown])``, ``unshift([setup][, teardown])`` and ``execute(fn,
*args)``. ``push`` and ``unshift`` create a new stack with the
provided setup and teardown added respectively at the top and bottom
of the stack.
``execute`` will walk the stack from bottom to top executing ``setup``
handlers (and waiting on their result), if all setup handlers execute
without failure the ``fn`` callback gets executed (and waited on) then
*all* ``teardown`` handlers are executed from top to bottom:
| setup
| setup
| setup
| setup
| fn
| teardown
| teardown
| teardown
V teardown
If a ``setup`` handler fails (the promise is rejected), teardowns will
start executing *from the previous level* (so the ``teardown``
matching the failed ``setup`` will *not* be run), but all
``teardowns`` below that will be run regardless, even if one fails the
next one will still be executed.
The stack will either ultimately return a promise rejection using the
*first* rejection it got (a rejection may be cascading, so the
rejection of a setup may also lead to or be linked to a teardown being
rejected later), or will return the resolution from ``fn``.
If ``execute`` is passed further arguments, those arguments will in
turn be forwarded to ``fn`` as well as all ``setup`` and ``teardown``
handlers.
bzr revid: xmo@openerp.com-20121116071712-zuld957icellezum
Diffstat (limited to 'addons/web/static/test/testing.js')
| -rw-r--r-- | addons/web/static/test/testing.js | 253 |
1 files changed, 253 insertions, 0 deletions
diff --git a/addons/web/static/test/testing.js b/addons/web/static/test/testing.js new file mode 100644 index 00000000000..919143ab533 --- /dev/null +++ b/addons/web/static/test/testing.js @@ -0,0 +1,253 @@ +openerp.testing.section('testing.stack', function (test) { + // I heard you like tests, so I put tests in your testing infrastructure, + // so you can test what you test + var reject = function () { + // utility function, rejects a success + var args = _.toArray(arguments); + return $.Deferred(function (d) { + d.reject.apply(d, ["unexpected success"].concat(args)); + }); + }; + test('direct, value, success', {asserts: 1}, function () { + var s = openerp.testing.Stack(); + return s.execute(function () { + return 42; + }).then(function (val) { + strictEqual(val, 42, "should return the handler value"); + }); + }); + test('direct, deferred, success', {asserts: 1}, function () { + var s = openerp.testing.Stack(); + return s.execute(function () { + return $.when(42); + }).then(function (val) { + strictEqual(val, 42, "should return the handler value") + }); + }); + test('direct, value, error', {asserts: 1}, function () { + var s = openerp.testing.Stack(); + return s.execute(function () { + throw new Error("foo"); + }).pipe(reject, function (f) { + strictEqual(f.message, "foo", "should reject with exception"); + return $.when(); + }); + }); + test('direct, deferred, failure', {asserts: 1}, function () { + var s = openerp.testing.Stack(); + return s.execute(function () { + return $.Deferred(function (d) { + d.reject("failed"); + }); + }).pipe(reject, function (f) { + strictEqual(f, "failed", "should propagate failure"); + return $.when(); + }); + }); + + test('successful setup', {asserts: 2}, function () { + var setup_done = false; + var s = openerp.testing.Stack(); + return s.push(function () { + return $.Deferred(function (d) { + setTimeout(function () { + setup_done = true; + d.resolve(2); + }, 50); + }); + }).execute(function () { + return 42; + }).then(function (val) { + ok(setup_done, "should have executed setup"); + strictEqual(val, 42, "should return executed function value (not setup)"); + }); + }); + test('successful teardown', {asserts: 2}, function () { + var teardown = false; + var s = openerp.testing.Stack(); + return s.push(null, function () { + return $.Deferred(function (d) { + setTimeout(function () { + teardown = true; + d.resolve(2); + }, 50); + }); + }).execute(function () { + return 42; + }).then(function (val) { + ok(teardown, "should have executed teardown"); + strictEqual(val, 42, "should return executed function value (not setup)"); + }); + }); + test('successful setup and teardown', {asserts: 3}, function () { + var setup = false, teardown = false; + var s = openerp.testing.Stack(); + return s.push(function () { + return $.Deferred(function (d) { + setTimeout(function () { + setup = true; + d.resolve(2); + }, 50); + }); + }, function () { + return $.Deferred(function (d) { + setTimeout(function () { + teardown = true; + d.resolve(2); + }, 50); + }); + }).execute(function () { + return 42; + }).then(function (val) { + ok(setup, "should have executed setup"); + ok(teardown, "should have executed teardown"); + strictEqual(val, 42, "should return executed function value (not setup)"); + }); + }); + + test('multiple setups', {asserts: 2}, function () { + var setups = 0; + var s = openerp.testing.Stack(); + return s.push(function () { + setups++; + }).push(function () { + setups++; + }).push(function () { + setups++; + }).push(function () { + setups++; + }).execute(function () { + return 42; + }).then(function (val) { + strictEqual(setups, 4, "should have executed all setups of stack"); + strictEqual(val, 42); + }); + }); + test('multiple teardowns', {asserts: 2}, function () { + var teardowns = 0; + var s = openerp.testing.Stack(); + return s.push(null, function () { + teardowns++; + }).push(null, function () { + teardowns++; + }).push(null, function () { + teardowns++; + }).push(null, function () { + teardowns++; + }).execute(function () { + return 42; + }).then(function (val) { + strictEqual(teardowns, 4, "should have executed all teardowns of stack"); + strictEqual(val, 42); + }); + }); + test('holes in setups', {asserts: 2}, function () { + var setups = []; + var s = openerp.testing.Stack(); + return s.push(function () { + setups.push(0); + }).push().push().push(function () { + setups.push(3); + }).push(function () { + setups.push(4); + }).push().push(function () { + setups.push(6); + }).execute(function () { + return 42; + }).then(function (val) { + deepEqual(setups, [0, 3, 4, 6], + "should have executed setups in correct order"); + strictEqual(val, 42); + }); + }); + test('holes in teardowns', {asserts: 2}, function () { + var teardowns = []; + var s = openerp.testing.Stack(); + return s.push(null, function () { + teardowns.push(0); + }).push().push().push(null, function () { + teardowns.push(3); + }).push(null, function () { + teardowns.push(4); + }).push().push(null, function () { + teardowns.push(6); + }).execute(function () { + return 42; + }).then(function (val) { + deepEqual(teardowns, [6, 4, 3, 0], + "should have executed teardowns in correct order"); + strictEqual(val, 42); + }); + + }); + + test('failed setup', {asserts: 5}, function () { + var setup, teardown, teardown2, code; + return openerp.testing.Stack().push(function () { + setup = true; + }, function () { + teardown = true; + }).push(function () { + return $.Deferred().reject("Fail!"); + }, function () { + teardown2 = true; + }).execute(function () { + code = true; + return 42; + }).pipe(reject, function (m) { + ok(setup, "should have executed first setup function"); + ok(teardown, "should have executed first teardown function"); + ok(!teardown2, "should not have executed second teardown function"); + strictEqual(m, "Fail!", "should return setup failure message"); + ok(!code, "should not have executed callback"); + return $.when(); + }); + }); + test('failed teardown', {asserts: 2}, function () { + var teardowns = 0; + return openerp.testing.Stack().push(null, function () { + teardowns++; + return $.Deferred().reject('Fail 1'); + }).push(null, function () { + teardowns++; + }).push(null, function () { + teardowns++; + return $.Deferred().reject('Fail 3'); + }).execute(function () { + return 42; + }).pipe(reject, function (m) { + strictEqual(teardowns, 3, + "should have tried executing all teardowns"); + strictEqual(m, "Fail 3", "should return first failure message"); + return $.when(); + }); + }); + test('failed call + teardown', {asserts: 2}, function () { + var teardowns = 0; + return openerp.testing.Stack().push(null, function () { + teardowns++; + }).push(null, function () { + teardowns++; + return $.Deferred().reject('Fail 2'); + }).execute(function () { + return $.Deferred().reject("code"); + }).pipe(reject, function (m) { + strictEqual(teardowns, 2, + "should have tried executing all teardowns"); + strictEqual(m, "code", "should return first failure message"); + return $.when(); + }); + }); + + test('arguments passing', {asserts: 9}, function () { + var asserter = function (a, b, c) { + strictEqual(a, 1); + strictEqual(b, "foo"); + deepEqual(c, {bar: "baz", qux: 42}); + }; + + return openerp.testing.Stack() + .push(asserter, asserter) + .execute(asserter, 1, "foo", {bar: 'baz', qux: 42}); + }); +}); |
