added a way to set planned tests
In order to check that every planned test has actually been executed, a new optional `planned` parameter has been added to `Tester.done()`: ```js casper.test.assert(true); casper.test.assert(true); casper.test.assert(true); casper.test.done(4); ``` Will trigger a failure: ``` fail: 4 tests planned, 3 tests executed. ```
Showing
48 changed files
with
85 additions
and
55 deletions
... | @@ -6,6 +6,8 @@ XXXX-XX-XX, v1.0.0 | ... | @@ -6,6 +6,8 @@ XXXX-XX-XX, v1.0.0 |
6 | 6 | ||
7 | ### Important Changes & Caveats | 7 | ### Important Changes & Caveats |
8 | 8 | ||
9 | #### Casper.evaluate() signature compatibility with PhantomJS | ||
10 | |||
9 | `Casper.evaluate()` method signature is now compatible with PhantomJS' one, so you can now write: | 11 | `Casper.evaluate()` method signature is now compatible with PhantomJS' one, so you can now write: |
10 | 12 | ||
11 | ```js | 13 | ```js |
... | @@ -22,6 +24,27 @@ casper.evaluate(function(a, b) { | ... | @@ -22,6 +24,27 @@ casper.evaluate(function(a, b) { |
22 | }, {a: "foo", b: "bar"}); // true | 24 | }, {a: "foo", b: "bar"}); // true |
23 | ``` | 25 | ``` |
24 | 26 | ||
27 | #### Specification of planned tests #### | ||
28 | |||
29 | In order to check that every planned test has actuall been executed, a new optional `planned` parameter has been added to `Tester.done()`: | ||
30 | |||
31 | ```js | ||
32 | casper.test.assert(true); | ||
33 | casper.test.assert(true); | ||
34 | casper.test.assert(true); | ||
35 | casper.test.done(4); | ||
36 | ``` | ||
37 | |||
38 | Will trigger a failure: | ||
39 | |||
40 | ``` | ||
41 | fail: 4 tests planned, 3 tests executed. | ||
42 | ``` | ||
43 | |||
44 | That's especially useful in case a given test script is abruptly interrupted leaving you with no obvious way to know it and an erroneous success status. | ||
45 | |||
46 | The whole [CapserJS test suite](https://github.com/n1k0/casperjs/tree/master/tests/) has been migrated to use this new feature. | ||
47 | |||
25 | ### Bugfixes & enhancements | 48 | ### Bugfixes & enhancements |
26 | 49 | ||
27 | - fixed [#281](https://github.com/n1k0/casperjs/issues/281) - `Casper.evaluate()` should take an array as context not object | 50 | - fixed [#281](https://github.com/n1k0/casperjs/issues/281) - `Casper.evaluate()` should take an array as context not object | ... | ... |
... | @@ -48,6 +48,7 @@ exports.create = function create(casper, options) { | ... | @@ -48,6 +48,7 @@ exports.create = function create(casper, options) { |
48 | */ | 48 | */ |
49 | var Tester = function Tester(casper, options) { | 49 | var Tester = function Tester(casper, options) { |
50 | "use strict"; | 50 | "use strict"; |
51 | /*jshint maxstatements:20*/ | ||
51 | 52 | ||
52 | if (!utils.isCasperObject(casper)) { | 53 | if (!utils.isCasperObject(casper)) { |
53 | throw new CasperError("Tester needs a Casper instance"); | 54 | throw new CasperError("Tester needs a Casper instance"); |
... | @@ -57,6 +58,7 @@ var Tester = function Tester(casper, options) { | ... | @@ -57,6 +58,7 @@ var Tester = function Tester(casper, options) { |
57 | 58 | ||
58 | this.SKIP_MESSAGE = '__termination__'; | 59 | this.SKIP_MESSAGE = '__termination__'; |
59 | 60 | ||
61 | this.executed = 0; | ||
60 | this.currentTestFile = null; | 62 | this.currentTestFile = null; |
61 | this.currentSuiteNum = 0; | 63 | this.currentSuiteNum = 0; |
62 | this.exporter = require('xunit').create(); | 64 | this.exporter = require('xunit').create(); |
... | @@ -141,6 +143,7 @@ exports.Tester = Tester; | ... | @@ -141,6 +143,7 @@ exports.Tester = Tester; |
141 | */ | 143 | */ |
142 | Tester.prototype.assert = Tester.prototype.assertTrue = function assert(subject, message, context) { | 144 | Tester.prototype.assert = Tester.prototype.assertTrue = function assert(subject, message, context) { |
143 | "use strict"; | 145 | "use strict"; |
146 | this.executed++; | ||
144 | return this.processAssertionResult(utils.mergeObjects({ | 147 | return this.processAssertionResult(utils.mergeObjects({ |
145 | success: subject === true, | 148 | success: subject === true, |
146 | type: "assert", | 149 | type: "assert", |
... | @@ -691,9 +694,14 @@ Tester.prototype.configure = function configure() { | ... | @@ -691,9 +694,14 @@ Tester.prototype.configure = function configure() { |
691 | /** | 694 | /** |
692 | * Declares the current test suite done. | 695 | * Declares the current test suite done. |
693 | * | 696 | * |
697 | * @param Number planned Number of planned tests | ||
694 | */ | 698 | */ |
695 | Tester.prototype.done = function done() { | 699 | Tester.prototype.done = function done(planned) { |
696 | "use strict"; | 700 | "use strict"; |
701 | if (planned > 0 && planned !== this.executed) { | ||
702 | this.fail(f('%s: %d tests planned, %d tests executed', | ||
703 | this.currentTestFile, planned, this.executed)); | ||
704 | } | ||
697 | this.emit('test.done'); | 705 | this.emit('test.done'); |
698 | this.running = false; | 706 | this.running = false; |
699 | }; | 707 | }; |
... | @@ -981,6 +989,7 @@ Tester.prototype.runTest = function runTest(testFile) { | ... | @@ -981,6 +989,7 @@ Tester.prototype.runTest = function runTest(testFile) { |
981 | "use strict"; | 989 | "use strict"; |
982 | this.bar(f('Test file: %s', testFile), 'INFO_BAR'); | 990 | this.bar(f('Test file: %s', testFile), 'INFO_BAR'); |
983 | this.running = true; // this.running is set back to false with done() | 991 | this.running = true; // this.running is set back to false with done() |
992 | this.executed = 0; | ||
984 | this.exec(testFile); | 993 | this.exec(testFile); |
985 | }; | 994 | }; |
986 | 995 | ... | ... |
... | @@ -22,5 +22,5 @@ casper.thenOpen('tests/site/index.html'); | ... | @@ -22,5 +22,5 @@ casper.thenOpen('tests/site/index.html'); |
22 | 22 | ||
23 | casper.run(function() { | 23 | casper.run(function() { |
24 | this.removeListener('resource.requested', fetchUA); | 24 | this.removeListener('resource.requested', fetchUA); |
25 | this.test.done(); | 25 | this.test.done(3); |
26 | }); | 26 | }); | ... | ... |
... | @@ -9,5 +9,6 @@ casper.on('remote.alert', function(message) { | ... | @@ -9,5 +9,6 @@ casper.on('remote.alert', function(message) { |
9 | 9 | ||
10 | casper.start('tests/site/alert.html').run(function() { | 10 | casper.start('tests/site/alert.html').run(function() { |
11 | this.test.assert(ok, 'alert event has been intercepted'); | 11 | this.test.assert(ok, 'alert event has been intercepted'); |
12 | this.test.done(); | 12 | this.removeAllListeners('remote.alert'); |
13 | this.test.done(1); | ||
13 | }); | 14 | }); | ... | ... |
... | @@ -20,5 +20,5 @@ casper.test.assertEquals(casper.page.settings.userName, 'niko'); | ... | @@ -20,5 +20,5 @@ casper.test.assertEquals(casper.page.settings.userName, 'niko'); |
20 | casper.test.assertEquals(casper.page.settings.password, 'plop'); | 20 | casper.test.assertEquals(casper.page.settings.password, 'plop'); |
21 | 21 | ||
22 | casper.run(function() { | 22 | casper.run(function() { |
23 | this.test.done(); | 23 | this.test.done(8); |
24 | }); | 24 | }); | ... | ... |
... | @@ -13,8 +13,7 @@ casper.start('tests/site/index.html', function() { | ... | @@ -13,8 +13,7 @@ casper.start('tests/site/index.html', function() { |
13 | this.test.assert(fs.isFile(testFile), 'Casper.capture() captured a screenshot'); | 13 | this.test.assert(fs.isFile(testFile), 'Casper.capture() captured a screenshot'); |
14 | }); | 14 | }); |
15 | 15 | ||
16 | if (phantom.version.major === 1 && phantom.version.minor >= 6) { | 16 | casper.thenOpen('tests/site/index.html', function() { |
17 | casper.thenOpen('tests/site/index.html', function() { | ||
18 | this.test.comment('Casper.captureBase64()'); | 17 | this.test.comment('Casper.captureBase64()'); |
19 | this.test.assert(this.captureBase64('png').length > 0, | 18 | this.test.assert(this.captureBase64('png').length > 0, |
20 | 'Casper.captureBase64() rendered a page capture as base64'); | 19 | 'Casper.captureBase64() rendered a page capture as base64'); |
... | @@ -22,12 +21,11 @@ if (phantom.version.major === 1 && phantom.version.minor >= 6) { | ... | @@ -22,12 +21,11 @@ if (phantom.version.major === 1 && phantom.version.minor >= 6) { |
22 | 'Casper.captureBase64() rendered a capture from a selector as base64'); | 21 | 'Casper.captureBase64() rendered a capture from a selector as base64'); |
23 | this.test.assert(this.captureBase64('png', {top: 0, left: 0, width: 30, height: 30}).length > 0, | 22 | this.test.assert(this.captureBase64('png', {top: 0, left: 0, width: 30, height: 30}).length > 0, |
24 | 'Casper.captureBase64() rendered a capture from a clipRect as base64'); | 23 | 'Casper.captureBase64() rendered a capture from a clipRect as base64'); |
25 | }); | 24 | }); |
26 | } | ||
27 | 25 | ||
28 | casper.run(function() { | 26 | casper.run(function() { |
29 | try { | 27 | try { |
30 | fs.remove(testFile); | 28 | fs.remove(testFile); |
31 | } catch(e) {} | 29 | } catch(e) {} |
32 | this.test.done(); | 30 | this.test.done(4); |
33 | }); | 31 | }); | ... | ... |
... | @@ -13,5 +13,5 @@ casper.start('tests/site/confirm.html', function() { | ... | @@ -13,5 +13,5 @@ casper.start('tests/site/confirm.html', function() { |
13 | 13 | ||
14 | casper.run(function() { | 14 | casper.run(function() { |
15 | this.test.assertEquals(received, 'are you sure?', 'confirmation message is ok'); | 15 | this.test.assertEquals(received, 'are you sure?', 'confirmation message is ok'); |
16 | this.test.done(); | 16 | this.test.done(2); |
17 | }); | 17 | }); | ... | ... |
... | @@ -20,5 +20,5 @@ casper.start('file://' + phantom.casperPath + '/tests/site/index.html', function | ... | @@ -20,5 +20,5 @@ casper.start('file://' + phantom.casperPath + '/tests/site/index.html', function |
20 | }); | 20 | }); |
21 | 21 | ||
22 | casper.run(function() { | 22 | casper.run(function() { |
23 | this.test.done(); | 23 | this.test.done(2); |
24 | }); | 24 | }); | ... | ... |
... | @@ -70,4 +70,4 @@ casper.test.assertEquals(casper.evaluate(function(a, b, c) { | ... | @@ -70,4 +70,4 @@ casper.test.assertEquals(casper.evaluate(function(a, b, c) { |
70 | return [a, b, c]; | 70 | return [a, b, c]; |
71 | }, "foo", "bar", "baz"), ["foo", "bar", "baz"], 'Casper.evaluate() accepts natural arguments context'); | 71 | }, "foo", "bar", "baz"), ["foo", "bar", "baz"], 'Casper.evaluate() accepts natural arguments context'); |
72 | 72 | ||
73 | casper.test.done(); | 73 | casper.test.done(11); | ... | ... |
... | @@ -37,4 +37,4 @@ casper.test.assertEquals(casper.foo, 42, "filter() applies the correct context") | ... | @@ -37,4 +37,4 @@ casper.test.assertEquals(casper.foo, 42, "filter() applies the correct context") |
37 | 37 | ||
38 | delete casper.foo; | 38 | delete casper.foo; |
39 | 39 | ||
40 | casper.test.done(); | 40 | casper.test.done(5); | ... | ... |
... | @@ -100,5 +100,5 @@ casper.thenOpen('tests/site/field-array.html', function() { | ... | @@ -100,5 +100,5 @@ casper.thenOpen('tests/site/field-array.html', function() { |
100 | }); | 100 | }); |
101 | 101 | ||
102 | casper.run(function() { | 102 | casper.run(function() { |
103 | this.test.done(); | 103 | this.test.done(19); |
104 | }); | 104 | }); | ... | ... |
... | @@ -18,5 +18,5 @@ casper.start('tests/site/frames.html', function() { | ... | @@ -18,5 +18,5 @@ casper.start('tests/site/frames.html', function() { |
18 | 18 | ||
19 | casper.run(function() { | 19 | casper.run(function() { |
20 | this.page.switchToMainFrame(); | 20 | this.page.switchToMainFrame(); |
21 | this.test.done(); | 21 | this.test.done(8); |
22 | }); | 22 | }); | ... | ... |
... | @@ -37,5 +37,5 @@ casper.thenOpen('http://localhost:8090/', function thenLocalhost(response) { | ... | @@ -37,5 +37,5 @@ casper.thenOpen('http://localhost:8090/', function thenLocalhost(response) { |
37 | 37 | ||
38 | casper.run(function() { | 38 | casper.run(function() { |
39 | server.close(); | 39 | server.close(); |
40 | this.test.done(); | 40 | this.test.done(4); |
41 | }); | 41 | }); | ... | ... |
... | @@ -19,5 +19,5 @@ casper.then(function() { | ... | @@ -19,5 +19,5 @@ casper.then(function() { |
19 | casper.run(function() { | 19 | casper.run(function() { |
20 | this.test.assert(this.history.length > 0, 'Casper.history contains urls'); | 20 | this.test.assert(this.history.length > 0, 'Casper.history contains urls'); |
21 | this.test.assertMatch(this.history[0], /tests\/site\/page1\.html$/, 'Casper.history has the correct first url'); | 21 | this.test.assertMatch(this.history[0], /tests\/site\/page1\.html$/, 'Casper.history has the correct first url'); |
22 | this.test.done(); | 22 | this.test.done(4); |
23 | }); | 23 | }); | ... | ... |
... | @@ -36,5 +36,5 @@ casper.then(function() { | ... | @@ -36,5 +36,5 @@ casper.then(function() { |
36 | 36 | ||
37 | casper.run(function() { | 37 | casper.run(function() { |
38 | this.test.assertEquals(this.result.log.length, 3, 'Casper.log() logged messages'); | 38 | this.test.assertEquals(this.result.log.length, 3, 'Casper.log() logged messages'); |
39 | this.test.done(); | 39 | this.test.done(4); |
40 | }); | 40 | }); | ... | ... |
... | @@ -131,5 +131,5 @@ casper.thenOpen('tests/site/index.html', { | ... | @@ -131,5 +131,5 @@ casper.thenOpen('tests/site/index.html', { |
131 | 131 | ||
132 | casper.run(function() { | 132 | casper.run(function() { |
133 | this.removeAllListeners('open'); | 133 | this.removeAllListeners('open'); |
134 | t.done(); | 134 | t.done(16); |
135 | }); | 135 | }); | ... | ... |
... | @@ -32,5 +32,5 @@ casper.thenOpen('tests/site/index.html'); | ... | @@ -32,5 +32,5 @@ casper.thenOpen('tests/site/index.html'); |
32 | 32 | ||
33 | casper.run(function() { | 33 | casper.run(function() { |
34 | this.removeAllListeners('page.resource.requested'); | 34 | this.removeAllListeners('page.resource.requested'); |
35 | t.done(); | 35 | t.done(3); |
36 | }); | 36 | }); | ... | ... |
... | @@ -21,4 +21,4 @@ casper.start "tests/site/resources.html", -> | ... | @@ -21,4 +21,4 @@ casper.start "tests/site/resources.html", -> |
21 | onTimeout = -> @test.fail "waitForResource timeout occured" | 21 | onTimeout = -> @test.fail "waitForResource timeout occured" |
22 | @waitForResource "dummy.js", onTime, onTimeout | 22 | @waitForResource "dummy.js", onTime, onTimeout |
23 | 23 | ||
24 | casper.run(-> @test.done()) | 24 | casper.run(-> @test.done(5)) | ... | ... |
... | @@ -28,5 +28,5 @@ casper.thenOpen('tests/site/form.html', function() { | ... | @@ -28,5 +28,5 @@ casper.thenOpen('tests/site/form.html', function() { |
28 | 28 | ||
29 | casper.run(function() { | 29 | casper.run(function() { |
30 | this.options.remoteScripts = []; | 30 | this.options.remoteScripts = []; |
31 | this.test.done(); | 31 | this.test.done(6); |
32 | }); | 32 | }); | ... | ... |
... | @@ -13,5 +13,5 @@ casper.start('tests/site/index.html', function() { | ... | @@ -13,5 +13,5 @@ casper.start('tests/site/index.html', function() { |
13 | casper.test.assert(casper.started, 'Casper.start() started'); | 13 | casper.test.assert(casper.started, 'Casper.start() started'); |
14 | 14 | ||
15 | casper.run(function() { | 15 | casper.run(function() { |
16 | this.test.done(); | 16 | this.test.done(4); |
17 | }); | 17 | }); | ... | ... |
... | @@ -17,6 +17,5 @@ casper.then(function() { | ... | @@ -17,6 +17,5 @@ casper.then(function() { |
17 | casper.run(function() { | 17 | casper.run(function() { |
18 | this.test.assertHttpStatus(200); | 18 | this.test.assertHttpStatus(200); |
19 | this.test.assertUrlMatches('Forlì', 'Casper.getCurrentUrl() retrieves a decoded URL'); | 19 | this.test.assertUrlMatches('Forlì', 'Casper.getCurrentUrl() retrieves a decoded URL'); |
20 | this.test.done(); | 20 | this.test.done(6); |
21 | }); | 21 | }); |
22 | ... | ... |
... | @@ -10,4 +10,4 @@ casper.test.assertEquals(casper.page.viewportSize.width, 1337, 'Casper.viewport( | ... | @@ -10,4 +10,4 @@ casper.test.assertEquals(casper.page.viewportSize.width, 1337, 'Casper.viewport( |
10 | casper.test.assertEquals(casper.page.viewportSize.height, 999, 'Casper.viewport() can change the height of page viewport'); | 10 | casper.test.assertEquals(casper.page.viewportSize.height, 999, 'Casper.viewport() can change the height of page viewport'); |
11 | casper.test.assertRaises(casper.viewport, ['a', 'b'], 'Casper.viewport() validates viewport size data'); | 11 | casper.test.assertRaises(casper.viewport, ['a', 'b'], 'Casper.viewport() validates viewport size data'); |
12 | 12 | ||
13 | casper.test.done(); | 13 | casper.test.done(3); | ... | ... |
... | @@ -9,8 +9,9 @@ casper.start('tests/site/index.html', function() { | ... | @@ -9,8 +9,9 @@ casper.start('tests/site/index.html', function() { |
9 | casper.wait(1000, function() { | 9 | casper.wait(1000, function() { |
10 | this.test.comment('Casper.wait()'); | 10 | this.test.comment('Casper.wait()'); |
11 | this.test.assert(new Date().getTime() - waitStart > 1000, 'Casper.wait() can wait for a given amount of time'); | 11 | this.test.assert(new Date().getTime() - waitStart > 1000, 'Casper.wait() can wait for a given amount of time'); |
12 | // Casper.waitFor() | 12 | }); |
13 | casper.thenOpen('tests/site/waitFor.html', function() { | 13 | |
14 | casper.thenOpen('tests/site/waitFor.html', function() { | ||
14 | this.test.comment('Casper.waitFor()'); | 15 | this.test.comment('Casper.waitFor()'); |
15 | this.waitFor(function() { | 16 | this.waitFor(function() { |
16 | return this.evaluate(function() { | 17 | return this.evaluate(function() { |
... | @@ -21,7 +22,6 @@ casper.wait(1000, function() { | ... | @@ -21,7 +22,6 @@ casper.wait(1000, function() { |
21 | }, function() { | 22 | }, function() { |
22 | this.test.fail('Casper.waitFor() can wait for something to happen'); | 23 | this.test.fail('Casper.waitFor() can wait for something to happen'); |
23 | }); | 24 | }); |
24 | }); | ||
25 | }); | 25 | }); |
26 | 26 | ||
27 | casper.thenOpen('tests/site/waitFor.html').waitForText('<li>four</li>', function() { | 27 | casper.thenOpen('tests/site/waitFor.html').waitForText('<li>four</li>', function() { |
... | @@ -33,5 +33,5 @@ casper.thenOpen('tests/site/waitFor.html').waitForText('<li>four</li>', function | ... | @@ -33,5 +33,5 @@ casper.thenOpen('tests/site/waitFor.html').waitForText('<li>four</li>', function |
33 | }); | 33 | }); |
34 | 34 | ||
35 | casper.run(function() { | 35 | casper.run(function() { |
36 | this.test.done(); | 36 | this.test.done(3); |
37 | }); | 37 | }); | ... | ... |
... | @@ -124,4 +124,4 @@ t.comment('parse(), get(), has()'); | ... | @@ -124,4 +124,4 @@ t.comment('parse(), get(), has()'); |
124 | }, 'drop() did not affect other raw options'); | 124 | }, 'drop() did not affect other raw options'); |
125 | })(cli.parse(['foo & bar', 'baz & boz', '--universe=42', '--lap=13.37', '--chucknorris', '--oops=false'])); | 125 | })(cli.parse(['foo & bar', 'baz & boz', '--universe=42', '--lap=13.37', '--chucknorris', '--oops=false'])); |
126 | 126 | ||
127 | t.done(); | 127 | t.done(76); | ... | ... |
... | @@ -16,4 +16,4 @@ casper.then -> | ... | @@ -16,4 +16,4 @@ casper.then -> |
16 | casper.run -> | 16 | casper.run -> |
17 | @test.assertEquals steps, 3, "Casper.options.onStepComplete() is called on step complete" | 17 | @test.assertEquals steps, 3, "Casper.options.onStepComplete() is called on step complete" |
18 | @options.onStepComplete = null | 18 | @options.onStepComplete = null |
19 | @test.done() | 19 | @test.done(4) | ... | ... |
... | @@ -63,4 +63,4 @@ t.assertEquals(processed(), 3, 'FunctionArgsInjector.process() processed the fun | ... | @@ -63,4 +63,4 @@ t.assertEquals(processed(), 3, 'FunctionArgsInjector.process() processed the fun |
63 | var fnIssue129 = createInjector(issue129).process({term: 'fixed'}); | 63 | var fnIssue129 = createInjector(issue129).process({term: 'fixed'}); |
64 | t.assertEquals(fnIssue129('fixed'), 'fixed', 'FunctionArgsInjector.process() has issue #129 fixed'); | 64 | t.assertEquals(fnIssue129('fixed'), 'fixed', 'FunctionArgsInjector.process() has issue #129 fixed'); |
65 | 65 | ||
66 | t.done(); | 66 | t.done(12); | ... | ... |
... | @@ -15,4 +15,4 @@ casper.test.assertMatch(xunit.getXML(), /<testcase classname="(.*)plop" name="It | ... | @@ -15,4 +15,4 @@ casper.test.assertMatch(xunit.getXML(), /<testcase classname="(.*)plop" name="It |
15 | xunit.addSuccess(require('fs').workingDirectory + '/plip.js', 'Failure'); | 15 | xunit.addSuccess(require('fs').workingDirectory + '/plip.js', 'Failure'); |
16 | casper.test.assertMatch(xunit.getXML(), /<testcase classname="(.*)plip" name="Failure"/, 'XUnitExporter.addFailure() handles class name'); | 16 | casper.test.assertMatch(xunit.getXML(), /<testcase classname="(.*)plip" name="Failure"/, 'XUnitExporter.addFailure() handles class name'); |
17 | 17 | ||
18 | casper.test.done(); | 18 | casper.test.done(4); | ... | ... |
-
Please register or sign in to post a comment