-
Notifications
You must be signed in to change notification settings - Fork 780
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow nested suites (modules) #543
Comments
+1000! The lack of nested modules ( like nested describes ) in QUnit have been one of my major drivers for using mocha in newer projects. Even better if it supports setup/teardown within those nested modules so we can get the equivalent of beforeEach and afterEach |
This could also work wonders to cleaning up the HTML report for the jquery/qunit-composite runner. |
What API would you use for this? |
API idea: QUnit.test( 'APP.Foo', {
setup: fn,
teardown: fn
}, function( assert ) {
var foo = new App.Foo();
assert.ok( foo, 'instantiation' );
assert.test( 'foo.add', {
setup: function () {
foo = new App.Foo();
}
}, function( assert ) {
assert.test( 'foo.add( String )', function( assert ) {
assert.equal( foo.add( 'x' ), 'default x' );
assert.equal( foo.add( 'y' ), 'default x y' );
} );
assert.test( 'foo.add( String... )', function( assert ) {
assert.equal( foo.add( 'x', 'y' ), 'default x y' );
assert.equal( foo.add( 'a', 'b', 'c' ), 'default x y a b c' );
} );
} );
assert.test( 'foo.reset()', function( assert ) {
foo.add( 'x', 'y' );
assert.equal( foo.reset(), 'default' );
} );
} );
QUnit.test( 'APP.Bar' );
... Which would be more-or-less the equivalent of: QUnit.module( 'APP.Foo', {
setup: fn,
teardown: fn
} );
(function() {
var foo = new App.Foo();
QUnit.test( 'foo.add', function( assert ) {
assert.ok( foo );
} );
QUnit.test( 'foo.add( String )', function( assert ) {
foo = new App.Foo();
assert.equal( foo.add( 'x' ), 'default x' );
assert.equal( foo.add( 'y' ), 'default x y' );
} );
QUnit.test( 'foo.add( String... )', function( assert ) {
foo = new App.Foo();
assert.equal( foo.add( 'x', 'y' ), 'default x y' );
assert.equal( foo.add( 'a', 'b', 'c' ), 'default x y a b c' );
} );
QUnit.test( 'foo.reset()', function( assert ) {
foo = new App.Foo();
foo.add( 'x', 'y' );
assert.equal( foo.reset(), 'default' );
} );
}());
QUnit.module( 'APP.Bar' );
... Right now we have special "module" groups that can only contain tests and supports setup/teardown,
|
Another idea which is similar to other existing implementations: QUnit.module( 'parent', function( test ) {
// Maybe test.setupOnce() as well?
test.setup(function() {
// Do stuff
});
test.teardown(function() {
// Do stuff
});
test( 'some test', function( assert ) {});
test.async( 'an async test', function( assert ) {});
QUnit.module( 'child', function( test ) {
// Nested!
});
}); |
I also like @dcherman's suggestion, which is very akin to Mocha's TDD style: suite('Array', function() {
suiteSetup(function() {
// This runs once before any `test` within the `suite` is executed
});
setup(function() {
// This runs before each `test`
});
teardown(function() {
// This runs after each `test`
});
suiteTeardown(function() {
// This runs once after every `test` within the `suite` has been executed
});
suite('#indexOf()', function() {
test('should return -1 when not present', function() {
assert.equal(-1, [1,2,3].indexOf(4));
});
});
}); |
This doesn't appear to be a priority at the moment. Patches are welcome, however. Note, though, that this shouldn't affect your ability to write good and maintainable tests. It's only a minor prettiness factor (one of which the usefulness is imho still debatable). The main reason I'm in favour of it is because it'd simplify the code a lot by taking away special meaning from "module" and "test". Everything would simply be groups of assertions and/or other groups. For setup/teardown one can use "test" right now, and for a persistent scope a closure is easy enough. I've written loads of tests over the past years and not once felt a need for this (not even with hacky closures). One QUnit module for each tangible component of the code, and one test for each logical group of assertions for an individual property, method or behaviour exposed by that component. |
I am assuming this is actually more of shift for our reporters than it is for our core |
The discussion here has been mostly about nesting code, but the original ticket actually referred to the "sleek nested HTML output" of Mocha. What the screenshot shows should be possible already, without requiring any API changes. It's mostly a matter of displaying the results differently and that's something we can explore. Otherwise, on the API/code side, I'm not inclined to change anything, for the reasons that @Krinkle has outlined above. |
To clarify, the screenshot in the original ticket description shows at most two branches and one leaf node, which corresponds to our module/test/assertion methods. So achieving that specific output shouldn't require any API changes. |
If I were going to use QUnit for nested modules, I think I would want the syntax to look like this: (function( suite, test, beforeEach ) {
suite( "parent", function() {
beforeEach(function( assert ) { /* ... */ });
test( "x", function( assert ) { /* ... */ });
test( "y", function( assert ) { /* ... */ });
suite( "child", function() {
beforeEach(function( assert ) {
// also automatically invokes its parent module's `beforeEach`
/* ... */
});
test( "z", function( assert ) { /* ... */ });
});
});
})( QUnit.module, QUnit.test, QUnit.beforeEach ); You'll note that the above example is utilizing a theoretical If that API is undesirable, we could also add it to a module context object (e.g. However, I would also definitely recommend we maintain the existing syntax as well. It is simple/linear, widely used, and generally well-liked: QUnit.module( "x", {
beforeEach: function( assert ) { /* ... */ },
afterEach: function( assert ) { /* ... */ }
});
QUnit.test( "y", function( assert ) { /* ... */ }); |
+1000!!! |
Allows modules to be nested. This is achieved by adding a third possible argument to the QUnit.module method, which is a function that is called for immediate processing. Also, testEnvironments for parent modules are invoked in recursively for each test (outer-first). Fixes qunitjs#543
Allows modules to be nested. This is achieved by adding a third possible argument to the QUnit.module method, which is a function that is called for immediate processing. Also, testEnvironments for parent modules are invoked in recursively for each test (outer-first). Fixes qunitjs#543
Allows modules to be nested. This is achieved by adding a third possible argument to the QUnit.module method, which is a function that is called for immediate processing. Also, testEnvironments for parent modules are invoked in recursively for each test (outer-first). Fixes qunitjs#543
Allows modules to be nested. This is achieved by adding a third possible argument to the QUnit.module method, which is a function that is called for immediate processing. Also, testEnvironments for parent modules are invoked in recursively for each test (outer-first). Fixes qunitjs#543
Allows modules to be nested. This is achieved by adding a function argument to the QUnit.module method, which is a function that is called for immediate processing. Also, testEnvironments for parent modules are invoked in recursively for each test (outer-first). Fixes qunitjs#543 Closes qunitjs#800 Closes qunitjs#859 Closes qunitjs#670 Ref qunitjs#858
A personal sore point for me when using QUnit is the lack of nested suites (
module
s) that are offered by other popular frameworks like Mocha and Jasmine.I've given it some cursory thought and, if we agree it adds value, I don't foresee any major roadblocks to implementing that capability. It would give us some options for richer reporting outputs as well, e.g. Mocha's sleek nested HTML report:
The text was updated successfully, but these errors were encountered: