Skip to content

Commit db78338

Browse files
jayjayjpgKrinkle
authored andcommitted
Core: Decide "No tests" based on test count, not assert count
If a test has no assertions, that is generally by itself another unrelated error. But more importantly, it is configurable, and also something that we support on a per-test basis via assert.expect(0) for which there are several use cases such as when the tests only purpose is not to throw, either from your source code, or from another helper library (e.g. Sinon assertion's throwing). Previously, if your test suite composed only of such tests, or if you selective run such test only, it wrongly caused the test runner to report a global error for "No tests." Fixes #1405. Closes #1449.
1 parent 474a708 commit db78338

File tree

6 files changed

+29
-2
lines changed

6 files changed

+29
-2
lines changed

src/core.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ extend( QUnit, {
9696

9797
// Initialize the configuration options
9898
extend( config, {
99-
stats: { all: 0, bad: 0 },
99+
stats: { all: 0, bad: 0, testCount: 0 },
100100
started: 0,
101101
updateRate: 1000,
102102
autostart: true,

src/core/processing-queue.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ function done() {
165165
const runtime = now() - config.started;
166166
const passed = config.stats.all - config.stats.bad;
167167

168-
if ( config.stats.all === 0 ) {
168+
if ( config.stats.testCount === 0 ) {
169169

170170
if ( config.filter && config.filter.length ) {
171171
throw new Error( `No tests matched the filter "${config.filter}".` );

src/test.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,7 @@ Test.prototype = {
299299
this.runtime = now() - this.started;
300300

301301
config.stats.all += this.assertions.length;
302+
config.stats.testCount += 1;
302303
module.stats.all += this.assertions.length;
303304

304305
for ( i = 0; i < this.assertions.length; i++ ) {

test/cli/fixtures/expected/tap-outputs.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,15 @@ ok 2 timeout > second
186186
# fail 1
187187
`,
188188

189+
"qunit zero-assertions.js":
190+
`TAP version 13
191+
ok 1 Zero assertions > has a test
192+
1..1
193+
# pass 1
194+
# skip 0
195+
# todo 0
196+
# fail 0`,
197+
189198
// in node 8, the stack trace includes 'at <anonymous>. But not in node 6 or 10.
190199
"qunit qunit --filter 'no matches' test":
191200
`TAP version 13
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
QUnit.module( "Zero assertions", function() {
2+
QUnit.test( "has a test", function( assert ) {
3+
assert.expect( 0 );
4+
5+
// A test may expect zero assertions if its main purpose
6+
// is to ensure there are no no run-time exceptions.
7+
} );
8+
} );

test/cli/main.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,15 @@ QUnit.module( "CLI Main", function() {
149149
}
150150
} ) );
151151

152+
QUnit.test( "allows running zero-assertion tests", co.wrap( function* ( assert ) {
153+
const command = "qunit zero-assertions.js";
154+
const execution = yield execute( command );
155+
156+
assert.equal( execution.code, 0 );
157+
assert.equal( execution.stderr, "" );
158+
assert.equal( execution.stdout, expectedOutput[ command ] );
159+
} ) );
160+
152161
if ( semver.gte( process.versions.node, "9.0.0" ) ) {
153162
QUnit.test( "callbacks and hooks from modules are properly released for garbage collection", co.wrap( function* ( assert ) {
154163
const command = "node --expose-gc --allow-natives-syntax ../../../bin/qunit.js memory-leak/*.js";

0 commit comments

Comments
 (0)