-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Fix flakey file system tests #10541
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 flakey file system tests #10541
Conversation
Kudos, SonarCloud Quality Gate passed!
|
Codecov Report
@@ Coverage Diff @@
## master #10541 +/- ##
==========================================
- Coverage 60.76% 60.74% -0.03%
==========================================
Files 578 578
Lines 31355 31355
Branches 4463 4464 +1
==========================================
- Hits 19053 19046 -7
- Misses 11335 11339 +4
- Partials 967 970 +3
Continue to review full report at Codecov.
|
async function writeToStream(filename: string, write: (str: fs.WriteStream) => void) { | ||
const closeDeferred = createDeferred(); | ||
const stream = fileSystem.createWriteStream(filename); | ||
stream.on('close', () => closeDeferred.resolve()); |
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.
Isn't the requirement to check whether createWriteStream
returns a writable stream
.
At the end of the day the API is createWriteStream
and that's what needs to be tested, not testing the functionality of stream
object returned by nodejs.
There are other methods on streams that we're not testing here, pipe
, event handlers
, etc..
I think the test is testing the wrong thing. We're testing if node streams work.
I'd suggest removing all the tests and changing to:
const isStream = require('is-stream');
const stream = fileSystem.createWriteStream(filename);
assert.isOk(isStream.writable(stream))
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.
Also, listening to close
isn't sufficient, we'd need to listen to flush
event to know if data was flushed. But that's not 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.
There is no flush method on the write stream.
And I didn't want to change the tests here, just make them pass. Who ever owns these can make that change.
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.
- Check for
flush
event - Call
end
method.
Who ever owns these can make that change.
@karthiknadig do we need such tests (see my comments).
Its just more unnecessary flaky tests. Also slower
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.
I think testing that it returns a writable stream should be enough. If I remember correctly this particular API was not completely supported or we had some asks on VSCode. /cc @ericsnowcurrently for more info.
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.
@ericsnowcurrently I can make the change suggested if you like.
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.
I'm just going to submit. Eric can change the tests later if he likes.
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.
These functional tests verify the behavior that the extension relies on. This matters because the node and vscode APIs don't have exactly the same behavior. Other similar functional tests uncovered such cases, showing why it's important to verify the expected behavior (to an extent).
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.
@rchiodo, as to checking for flush and calling .end(), I don't see a problem offhand. I'd have to double-check the node docs, but honestly, I trust Don. 😄
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.
There are other methods on streams that we're not testing here, pipe, event handlers, etc..
True. And if the extension relies on those then we should consider testing them. Then again, it probably isn't worth the effort until the VS Code FS API provides some sort of WriteStream. My vote is to not add more tests. Regardless, it should be handled in a separate issue.
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.
LGTM
I just have one comment about a slightly different helper approach that keeps the code-under-test in the test function.
Also, the flush/end thing Don suggested (if you agree it makes sense).
const stream = fileSystem.createWriteStream(filename); | ||
stream.write(data); | ||
stream.destroy(); | ||
await writeToStream(filename, s => s.write(data)); |
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.
FWIW, I'm a big believer of keeping as much of the test-targeted code in the test function as possible. The following variation on your solution would do that. It uses a sort of context-manager style that reduces the amount of code the test cares about without obscuring the code the test does care about:
await writeToStream(filename, s => s.write(data)); | |
const stream = fileSystem.createWriteStream(filename); | |
await withClosing(stream, () => { | |
stream.write(data); | |
}); |
This would rely on the following helper, derived from writeToStream()
:
async function withClosing(stream: WriteStream, test: () => void) {
const closeDeferred = createDeferred();
stream.on('close', () => closeDeferred.resolve());
test()
stream.end();
stream.close();
stream.destroy();
await closeDeferred.promise;
}
Other approaches (in order to most-to-least readable result):
- for tests on operations on the stream (rather than its creation), we could use a helper to create the stream:
function createWriteStream(filename: string): [WriteStream, () => Promise<void>] { ... }
- combine that with the context-manager style:
async function withStream(filename: string, (stream: WriteStream) => Promise<void>) { ... }
- be more exliicit about it (1 helpers):
function getCloser(stream: WriteStream): () => Promise<void> { ... }
- be more exliicit about it (2 helpers):
function prepForClose(stream: WriteStream): Promise<void> { ... }
function destroyStream(stream: WriteStream) { ... }
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.
Sorry already submitted. Feel free to update if you like.
There is no flush method on a stream though, so don't add that:
https://nodejs.org/api/stream.html
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.
There's actually a 'finish' event that fires after all data has been written. That's likely better than the close event.
* master: Fix flakey file system tests (#10541) Tweaks for gather (#10532) Fix #10437: Update launch.json handling to support "listen" and "connect" (#10517) Add conda support to nightly flake test (#10523) Rename datascience to datascience_modules (#10525) Clean up the extension activation code. (#10455) Allow escape and ctrl+U to clear the interactive window (#10513) Fix builtins so they don't interfere with our execution (#10511) Jupyter autocompletion will only show up on empty lines, (#10420) notify on missing kernel and interpreter with kernel (#10508)
* Update version and change log * Fix flakey file system tests (#10541) Co-authored-by: Rich Chiodo <rchiodo@users.noreply.github.com>
File system tests seem to fail randomly. I believe it's because they're not waiting for the file write to finish.
Here's an example failure:
https://dev.azure.com/ms/vscode-python/_build/results?buildId=67769&view=ms.vss-test-web.build-test-results-tab&runId=2169996&resultId=100021&paneView=debug