[heft] "heft --debug test" and "heft test --verbose" should enable Jest's verbose mode #4402
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Summary
The problem: When debugging code, it's common practice to add
console.log()
in various files to monitor variable states, while also interactively stepping through breakpoints in the VS Code debugger. This experience is broken for unit tests, because Jest reroutesconsole.log()
to a special handler that only prints the output after the test has completed.Details
Why would Jest do that? The ideal model seems something like:
console.log()
should print to the interactive consoleconsole.log()
should fail the build, because nobody wants thousands of lines of noisy unit test output in their CI logsHowever, perhaps this restriction was too difficult to enforce. Probably many projects will call
console.log()
as part of their normal execution, and if it can't be mocked easily, then when Jest runs that code, it will always print to the console as a side effect. So instead Jest reroutesconsole.log()
to its internalBufferedConsole
which collects the strings, which are then passed to the Jest reporter for reporting at the end of the test. This probably also ensures that parallel test runs don't interfere with each other's output.This also allows the
console.log()
output to be reformatted so that it cannot be confused with build logs from the toolchain. OurHeftJestReporter
adds blue prefixes as seen below, for example:Okay, but what about interactive debugging? It is extremely frustrating to call
console.log()
while stepping through code in the debugger, and it doesn't get printed, and there's no way to see the results without using watch windows to access Jest internals.How can we ensure that
console.log()
gets printed immediately in that scenario, rather than buffering it? The obvious answer is to hook into Jest'sBufferedConsole
provider and also print to the realconsole.log()
API. This would have the benefit of being compatible with VS Code's"console": "internalConsole"
in launch.json, whereas Jest's output gets printed to STDERR and is therefore invisible without"console": "integratedTerminal"
.But unfortunately, this turns out to be impossible without monkey-patching Jest, because the buffering is hard-wired:
jest-runner/src/runTest.ts
However although we can't intercept the logging events, if we set
globalConfig.verbose
then we getCustomConsole
which does prints interactively, but just with rather ugly-looking output:Despite being ugly, I think it is an improvement for the interactive debugging experience, and perhaps more consistent with expectations of
--verbose
. So that is what I've done in this PR.How do we distinguish debugging from a normal build? In this PR the definition is
heft --debug test
orheft test --verbose
.Possible alternative implementation
If someone really hates the
CustomConsole
formatting, we could consider monkey-patching Jest instead.What is particularly annoying with Jest's design is that
console.error()
gets formatted like a build failure:But then the Jest run "succeeds" with process exit code
0
. 🤦How it was tested
verbose:true
does not affect the routing of logging to STDERR vs STDOUT (which would impact Rush's interpretation of "success with warnings")Impacted documentation
@D4N14L @elliot-nelson @dmichon-msft