-
-
Notifications
You must be signed in to change notification settings - Fork 305
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
Test order is affected by a presence of a nested test #222
Comments
Is anyone checking at this? @substack @ljharb |
I think this may be tied to this other open issue #122 |
This is not an ordering problem; this is a reporting problem.
I agree this is confusing semantic difference between I recommend adding |
@Raynos From what I see, it is definitely an ordering issue, not a reporting one. var test = require('tape');
test('first', function (t) {
setTimeout(function () {
console.log('first test', +new Date());
t.ok(1);
t.end();
}, 200);
t.test('second', function (t) {
console.log('second test', +new Date());
t.ok(1);
t.end();
});
});
test('third', function (t) {
setTimeout(function () {
console.log('third test', +new Date());
t.ok(1);
t.end();
}, 100);
});
|
Your right; this is simply broken. |
I honestly do not know enough about what the semantics of sub tests are supposed to be to fix this... It should either be: second test or first test |
I think it should be
because sub tests are not much different from the same level tests in a sense that they may need the previous/parent test to be finished. For example, nested tests may use a context that is set up in the parent test and may need the parent test to finish working with the context before a nested test can start using the context. |
I would expect tape follows JS scoping rules, so the ordering of the tests shouldn't affect anything unless a subtest mutates something another subtest depends on. |
@ljharb Why allowing the second test to run before the first one is finished? Except the nesting level, the second and the third tests are not much different conceptually, so why having different rules for the sub tests? |
In other words, the first test may be doing things in this scope: test('first', function (t) {
... as well as in this scope: setTimeout(function () {
...
}, 200); Allowing the second test to run before the first one is finished, means potentially interrupting the work of the first test. The isolation of the first test is broken. |
Using |
The bug here is that sub tests work differently purely on the existence of plan() |
@ljharb So I had a code like this: var test = require('tape');
test('first', function (t) {
setTimeout(function () {
t.ok(1, 'first test');
t.end();
}, 200);
});
test('third', function (t) {
setTimeout(function () {
t.ok(1, 'third test');
t.end();
}, 100);
}); The first test was finishing before the third one. Then I added a subtest: var test = require('tape');
test('first', function (t) {
setTimeout(function () {
t.ok(1, 'first test');
t.end();
}, 200);
t.test('second', function (t) {
t.ok(1, 'second test');
t.end();
});
});
test('third', function (t) {
setTimeout(function () {
t.ok(1, 'third test');
t.end();
}, 100);
}); Adding the second test introduced 2 issues:
Regarding the first issue - semantically, subtests are separate tests. They're executed after their parent test. That's what happens when the parent test in synchronous or has
I know I may do the setTimeout inside the subtest, or may define the subtest inside the setTimeout, or may add Regarding the second issue - no matter how I structure the first test subtests, the third test should never execute before the first one is finished. It is inconsistent with tape's promise to execute tests sequentially. |
Gotcha - I always use |
This seems to be a consequence of supporting nested tests that implicitly end their parent. See the test for this behavior. Something that let any asynchronous process to settle instead of |
Hi, as a beginner and maybe missing some bigger picture:
|
The issue is that the third test starts before the first test is finished (with 3 tests), AND if you remove the second test, then the third test doesn't start the first test is finished. |
Your example without plan() does the following in Promise-terms, where the order of execution is not deterministic (which is fine if there is no shared mutable context).
In order to execute test3 always after the first two, because it shares some mutable context with the others for example, you have to seperate their "async contexts", and I think that this should not be tape's responsibiltiy:
To depend on deterministic order for asynchronous execution is an anti pattern as far as I understand. PS |
(Promises aren't quite the same - a promise represents a future value for work that has already begun, whereas a callback is the work itself) |
In the example you are not working with the callbacks directly, but passing them to seTimeout() and setTimeout() is some work to be done in the future, isn't it? |
that is true. but the test itself is not passed to setInterval, and it's not finished until "end()" is called (or the timeout reached). |
Of course, and I believe that the language itself provides solutions for this and that it is not tape's responsibility to solve this problem, that is all. |
I don't think it's how most of test frameworks I know (including tape) work. This code works as I expect and executes the var test = require('tape');
test('first', function (t) {
setTimeout(function () {
t.ok(1, 'first test');
t.end();
}, 200);
});
test('third', function (t) {
t.ok(1, 'third test');
t.end();
}); No matter how long does the |
Quick followup after my last post. Listening to I played a bit with Angular zone.js library. It works but it breaks even more tests :’D It’s interesting to note that this simply doesn’t happen with |
I fixed the failing test, listening to |
Oh well, neither |
|
I tried to create example which shows how to test ~~~a Koa.js server~~~ with blue-tape and promises. |
@ljharb Would a fix for Node only and an update to @ArtemGovorov In the meantime you can try with |
@kl0tl I'd prefer the same bugs be present consistently across every environment. One of the primary use cases for |
@ljharb Yeah, consistency wins you’re right. I’ll document this behavior inside a new What do you think about bringing @ArtemGovorov Sadly this bug is here to stay :( I hope it doesn’t prevent Wallaby to integrate with |
|
|
Supporting that is tricky because we'd have to either a) assume Promise was available, which forces the user to know they need to shim it, b) allow explicit injection of Solution a is dangerous, b is awkward, and c is heavyweight. If you want to open a new thread to discuss it (not on this one) we can, but I don't think it's likely. |
Discussion on promises moved to #262. |
I finally took time to document the issue! It seems this bug can’t be fixed reliably across node and browsers :( Would it be conceivable to deprecate the implicit termination of parents tests and remove it in a future release? If not there’s not much more to do regarding this. |
If I understand problem correctly there are only two possible fixes: A. Resign from support of no B. Tweak In my eyes @ArtemGovorov can you explain why exactly it's a blocker for Wallaby? Aside of this issue, I can imagine some race conditions in asynchronous tests which will still make asserts to not go down always in same order (and it could be seen as acceptable). |
The problem isn't that 'first' actually starts terminating after 'third', it's that the entire block in setTimeout runs after 'first' has ended (implicitly, due to subtest without plan as @kl0tl noted)
this is basically just #264 |
This behavior was introduced in 35f29a as part of the fix for #33 I suggest that https://github.com/Kl0tl/tape/blob/master/test/nested-sync-noplan-noend.js#L1 should hang, since it doesn't have have a plan or end, which violates the documented behavior "If you forget to t.plan() out how many assertions you are going to run and you don't call t.end() explicitly, your test will hang." I think the right fix here is to end the test upon subtest completion, but only if t.end() has been called already and conversely defer t.end() if subtests are queued. createHarness needs an option autoEnd for the exported harness to call t.end() after all subtests. |
…t includes subtests Fixes tape-testing#222.
…t includes subtests Fixes tape-testing#222.
…t includes subtests Fixes tape-testing#222.
Fix premature end of tests (and running sibling tests) when test includes subtests Fixes #222.
[New] Implements TAP TODO directive (#254) [New] add alias 'notDeepEquals' to 'notDeepEqual' function (#411) [Fix] fix premature end of tests (and running sibling tests) when test includes subtests (#403, #222) [Fix] only use one test runner for results, even if multiple streams are created (#404, #361, #105) [Fix] windows: Show failure location even if driver letter is lowercase (#329) [Docs] link to mixed tape (#445) [Docs] Add electron-tap (#240) [Docs] Add tape-promise into 'other' (#210) [Docs] Mention [`flip-tape`](https://github.com/pguth/flip-tape/blob/master/README.md) in the section "other". (#359) [Docs] Add an alternative ES6 tape runner (#328)
The following code:
outputs:
and it's expected. But if I change it to its logical equivalent without
plan
:the the test order is broken:
While changing the order of the first and the second test is somewhat expected, ending the first test prematurely, and letting the third test execute before it, looks like a bug. Especially considering that commenting
t.test('second'...
test out restores the expected order, and make the third test wait until the first one ends.The text was updated successfully, but these errors were encountered: