-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
Fix unhandled promise rejections #702
Fix unhandled promise rejections #702
Conversation
Uncaught rejections were from the methods `testManager.runTest` and `testManager.discoverTests` that are killed when tests complete. They ought to be handled just to prevent this error, but otherwise there is not any code defect. I handled it using the same code as in https://github.com/Microsoft/vscode-python/blob/1cd98b2d3c044a1ed69ca2fe6d548998cc52aabf/src/test/unittests/debugger.test.ts#L150-L156. I had to disable tslint in a few places because tslint (from the pre-commit hook) is very strict with promises, see https://stackoverflow.com/q/43980188/5749914.
This was giving errors for me but not in Travis, probably because I did not have rope installed.
@@ -108,11 +108,11 @@ suite('Interpreters from Conda Environments Text File', () => { | |||
fileSystem.setup(fs => fs.fileExistsAsync(TypeMoq.It.isValue(environmentsFilePath))).returns(() => Promise.resolve(true)); | |||
fileSystem.setup(fs => fs.readFile(TypeMoq.It.isValue(environmentsFilePath))).returns(() => Promise.resolve(interpreterPaths.join(EOL))); | |||
|
|||
AnacondaCompanyNames.forEach(async companyDisplayName => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
forEach
on an async function doesn't do anything.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please see below for the fix to this entire test
@@ -71,10 +71,31 @@ suite('Unit Tests - debugging', () => { | |||
assert.equal(tests.testFunctions.length, 2, 'Incorrect number of test functions'); | |||
assert.equal(tests.testSuites.length, 2, 'Incorrect number of test suites'); | |||
|
|||
const deferred = createDeferred<string>(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With using deferred
I am basically copying from https://github.com/Microsoft/vscode-python/blob/1cd98b2d3c044a1ed69ca2fe6d548998cc52aabf/src/test/unittests/debugger.test.ts#L150-L156
runningPromise | ||
.then(() => 'Debugger stopped when it shouldn\'t have') | ||
.catch(() => 'Debugger crashed when it shouldn\'t have') | ||
// tslint:disable-next-line:no-floating-promises |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See https://stackoverflow.com/a/48603963/5749914 for my take on why this is necessary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should change this again as follows:
.catch(() => deferred.reject('Debugger crashed when it shouldn\'t have'))
This way, whether the promise resolves or rejects, we're capturing it and accordingly rejecting the deferred
promise.
Thanks for cleaning up the tests, please could you create an issue for this so we can track the PR against an issue. |
Also, travis is failing, please could you fix the tests where its failing, I cannot merge the PR without the tests passing. |
The issue for this is #479. |
@elliott-beach oh awesome, here's the fix to the failing travis unit test. test('Must strip company name from version info', async () => {
const interpreterPaths = [
path.join(environmentsPath, 'conda', 'envs', 'numpy')
];
const pythonPath = path.join(interpreterPaths[0], 'pythonPath');
condaService.setup(c => c.condaEnvironmentsFile).returns(() => environmentsFilePath);
condaService.setup(c => c.getInterpreterPath(TypeMoq.It.isAny())).returns(() => pythonPath);
fileSystem.setup(fs => fs.fileExistsAsync(TypeMoq.It.isValue(pythonPath))).returns(() => Promise.resolve(true));
fileSystem.setup(fs => fs.fileExistsAsync(TypeMoq.It.isValue(environmentsFilePath))).returns(() => Promise.resolve(true));
fileSystem.setup(fs => fs.readFile(TypeMoq.It.isValue(environmentsFilePath))).returns(() => Promise.resolve(interpreterPaths.join(EOL)));
for (const companyName of AnacondaCompanyNames) {
const versionWithCompanyName = `Mock Version :: ${companyName}`;
interpreterVersion.setup(c => c.getVersion(TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns(() => Promise.resolve(versionWithCompanyName));
const interpreters = await condaFileProvider.getInterpreters();
assert.equal(interpreters.length, 1, 'Incorrect number of entries');
assert.equal(interpreters[0].displayName, `${AnacondaDisplayName} Mock Version`, 'Incorrect display name');
}
}); |
I was hoping you should show me how to fix it, thanks!!! |
I don't want to muddy the waters. Thanks though |
await expect(discoveryPromise).to.eventually.equal(EmptyTests); | ||
// This promise should never resolve nor reject. | ||
runningPromise | ||
.then(() => 'Debugger stopped when it shouldn\'t have') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This won't do anything, if this isn't necessary, then you need to change this line as follows:
.then(() => Promise.reject('Debugger stopped when it shouldn\'t have'))
This will cause it to fail, then the catch will do what's necessary
or
Just fail early
.then(() => deferred.reject('Debugger stopped when it shouldn\'t have'))
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, makes sense. It is 1:30AM my time and I will fix this tomorrow. Thanks for the review!
runningPromise | ||
.then(() => 'Debugger stopped when it shouldn\'t have') | ||
.catch(() => 'Debugger crashed when it shouldn\'t have') | ||
// tslint:disable-next-line:no-floating-promises |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should change this again as follows:
.catch(() => deferred.reject('Debugger crashed when it shouldn\'t have'))
This way, whether the promise resolves or rejects, we're capturing it and accordingly rejecting the deferred
promise.
.catch(() => 'Debugger crashed when it shouldn\'t have') | ||
// tslint:disable-next-line:no-floating-promises | ||
.then(error => { | ||
deferred.reject(error); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This .then
won't be necessary.
Codecov Report
@@ Coverage Diff @@
## master #702 +/- ##
=========================================
+ Coverage 62.39% 62.4% +<.01%
=========================================
Files 241 241
Lines 11109 11109
Branches 2001 2001
=========================================
+ Hits 6932 6933 +1
+ Misses 4169 4168 -1
Partials 8 8
Continue to review full report at Codecov.
|
@@ -75,7 +90,7 @@ suite('Unit Tests Stopping Discovery and Runner', () => { | |||
await new Promise(resolve => setTimeout(resolve, 1000)); | |||
|
|||
// User manually discovering tests will kill the existing test runner. | |||
mockTestManager.discoverTests(CommandSource.ui, true, false, true); | |||
await mockTestManager.discoverTests(CommandSource.ui, true, false, true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This caused the coverage to go down because, without the await
, discoverTests
would eventually receive a cancellation request, triggering handler code. Edit: that's wrong, it's somewhere else
In this case (for this PR), as they're fixes in tests, that's fine |
Oh well I just fixed it, and we might as well cover test cancellation, which is actually code that's shipped, not simply internal test code. So let's see if the CI passes. |
Hooray, coverage passed! |
The tests fail because I unearthed one test that was silently failing,
'Must strip company name from version info'
.Most uncaught rejections were from the promises of
testManager.runTest
andtestManager.discoverTests
getting killed when the test ended. They ought to be handled just to prevent this error, but otherwise there is not any code defect.Fixes #479, I would hope.