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 exited without ending" #223
Comments
substack's tape had strange intermittent issues tape-testing/tape#223
@gritzko Is this on Node, or in the browser? |
This means your test did not call Probably a race condition in your own code. |
I am seeing a similar issue. I have tests split across multiple files. When I run the tests using $ istanbul cover tape -- ./test/*.js some runs all complete (no errors) and others return an The tests are all synchronous, so no async race conditions. And all tests explicitly call |
Are you certain your tests are idempotent and that the state of some tests What happens if you run the tests individually? Do they work every time? If On Tue, Dec 29, 2015 at 3:51 PM, Athan notifications@github.com wrote:
|
@joshrivers node, AFAIR |
@Marak If I run each test file individually, the tests always pass. No tests share state. |
@kgryte - Can you describe the nature of the tests? If they are all synchronous tests I'm assuming they are performing no file-system or network based i/o? Or are they using synchronous file-system methods? What I'm trying to ascertain is if you are accessing any shared resources across the tests which could be causing conflicting state. |
The tests are of the variety: test( 'awesome test', function ( t ) {
t.ok( 5 === 5, 'numbers are equal' );
t.end();
}); In the last file which occasionally fails, I added additional (synchronous) dummy test cases to see what happens. The result is that either all tests pass or all fail due to the |
@kgryte - Maybe the issue is with |
What happens if you change up this require statement: https://github.com/kgryte/utils-copy-error/blob/master/test/test.ctors.js#L6
Then inside the first test put:
|
Same result. Did the same for the |
@Marak If I run the tests without |
@kgryte - The thing is, I have some faith that If the issue only comes up using Simple question, are you certain you are using the latest stable versions of all projects involved? |
@Marak Yes, I have the latest versions of all projects. So I did the following # Instrument files beforehand and output to temporary directory...
$ istanbul instrument ./lib --output ./tmp
# Run the tests on the instrumented files...
$ tape ./test/*.js I ran into the same issue. When |
@kgryte - Did you try opening an issue in |
@Marak I am not convinced that the issue is |
@Marak So, I put a
Notice that the last file appears after the tests have run. |
@Marak The race condition belongs to My running hypothesis is as follows: without the |
Similar issues have been reported before: #160 |
Update: if I use Correction: I just had a build fail due to tests prematurely ending even when using |
@Marak I added a
|
This does sound like a bug given the following conditions:
Looks the race condition is here: https://github.com/substack/tape/blob/master/bin/tape#L28-L34 We really should "resolve" all globs in parallel; and then loop over ALL the files once instead of doing multiple loops. As a temporary workaround @kgryte can do |
@Raynos workaround works. All files are resolved before tests are run. Thanks! |
…/tape#223) and add testling-proxyquire template
Issue can be related to calling If you have any require('leaked-handles').set({
fullStack: true, // use full stack traces
timeout: 5000, // run every 30 seconds instead of 5.
debugSockets: true // pretty print tcp thrown exceptions.
}); |
I'm consistently getting errors and reports of errors from other developers trying to use the If we switch to the |
@Marak can you elaborate on "at once"? One of the primary benefits of tape over tap is that it's lightweight and can also run in a browser. If those aren't concerns, and encouraging bad code to be written properly isn't an option, I think switching libs might make sense. |
I mean to say when running tests with globs like It's just odd to me that these two commands are yielding much different test results:
Noted about primary benefits of |
I believe in that case tap may run each file in its own process, whereas tape runs them all in the same one? Just guessing tho. Personally I usually |
@ljharb - Are you saying that you require all your test files in one One of our developers wanted to do the same and I'm not sure that would scale well for a project with many suites. Going to switch to |
@Marak yes, precisely that. My general sense is that when that doesn't scale, the project is too large, and thus must be split into smaller projects in their own repos. |
i'm pretty sure i've been fighting this issue all day. here's a barebones test that'll show it up: const test = require('tape').test;
function _test(identifier) {
console.log(`starting test ${identifier}`);
test(`_test ${identifier}`, assert => {
assert.true(true);
});
}
function _runAsyncTests() {
setTimeout(_test, 1000, `A`);
setTimeout(_test, 3000, `B`);
}
_runAsyncTests(); here's the output:
i've traced it through into |
@simonhac I trust that you realize that if you added an |
thanks @ljharb -- do you mean that i should change my code to the following? const test = require('tape').test;
function _test(identifier) {
test(`_test ${identifier}`, assert => {
assert.plan(1)
assert.true(true);
assert.end();
});
}
function _runAsyncTests() {
setTimeout(_test, 1000, `A`);
setTimeout(_test, 3000, `B`);
} unfortunately, that still fails:
but i've worked out why -- will post in next comment. |
ok, i think i've worked this out. as soon as the list of executing tests is empty check out this simple example: const test = require('tape').test;
function _test(name) {
test(`test ${name}`, t => {
t.plan(1);
t.pass(name);
t.end();
});
}
_test(`huey`);
_test(`dewey`);
setTimeout(function () {
_test(`louie`);
}, 100); the runtime gets to the bottom of the script before the deferred task to schedule the 'louie' test is executed, and we get the following failing test report:
if i add the following statement to the bottom it works just fine! test(`afterTests`, t => {
setTimeout(function () {
t.end();
}, 1000);
}); it is not immediately intuitive to the casual reader why this might make it work, but this supports my theory above. it would be nicer if ps. you may ask why i have delayed tests -- i have a test harness that generates tests only once it has asynchronously read in a file. i can code around this (by loading the file in a dummy test at the top of the script), but i thought it was worth explaining what i found because it looks like this issue frequently bites others. |
Because you want |
@ljharb in this case, i didn't think there was a difference between: const test = require('tape').test; and: let test = require('tape'); i've tried your suggestion, and it still fails for me. does it pass for you? |
|
Tests must all be scheduled synchronously - for your use case I'd recommend wrapping the entire file in a single |
thanks @jtlapp my example above does use @ljharb, thanks for your response:
i asynchronously schedule tests when use data driven test suites. i've found that this works so long as the scheduling is done within a synchronously initiated 'dummy' test. ie. your suggestion of wrapping the test scheduler in a good workaround. from searching the issues in this project, it looks like this problem has caught quite a few and is difficult to track down. (with async calls there's always the chance of non-determinism.) i'd suggest the following:
the second option is my preferred. |
I was trying to explain why your options 2 and 3 are not possible. |
thanks @jtlapp -- i don't understand why options 2 & 3 are not possible. at least with option 3, couldn't the current behaviour feels obscure for someone not into the implementation details. |
I just tried to write a lengthy explanation and found you correct and myself incorrect, @simonhac. I was actually defending I'm now siding with you, @simonhac. This appears to be another artifact of |
I think I'm having this problem as well. tape "*.test.js" "lib/*.test.js" Every few times I run it, some of the tests don't run and it says some tests exited without ending. I need the multiple globs to avoid running tests under |
Try replacing Change from... glob(arg, function (err, files) {
files.forEach(function (file) {
require(resolvePath(cwd, file));
});
}); ...to... glob.sync(arg).forEach(function(files) {
files.forEach(function (file) {
require(resolvePath(cwd, file));
});
}); (I just threw that together now, so there may be a bug in there.) |
Close! This did the trick: glob.sync(arg).forEach(function(file) {
require(resolvePath(cwd, file));
}); So... should that be a PR? I don't know what else that might affect. Tape's tests still pass after that change, though. |
It'll slow down test suites that do manage to run in parallel. |
PR to fix this issue: #374 |
- [Fix] fix spurious "test exited without ending" (#223) - [New] show full error stack on failure (#330) - [Deps] update `resolve`, `object-inspect`, `glob` - [Dev Deps] update `tap`, `concat-stream`, `js-yaml` - [Tests] fix stack differences on node 0.8 - [Tests] npm v4.6+ breaks on node < v1, npm v5+ breaks on node < v4 - [Tests] on `node` `v8`; no need for sudo; `v0.8` passes now; allow v5/v7/iojs to fail.
Hi!
Probabilistically, I get the following:
19 out of 20 runs are OK.
I am mostly annoyed by the fact I can not localize/attribute the error.
The text was updated successfully, but these errors were encountered: