From 185a941acc779923fc76b2ce2cde6a3dcf020783 Mon Sep 17 00:00:00 2001 From: Peter Bacon Darwin Date: Thu, 31 Aug 2017 22:06:22 +0100 Subject: [PATCH] test: support debugging unit tests in node (#18987) PR Close #18987 --- docs/DEBUG.md | 59 ++++++++++++++++++++++++++++++++++++++++ docs/DEVELOPER.md | 2 ++ test.sh | 5 ++-- tools/tsc-watch/index.ts | 23 ++++++++++------ 4 files changed, 79 insertions(+), 10 deletions(-) create mode 100644 docs/DEBUG.md diff --git a/docs/DEBUG.md b/docs/DEBUG.md new file mode 100644 index 0000000000..af98cafb78 --- /dev/null +++ b/docs/DEBUG.md @@ -0,0 +1,59 @@ +# Debugging Angular + +The Angular project has comprehensive unit tests for the core packages and the tools. +The core packages are tested both in the browser (via Karma) and on the server (via Node.js). + +## Debugging in Karma + +Run the unit tests as normal using via the `./test.sh` script. For example: + +```bash +./test.sh browserNoRouter +``` + +Once the initial build has completed and the Karma server has started up, you can go to the +Chrome browser that is automatically opened, usually pointing to `http://localhost:9876`. +The script will sit watching for code changes, recompiling the changed files and triggering +further runs of the unit tests in the browser. + +In this browser there is a "DEBUG" link (in the top right corner). Clicking this link will +open up a new tab that will run the unit tests and will not timeout, giving you time to +step through the code. + +Open up this tab's developer console to access the source code viewer where you can set +breakpoints and interrogate the current stack and variables. + +It is useful to focus your debugging on one test at a time by changing that test to be +defined using the `fit(...)` function, rather than `it(...)`. Moreover it can be helpful +to place a `debugger` statement in this `fit` clause to cause the debugger to stop when +it hits this test. + +## Debugging in Node + +Run the unit tests as normal using the `./test.sh` script, but add the `--debug` flag to +the command. For example: + +```bash +./test.sh node --debug +``` + +Once the initial building has completed, the script will watch for code changes, recompiling +and running the unit tests via a tool call `cjs-jasmine`. Due to the `--debug` flag, each +test run will create a debugging server listening on a port (such as 9229), which can be +connected to by a debugger. + +You can use Chrome as the debugger by navigating to `chrome://inspect` then clicking the +"Open dedicated DevTools for Node" link. This will open up a Developer console, which will +automatically connect to the debugging server. + +It is useful to focus your debugging on one test at a time by changing that test to be +defined using the `fit(...)` function, rather than `it(...)`. Moreover it can be helpful +to place a `debugger` statement in this `fit` clause to cause the debugger to stop when +it hits this test. + +**Problem with node 6:** at the time of writing, the node process does not tell the Chrome +debugger when it has completed, and so the debugger is not able to automatically disconnect +from listening to the debugging server. To solve this, just close the developer tools window +after each run of the unit tests, before making changes to the code. This is fixed in node 8 +and may be backported to node 6. This issue is tracked in +https://github.com/nodejs/node/pull/12814#issuecomment-309908579. diff --git a/docs/DEVELOPER.md b/docs/DEVELOPER.md index 86f75cf63b..ab7ee6ce8d 100644 --- a/docs/DEVELOPER.md +++ b/docs/DEVELOPER.md @@ -126,6 +126,8 @@ $ ./test.sh tools # Run angular tooling (not framework) tests You should execute the 3 test suites before submitting a PR to github. +See [DEBUG.md](DEBUG.md) for information on debugging the code while running the unit tests. + All the tests are executed on our Continuous Integration infrastructure and a PR could only be merged once the tests pass. - CircleCI fails if your code is not formatted properly, diff --git a/test.sh b/test.sh index 998406ee25..372e3a8142 100755 --- a/test.sh +++ b/test.sh @@ -6,7 +6,8 @@ if [ $# -eq 0 ] then echo "Angular test runner. (No platform specified)" echo - echo "./test.sh [node|browser|browserNoRouter|router|tools]" + echo "./test.sh [node|browser|browserNoRouter|router|tools] [--debug]" + echo "(--debug flag only relevant to 'node' and 'tools' testing - see https://github.com/angular/angular/blob/master/docs/DEBUG.md)" echo else cd `dirname $0` @@ -25,5 +26,5 @@ else node --max-old-space-size=3000 dist/all/@angular/tsc-wrapped/src/main -p packages node --max-old-space-size=3000 dist/all/@angular/tsc-wrapped/src/main -p modules fi - node dist/tools/tsc-watch/ $1 watch + node dist/tools/tsc-watch/ $1 watch $2 fi diff --git a/tools/tsc-watch/index.ts b/tools/tsc-watch/index.ts index d3e1e44f39..000d4014bc 100644 --- a/tools/tsc-watch/index.ts +++ b/tools/tsc-watch/index.ts @@ -29,6 +29,7 @@ function md(dir: string, folders: string[]) { let tscWatch: TscWatch = null; const platform = process.argv.length >= 3 ? process.argv[2] : null; const runMode: string = process.argv.length >= 4 ? process.argv[3] : null; +const debugMode = process.argv.some(arg => arg === '--debug'); const BaseConfig = { start: 'File change detected. Starting incremental compilation...', error: 'error', @@ -36,13 +37,14 @@ const BaseConfig = { }; if (platform == 'node') { + const specFiles = [ + '@angular/**/*_spec.js', '@angular/compiler-cli/test/**/*_spec.js', + '@angular/benchpress/test/**/*_spec.js' + ]; tscWatch = new TscWatch(Object.assign( { tsconfig: 'packages/tsconfig.json', - onChangeCmds: [[ - 'node', 'dist/tools/cjs-jasmine', '--', '@angular/**/*_spec.js', - '@angular/compiler-cli/test/**/*_spec.js', '@angular/benchpress/test/**/*_spec.js' - ]] + onChangeCmds: [createNodeTestCommand(specFiles, debugMode)] }, BaseConfig)); } else if (platform == 'browser') { @@ -94,13 +96,11 @@ if (platform == 'node') { }, BaseConfig)); } else if (platform == 'tools') { + const specFiles = ['dist/all/@angular/tsc-wrapped/**/*{_,.}spec.js']; tscWatch = new TscWatch(Object.assign( { tsconfig: ['tools/tsconfig.json', 'packages/tsc-wrapped/tsconfig.json'], - onChangeCmds: [[ - 'node', 'dist/tools/cjs-jasmine/index-tools', '--', - 'dist/all/@angular/tsc-wrapped/**/*{_,.}spec.js' - ]] + onChangeCmds: [createNodeTestCommand(specFiles, debugMode)] }, BaseConfig)); } else { @@ -114,3 +114,10 @@ if (runMode === 'watch') { } else { tscWatch.run(); } + +function createNodeTestCommand(specFiles: string[], debugMode: boolean) { + return ['node'] + .concat(debugMode ? ['--inspect'] : []) + .concat('dist/tools/cjs-jasmine', '--') + .concat(specFiles); +}