diff --git a/README.md b/README.md index a8312723f..29b5ffef5 100644 --- a/README.md +++ b/README.md @@ -76,6 +76,7 @@ Hermione is a utility for integration testing of web pages using [WebdriverIO](h - [Test Collection](#test-collection) - [Test Parser API](#test-parser-api) - [setController(name, methods)](#setcontrollername-methods) +- [Debug mode](#debug-mode) @@ -767,6 +768,8 @@ Configuration data can be changed depending on extra conditions in the `prepareE -r, --reporter Test reporter -b, --browser Run tests only in specified browser --grep Run only tests matching string or regexp + --inspect[=[host:]port] Run tests in debug mode + --inspect-brk[=[host:]port] Run tests in debug mode with break at the start ``` For example, @@ -1001,3 +1004,15 @@ describe('foo', () => { ``` **Note**: controller will be removed as soon as current file will be parsed + +## Debug mode + +In order to understand what is going on in the test step by step, there is a debug mode. You can run tests in this mode using these options: --inspect and --inspect-brk. The difference between them is that the second one stops before executing the code. + +Example: +``` +hermione path/to/mytest.js --inspect +``` + +**Note**: In the debugging mode, only one worker is started and all tests are performed only in it. +Use this mode with option `sessionsPerBrowser=1` in order to debug tests one at a time. diff --git a/lib/cli/index.js b/lib/cli/index.js index 2bce217bd..3935914b8 100644 --- a/lib/cli/index.js +++ b/lib/cli/index.js @@ -31,6 +31,8 @@ exports.run = () => { .option('-s, --set ', 'run tests only in the specified set', collect) .option('--grep ', 'run only tests matching the pattern') .option('--update-refs', 'update screenshot references or gather them if they do not exist ("assertView" command)') + .option('--inspect [inspect]', 'nodejs inspector on [=[host:]port]') + .option('--inspect-brk [inspect-brk]', 'nodejs inspector with break at the start') .arguments('[paths...]') .action(async (paths) => { try { @@ -39,7 +41,11 @@ exports.run = () => { browsers: program.browser, sets: program.set, grep: program.grep, - updateRefs: program.updateRefs + updateRefs: program.updateRefs, + inspectMode: (program.inspect || program.inspectBrk) && { + inspect: program.inspect, + inspectBrk: program.inspectBrk + } }); process.exit(isTestsSuccess ? 0 : 1); diff --git a/lib/hermione.js b/lib/hermione.js index f7892cd2a..7afb6936d 100644 --- a/lib/hermione.js +++ b/lib/hermione.js @@ -24,7 +24,7 @@ module.exports = class Hermione extends BaseHermione { this.emit(RunnerEvents.CLI, parser); } - async run(testPaths, {browsers, sets, grep, updateRefs, reporters} = {}) { + async run(testPaths, {browsers, sets, grep, updateRefs, reporters, inspectMode} = {}) { validateUnknownBrowsers(browsers, _.keys(this._config.browsers)); this._runner = Runner.create(this._config) @@ -37,7 +37,7 @@ module.exports = class Hermione extends BaseHermione { eventsUtils.passthroughEventAsync(this._runner, this, _.values(RunnerEvents.getAsync())); eventsUtils.passthroughEventAsync(signalHandler, this, RunnerEvents.EXIT); - RuntimeConfig.getInstance().extend({updateRefs}); + RuntimeConfig.getInstance().extend({updateRefs, inspectMode}); await this._init(); diff --git a/lib/runner/workers.js b/lib/runner/workers.js index f2f392f4a..5c535d26a 100644 --- a/lib/runner/workers.js +++ b/lib/runner/workers.js @@ -26,18 +26,41 @@ module.exports = class Workers { _createWorkerFarm() { const workerFilepath = require.resolve('../worker'); + const params = { maxConcurrentWorkers: this._config.system.workers, maxCallsPerWorker: this._config.system.testsPerWorker, maxConcurrentCallsPerWorker: Infinity, autoStart: true, maxRetries: 0, - onChild: (child) => this._initChild(child) + onChild: (child) => this._initChild(child), + ...this._inspectParams() }; return workerFarm(params, workerFilepath, ['runTest']); } + _inspectParams() { + const runtimeConfig = RuntimeConfig.getInstance(); + + if (!runtimeConfig || !runtimeConfig.inspectMode) { + return; + } + + const {inspect, inspectBrk} = runtimeConfig.inspectMode; + + const inspectName = inspectBrk ? 'inspect-brk' : 'inspect'; + let inspectValue = inspectBrk ? inspectBrk : inspect; + + inspectValue = typeof inspectValue === 'string' ? `=${inspectValue}` : ''; + + return { + workerOptions: {execArgv: [`--${inspectName}${inspectValue}`]}, + maxConcurrentWorkers: 1, + maxCallsPerWorker: Infinity + }; + } + _initChild(child) { child.on('message', ({event} = {}) => { switch (event) { diff --git a/test/lib/cli/index.js b/test/lib/cli/index.js index cd4edcdf1..9a788aca9 100644 --- a/test/lib/cli/index.js +++ b/test/lib/cli/index.js @@ -205,4 +205,22 @@ describe('cli', () => { assert.calledWith(logger.error, 'some-error'); }); + + it('should turn on debug mode from cli', async () => { + onParse((parser) => parser.inspect = true); + + hermioneCli.run(); + await actionPromise; + + assert.calledWithMatch(Hermione.prototype.run, any, {inspectMode: {inspect: true}}); + }); + + it('should turn on debug mode from cli with params', async () => { + onParse((parser) => parser.inspectBrk = '9229'); + + hermioneCli.run(); + await actionPromise; + + assert.calledWithMatch(Hermione.prototype.run, any, {inspectMode: {inspectBrk: '9229'}}); + }); }); diff --git a/test/lib/hermione.js b/test/lib/hermione.js index ef956c965..8806a35d2 100644 --- a/test/lib/hermione.js +++ b/test/lib/hermione.js @@ -131,10 +131,13 @@ describe('hermione', () => { it('should init runtime config', () => { mkRunnerStub_(); - return runHermione([], {updateRefs: true}) + return runHermione([], {updateRefs: true, inspectMode: {inspect: true}}) .then(() => { assert.calledOnce(RuntimeConfig.getInstance); - assert.calledOnceWith(RuntimeConfig.getInstance.lastCall.returnValue.extend, {updateRefs: true}); + assert.calledOnceWith( + RuntimeConfig.getInstance.lastCall.returnValue.extend, + {updateRefs: true, inspectMode: {inspect: true}} + ); }); }); diff --git a/test/lib/runner/workers.js b/test/lib/runner/workers.js index c72974c90..f73986aa0 100644 --- a/test/lib/runner/workers.js +++ b/test/lib/runner/workers.js @@ -53,6 +53,31 @@ describe('Workers', () => { ['runTest'] ); }); + + it('should init worker farm in debug mode', () => { + RuntimeConfig.getInstance.returns({inspectMode: {inspect: '9229'}}); + + mkWorkers_({ + system: { + workers: 100500, + testsPerWorker: 500100 + } + }); + + assert.calledOnceWith(workerFarm, + { + workerOptions: {execArgv: ['--inspect=9229']}, + maxConcurrentWorkers: 1, + maxCallsPerWorker: Infinity, + maxConcurrentCallsPerWorker: Infinity, + autoStart: true, + maxRetries: 0, + onChild: sinon.match.func + }, + sinon.match('lib/worker/index.js'), + ['runTest'] + ); + }); }); describe('communication with worker', () => {