-
Notifications
You must be signed in to change notification settings - Fork 779
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 calls to "expect" within a single test to be cumulative #226
Comments
The patch is simple enough, but the design is questionable. Having a single expect per test means that you have to structure modules, tests and assertions in a way that a single expect makes sense. Having one test method call out to several other methods, each with expect calls, sound like you're not structuring your tests in a way to fits QUnit. Before closing or landing, I'd like to see your usecase to get a better idea what you're trying to solve. |
Hi Joern - this facility is essential when tests are written which are in some way reflective or driven by declarative configuration. Here is a simple setup which on the first line sets up 3 component types to be tested in an array. The body of the test iterates over the array and issues a test case for each member against a different type. The expectation is that the set of components under test can be driven directly by adding or removing elements from the head array - it would be onerous to expect the test maintainer, in order to arrive at a valid test, to inspect all the code paths and add up the total number of "expect" counts to place in the head test. As it happens in this case the number of expects is constant (1) for each component, but we also have cases where the test cases themselves are also polymorphic, variable on the type of the component being tested, and so the burden of counting "expect" clauses would be particularly onerous. In terms of structuring our tests to fit QUnit, I hope that in the final analysis that QUnit can be found to be useful in a broad community and being purposed to fit a diverse collection of needs, of course without compromising its core architectural principles and consistency. I hope you agree that this is an useful improvement which increases QUnit's coverage without compromising its consistency. fluid.tests.gradeTestTypes = ["fluid.tests.gradedComponent", "fluid.tests.autoGradedComponent", "fluid.tests.ungradedComponent"]; function testEvent(message, component) {
|
In this case, why not use a test for each type?
Then put an appropiate module() call in front of that. |
I think we should be free to issue tests of the granularity we prefer. It seems unnecessarily bulky to declare a new module around this construction and a fresh test case for each fixture. The inability to cumulate "expect" forces each leaf function in the testing architecture to become its own test case which is not usually an appropriate choice. I can quote more elaborate test cases than this one where the economics are even more skewed. Could you explain your opposition to this feature, which clearly meets a need by some of your userbase, for which you have a patch, tests and a clear explanation, and breaks none of your existing tests? |
A general opposition of new features is pretty healthy for open source projects. In this case my concern is about the change in the semantics of expect. The unit tests don't tell us what code might break elsewhere due to a change, even if its very unlikely to break something in this case. This isn't the first request asking for different module/test/assertion semantics, and I have to make sure that the usecase is actually valid.
I'd like to see those, as the previous example itself wasn't convincing. Is there another (GitHub) project I can look at? Maybe there's an alternative solution to the problem. |
Here is a more elaborate example. At lines 566-577 we set up a bunch of tests, which does indeed issue a distinct test for each loop entry as you advise - however, as the tested code is polymorphic, as well as being composed of a number of independent units, the number of "expect" calls can't be easily computed in advance. We don't actually issue any expect calls here since there aren't any dynamic code paths within the tests themselves, but this is just an accident of how these tests are written, and they may well need to be expanded to issue "expect" in the future. For example, look at the "leaf function" "checkUploaderArgumentMap". I think it is unreasonable to expect this to be a whole test case in itself. It should be able to express its own "expect" count (2). In general, I think your solution isn't workable because it forces us to couple the unit of the test fixture (which amongst other things, is coupled to the cycle of replacing the "#main" markup and setup/tearDown) with the smallest unit of code which we have which issues assertion calls. This prevents tests from being expressed in the scalable manner that one would use when writing normal code. The "teardown/replace" boundary in the architecture is a fixed one depending on the actual lifecycle of the component being tested, and should not be used to define architectural boundaries in the structure of the code forming the test cases. |
Thanks for the full example. I'll need a bit more time to get back to this, but expect the patch to land sometime soon. |
Cheers, Joern - thanks for your patience with the discussion |
I oppose the idea of cumulative If you don't know the number of tests to be run in advance, don't use If you use a wrapper for creating several tests, (in that your assertions are not directly inside the
test('foo', function () {
expect(10);
K.Test.doTenTestsWith('X');
expect(10);
K.Test.doTenTestsWith('Y');
}); .. you'd have: test('foo X', function () {
expect(10);
K.Test.doTenTestsWith('X');
} );
test('foo Y', function () {
expect(10);
K.Test.doTenTestsWith('Y');
} ); Or even make the call to
test('foo', function () {
var expected = 0;
K.Test.doTenTestsWith('X');
expected += 10;
K.Test.doTenTestsWith('Y');
expected += 10;
expect(expected);
}); If we decide to keep not-supporting cumulative setting of |
Hi Timo - I disagree with your argument, for reasons which I have already stated. To deal with each of your presented choices, ii) Simply don't use "expect()" - this is a choice we exercise from time to time, but sometimes it is important for the integrity of a test that it has run to conclusion (if it has unexpected exit paths in the logic that allow it to terminate without failure). Your argument about doing an AJAX request and getting an unknown number of properties is invalid - an AJAX request could never be part of a unit test fixture since it would introduce an environmental dependency. Of course, jqUnit is equally useful for integration tests, but unit tests are, culturally, its primary use case - as its name suggests. iii) Arguments based around expecting the test case author to mock up this feature of the testing framework manually whenever they want it are unhelpful. The testing framework has this feature (the ability to count the number of assertions) and it would be most helpful for it to be upgraded so that it covers more use cases for the user base. |
This is a breaking change, so I'm against it for that reason alone. But, I see two sane ways to accomplish what @amb26 is asking for:
test( "do lots of stuff", function() {
var expected = 10;
expect( expected );
// do stuff locally which causes 10 assertions
expected += someHelperWithUnknownAssertions();
expect( expected );
});
test( "do lots of stuff", function() {
// ...
someHelperWithUnknownAssertions();
});
function someHelperWithUnknownAssertions() {
expect( QUnit.currentTest.expected + 5 );
// do assertions
} |
That would be |
We could make expect() return the current number of assertions when called without arguments. |
Right now it hurts modularity that it is not possible for a test function to call various subfunctions which each make their own separate calls to "expect" along with issuing some assertions. Forcing the user to push the "expect" count to top level makes test cases fragile - it would be helpful if several calls to "expect" within a single test case were cumulative, rather than the last one replacing the total count.
The text was updated successfully, but these errors were encountered: