You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository was archived by the owner on Jul 29, 2024. It is now read-only.
Repository navigation
This repository was archived by the owner on Jul 29, 2024. It is now read-only.
multiCapabilities doesn't invoke parallel instances of WebDriver #5145
Bug report
Using Protractor = 6.0.0-beta, multiCapabilities execute individual captibilities in sequential order rather than running the capabilities in parallel.
My problem with this was we called a method that returned a Promise without awaiting the promise. I ended up putting an await there. This might not be it... It might be:
I think this is the same issue, my error is saying the path to the spec file for chrome is not correct, but I believe it is looking at my project structure, it's obvious. So I believe the error is wrong, but it is the same issue.
Conf file:
In my multiCapabilities I have two different browsers with the argument
respectively, but only Firefox browser launches. I expect both Chrome and Firefox to run parallel (2 instances of webDriver) with different spec files respectively.
browserName: 'chrome',
chromeOptions: {
args: ['--no-sandbox', '--disable-gpu', '--disable-dev-shm-usage', '--use-fake-ui-for-media-stream',
'--ignore-certificate-errors', '--allow-insecure-localhost', '--incognito', '--headless', '--start-maximized', '--user-agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36"'],
prefs: {
download: {
prompt_for_download: false,
default_directory: process.env.DOWNLOAD_DIRECTORY
},
specs: './e2e/file-presentation-flow/*.e2e-spec.ts',
'profile.content_settings.exceptions.clipboard': {
'https://files.globalmeet.com,*': { last_modified: Date.now(), setting: 1 }
},
}
},
},
{
browserName: 'firefox',
'moz:firefoxOptions': {
'args': ['--safe-mode', '--headless']
},
specs: './e2e/smoke-tests/*.e2e-spec.ts'
}
],```
**LOGS:**
```[10:30:35] I/testLogger - [chrome #01] PID: 21345
[chrome #01] /home/ntelang/PGi/convergence-client/node_modules/protractor/built/runner.js:322
[chrome #01] throw new Error('Spec patterns did not match any files.');
[chrome #01] ^
[chrome #01]
[chrome #01] Error: Spec patterns did not match any files.
[chrome #01] at Runner.run (/home/ntelang/PGi/convergence-client/node_modules/protractor/built/runner.js:322:19)
[chrome #01] at process.on (/home/ntelang/PGi/convergence-client/node_modules/protractor/built/runnerCli.js:43:20)
[chrome #01] at emitTwo (events.js:126:13)
[chrome #01] at process.emit (events.js:214:7)
[chrome #01] at emit (internal/child_process.js:772:12)
[chrome #01] at _combinedTickCallback (internal/process/next_tick.js:141:11)
[chrome #01] at process._tickCallback (internal/process/next_tick.js:180:9)
[chrome #01]
[10:30:35] I/testLogger -
[10:30:35] E/launcher - Runner process exited unexpectedly with error code: 1
[10:30:35] I/launcher - 1 instance(s) of WebDriver still running
..[10:31:08] I/testLogger -
------------------------------------
[10:31:08] I/testLogger - [firefox #11] PID: 21350
[firefox #11] Specs: /home/ntelang/PGi/convergence-client/e2e/smoke-tests/smokeTest.e2e-spec.ts
[firefox #11]
[firefox #11] [10:30:35] I/direct - Using FirefoxDriver directly...
[firefox #11] Spec started
When should we expect 6.0.1? It looks like the development of a protractor has stopped completely. And the latest version 6.0.0 has a typescript error. that makes it totally unuseful. Can somebody release just that fix under 6.0.1, and then take care of the rest in a scope of 6.0.2?
Or else, if there's no more development of protractor, can it be announced, so that people start to look for alternatives?
Reacted by lukaslewandowski-pearson, Laszlo Heluszko, Jon Beilke, tstern, yevhen309, Carlos Belizón, capoden, el-davo, mjbs82, Francisco Robles Martín and 4 more
I've found workaround for parallel sessions using bluebird promises.
Bluebird allows to control count of concurrent promises.
But you should know that it was not tested across all available multiCapabilities configurations.
In my case it just fixed configuration with shardTestFiles and maxInstances attributes. launcher.js:
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
}
function rejected(value) {
try {
step(generator["throw"](value));
} catch (e) {
reject(e);
}
}
function step(result) {
result.done ? resolve(result.value) : new P(function (resolve) {
resolve(result.value);
}).then(fulfilled, rejected);
}
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", {value: true});
/**
* The launcher is responsible for parsing the capabilities from the
* input configuration and launching test runners.
*/
const fs = require("fs");
const configParser_1 = require("./configParser");
const exitCodes_1 = require("./exitCodes");
const logger_1 = require("./logger");
const taskRunner_1 = require("./taskRunner");
const taskScheduler_1 = require("./taskScheduler");
const util_1 = require("./util");
const promiseBluebird = require('bluebird');
let logger = new logger_1.Logger('launcher');
let RUNNERS_FAILED_EXIT_CODE = 100;
/**
* Keeps track of a list of task results. Provides method to add a new
* result, aggregate the results into a summary, count failures,
* and save results into a JSON file.
*/
class TaskResults {
constructor() {
// TODO: set a type for result
this.results_ = [];
}
add(result) {
this.results_.push(result);
}
totalSpecFailures() {
return this.results_.reduce((specFailures, result) => {
return specFailures + result.failedCount;
}, 0);
}
totalProcessFailures() {
return this.results_.reduce((processFailures, result) => {
return !result.failedCount && result.exitCode !== 0 ? processFailures + 1 : processFailures;
}, 0);
}
saveResults(filepath) {
let jsonOutput = this.results_.reduce((jsonOutput, result) => {
return jsonOutput.concat(result.specResults);
}, []);
let json = JSON.stringify(jsonOutput, null, ' ');
fs.writeFileSync(filepath, json);
}
reportSummary() {
let specFailures = this.totalSpecFailures();
let processFailures = this.totalProcessFailures();
this.results_.forEach((result) => {
let capabilities = result.capabilities;
let shortName = (capabilities.browserName) ? capabilities.browserName : '';
shortName = (capabilities.logName) ?
capabilities.logName :
(capabilities.browserName) ? capabilities.browserName : '';
shortName += (capabilities.version) ? capabilities.version : '';
shortName += (capabilities.logName && capabilities.count < 2) ? '' : ' #' + result.taskId;
if (result.failedCount) {
logger.info(shortName + ' failed ' + result.failedCount + ' test(s)');
} else if (result.exitCode !== 0) {
logger.info(shortName + ' failed with exit code: ' + result.exitCode);
} else {
logger.info(shortName + ' passed');
}
});
if (specFailures && processFailures) {
logger.info('overall: ' + specFailures + ' failed spec(s) and ' + processFailures +
' process(es) failed to complete');
} else if (specFailures) {
logger.info('overall: ' + specFailures + ' failed spec(s)');
} else if (processFailures) {
logger.info('overall: ' + processFailures + ' process(es) failed to complete');
}
}
}
let allTasksCount;
let taskResults_ = new TaskResults();
/**
* Initialize and run the tests.
* Exits with 1 on test failure, and RUNNERS_FAILED_EXIT_CODE on unexpected
* failures.
*
* @param {string=} configFile
* @param {Object=} additionalConfig
*/
let initFn = function (configFile, additionalConfig) {
return __awaiter(this, void 0, void 0, function* () {
let configParser = new configParser_1.ConfigParser();
if (configFile) {
configParser.addFileConfig(configFile);
}
if (additionalConfig) {
configParser.addConfig(additionalConfig);
}
let config = configParser.getConfig();
logger_1.Logger.set(config);
logger.debug('Running with --troubleshoot');
logger.debug('Protractor version: ' + require('../package.json').version);
logger.debug('Your base url for tests is ' + config.baseUrl);
// Run beforeLaunch
yield util_1.runFilenameOrFn_(config.configDir, config.beforeLaunch);
// 1) If getMultiCapabilities is set, resolve that as
// `multiCapabilities`.
if (config.getMultiCapabilities && typeof config.getMultiCapabilities === 'function') {
if (config.multiCapabilities.length || config.capabilities) {
logger.warn('getMultiCapabilities() will override both capabilities ' +
'and multiCapabilities');
}
// If getMultiCapabilities is defined and a function, use this.
const waitMultiConfig = yield config.getMultiCapabilities();
config.multiCapabilities = waitMultiConfig;
config.capabilities = null;
}
// 2) Set `multicapabilities` using `capabilities`,
// `multicapabilities`, or default
if (config.capabilities) {
if (config.multiCapabilities.length) {
logger.warn('You have specified both capabilities and ' +
'multiCapabilities. This will result in capabilities being ' +
'ignored');
} else {
// Use capabilities if multiCapabilities is empty.
config.multiCapabilities = [config.capabilities];
}
} else if (!config.multiCapabilities.length) {
// Default to chrome if no capabilities given
config.multiCapabilities = [{browserName: 'chrome'}];
}
// 3) If we're in `elementExplorer` mode, throw an error and exit.
if (config.elementExplorer || config.framework === 'explorer') {
const err = new Error('Deprecated: Element explorer depends on the ' +
'WebDriver control flow, and thus is no longer supported.');
logger.error(err);
process.exit(1);
}
// 4) Run tests.
let scheduler = new taskScheduler_1.TaskScheduler(config);
if (!allTasksCount){
allTasksCount = scheduler.numTasksOutstanding();
}
process.on('uncaughtException', (exc) => {
let e = (exc instanceof Error) ? exc : new Error(exc);
if (config.ignoreUncaughtExceptions) {
// This can be a sign of a bug in the test framework, that it may
// not be handling WebDriver errors properly. However, we don't
// want these errors to prevent running the tests.
logger.warn('Ignoring uncaught error ' + exc);
return;
}
logger.error(e.message);
logger.error(e.stack);
if (e instanceof exitCodes_1.ProtractorError) {
let protractorError = e;
process.exit(protractorError.code);
} else {
process.exit(1);
}
});
process.on('unhandledRejection', (reason, p) => {
if (reason.stack.match('angular testability are undefined') ||
reason.stack.match('angular is not defined')) {
logger.warn('Unhandled promise rejection error: This is usually occurs ' +
'when a browser.get call is made and a previous async call was ' +
'not awaited');
}
logger.warn(p);
});
process.on('exit', (code) => {
if (code) {
logger.error('Process exited with error code ' + code);
} else if (scheduler.numTasksOutstanding() > 0) {
logger.error('BUG: launcher exited with ' + scheduler.numTasksOutstanding() + ' tasks remaining');
process.exit(RUNNERS_FAILED_EXIT_CODE);
}
});
// Run afterlaunch and exit
const cleanUpAndExit = (exitCode) => __awaiter(this, void 0, void 0, function* () {
try {
const returned = yield util_1.runFilenameOrFn_(config.configDir, config.afterLaunch, [exitCode]);
if (typeof returned === 'number') {
process.exit(returned);
} else {
process.exit(exitCode);
}
} catch (err) {
logger.error('Error:', err);
process.exit(1);
}
});
const totalTasks = scheduler.numTasksOutstanding();
let forkProcess = false;
if (totalTasks > 1) { // Start new processes only if there are >1 tasks.
forkProcess = true;
if (config.debug) {
throw new exitCodes_1.ConfigError(logger, 'Cannot run in debug mode with multiCapabilities, count > 1, or sharding');
}
}
const createNextTaskRunner = () => __awaiter(this, void 0, void 0, function* () {
return new Promise((resolve) => __awaiter(this, void 0, void 0, function* () {
const task = scheduler.nextTask();
if (task) {
const taskRunner = new taskRunner_1.TaskRunner(configFile, additionalConfig, task, forkProcess);
try {
const result = yield taskRunner.run();
if (result.exitCode && !result.failedCount) {
logger.error('Runner process exited unexpectedly with error code: ' + result.exitCode);
}
taskResults_.add(result);
task.done();
// yield createNextTaskRunner();
// If all tasks are finished
// if (scheduler.numTasksOutstanding() === 0) {
resolve();
// }
logger.info(scheduler.countActiveTasks() + ' instance(s) of WebDriver still running');
} catch (err) {
const errorCode = exitCodes_1.ErrorHandler.parseError(err);
logger.error('Error:', err.stack || err.message || err);
yield cleanUpAndExit(errorCode ? errorCode : RUNNERS_FAILED_EXIT_CODE);
}
} else {
resolve();
}
}));
});
const taskList = Array(allTasksCount).fill(() => createNextTaskRunner());
const maxConcurrentTasks = scheduler.maxConcurrentTasks();
yield promiseBluebird.map(taskList, task => task(), {concurrency: maxConcurrentTasks});
// for (let i = 0; i < maxConcurrentTasks; ++i) {
// yield createNextTaskRunner();
// }
logger.info('Running ' + scheduler.countActiveTasks() + ' instances of WebDriver');
// By now all runners have completed.
// Save results if desired
if (config.resultJsonOutputFile) {
taskResults_.saveResults(config.resultJsonOutputFile);
}
taskResults_.reportSummary();
let exitCode = 0;
if (taskResults_.totalProcessFailures() > 0) {
exitCode = RUNNERS_FAILED_EXIT_CODE;
} else if (taskResults_.totalSpecFailures() > 0) {
exitCode = 1;
}
yield cleanUpAndExit(exitCode);
// Start `const maxConcurrentTasks` workers for handling tasks in
// the beginning. As a worker finishes a task, it will pick up the next
// task from the scheduler's queue until all tasks are gone.
});
};
exports.init = initFn;
//# sourceMappingURL=launcher.js.map
Appreciate if you could provide some insight into the future of Protractor. Its' been more than 6 months since we have any update on Protractor 6.0. If the plan is to abandon protractor, kindly let us know so that we have enough room to look for the alternatives.
Reacted by Haritha Wickremasinghe, Himanshu Jain, Jared Anderson and Dmitry Gorelenkov
My problem with this was we called a method that returned a Promise without awaiting the promise. I ended up putting an await there. This might not be it... It might be:
here you wait for every runner, sequentially in the loop.
now:
for (let i = 0; i < maxConcurrentTasks; ++i) {
await createNextTaskRunner();
}
should be:
const runners = [];
for (let i = 0; i < maxConcurrentTasks; ++i) {
runners.push(createNextTaskRunner());
}
await Promise.all(runners); // wait for all, running simultaneously
@heathkit@cnishina@juliemr no longer work on Protractor, we can't speak to future plans. We continue to use Protractor internally, and there's a lot of other projects at Google that depend on it.
The Angular team would like to invest more in Protractor, and will have time now that they've landed Ivy. @IgorMinar will be better able to answer questions about the future of Protractor.
Activity
vsravuri commentedon Feb 8, 2019
@cnishina
Could you please have a look at this issue? This issue is blocking me from running automation tests using Protractor = 6.0.0-beta branch.
vsravuri commentedon Feb 23, 2019
@cnishina @heathkit @juliemr
Could you please have a look at this issue? I am unable to run my tests with multiCapabilities using 6.0.0-beta build
vsravuri commentedon Mar 29, 2019
@cnishina
Any reason why you think multiCapabilities not working in Protractor 6.0.0?
pkearney13 commentedon Mar 29, 2019
Same here
jithinkmatthew commentedon Mar 29, 2019
Facing same problem with protractor version
6.0.0vsravuri commentedon Mar 29, 2019
@cnishina
Any update on this issue?
cnishina commentedon Mar 29, 2019
Yikes, this appears to be an issue. Maybe keep using 5.4.2 until this is resolved. I'm not sure and will talk it over with Julie.
cnishina commentedon Mar 30, 2019
While removing q from Protractor, I did run into this (which might be suspect): https://github.com/angular/protractor/blob/master/lib/launcher.ts#L231
My problem with this was we called a method that returned a Promise without awaiting the promise. I ended up putting an await there. This might not be it... It might be:
https://github.com/angular/protractor/blob/master/lib/launcher.ts#L250
vsravuri commentedon Mar 30, 2019
@cnishina
Appreciate your help for looking into this issue. I will continue using 5.4.2 until this issue is resolved.
vsravuri commentedon Apr 8, 2019
@juliemr @cnishina
Any plan to fix this issue in the beta release you are working on?
vsravuri commentedon May 7, 2019
@cnishina @juliemr
Both multiCapabilities & shardTestFiles (#5232) doesn't work with Protractor 6.0.0
Eagerly waiting for next release of Protractor to unblock in running parallel tests.
cnishina commentedon May 7, 2019
Similar issue here: #5232
I have not had time to look at this.
gawicks commentedon Jun 1, 2019
Any updates on this?
telangn commentedon Jun 18, 2019
I think this is the same issue, my error is saying the path to the spec file for chrome is not correct, but I believe it is looking at my project structure, it's obvious. So I believe the error is wrong, but it is the same issue.
Conf file:
In my multiCapabilities I have two different browsers with the argument
**specs: ./e2e/file-presentation-flow/*.e2e-spec.ts**and
**specs: './e2e/smoke-tests/*.e2e-spec.ts**respectively, but only Firefox browser launches. I expect both Chrome and Firefox to run parallel (2 instances of webDriver) with different spec files respectively.
wodddy commentedon Aug 7, 2019
When should we expect 6.0.1? It looks like the development of a protractor has stopped completely. And the latest version 6.0.0 has a typescript error. that makes it totally unuseful. Can somebody release just that fix under 6.0.1, and then take care of the rest in a scope of 6.0.2?
Or else, if there's no more development of protractor, can it be announced, so that people start to look for alternatives?
froblesmartin commentedon Sep 11, 2019
Any update on this? Has someone found any workaround in the meantime? @cnishina
Even more important: Is the project abandoned?
abruslik commentedon Sep 25, 2019
I've found workaround for parallel sessions using bluebird promises.
Bluebird allows to control count of concurrent promises.
But you should know that it was not tested across all available multiCapabilities configurations.
In my case it just fixed configuration with shardTestFiles and maxInstances attributes.
launcher.js:
Phonesis commentedon Jan 14, 2020
@cnishina Keen to know where things stand with Protractor and future of version 6. Not seen any updates for few months?
froblesmartin commentedon Jan 14, 2020
I was trying to contact some developers of this project and Angular 4 months ago and I had no reply. It really seems abandoned.
Kungfoowiz commentedon Jan 15, 2020
Yes, this is important. Please announce if protractor development is being continued or we need to look into alternatives?
telangn commentedon Jan 15, 2020
Start using Cypress
Phonesis commentedon Jan 15, 2020
I don't see Cypress as a viable alternative atm. It only supports Chrome and doesn't work with BrowserStack. Also, it requires a paid license.
vsravuri commentedon Jan 15, 2020
@heathkit @cnishina @juliemr
Appreciate if you could provide some insight into the future of Protractor. Its' been more than 6 months since we have any update on Protractor 6.0. If the plan is to abandon protractor, kindly let us know so that we have enough room to look for the alternatives.
yadimon commentedon Mar 4, 2020
here you wait for every runner, sequentially in the loop.
now:
should be:
and
Promise((resolve) => ...)(https://github.com/angular/protractor/blob/master/lib/launcher.ts#L219)should be just async function, so remove the line. Otherwise, no
resolve()happens at the end of the method with outstanding tasks https://github.com/angular/protractor/blob/master/lib/launcher.ts#L235heathkit commentedon Mar 4, 2020
@heathkit @cnishina @juliemr no longer work on Protractor, we can't speak to future plans. We continue to use Protractor internally, and there's a lot of other projects at Google that depend on it.
The Angular team would like to invest more in Protractor, and will have time now that they've landed Ivy. @IgorMinar will be better able to answer questions about the future of Protractor.
rajjaiswalsaumya commentedon Aug 27, 2020
Is someone fixing this ? I need it badly. Our tests serially takes more than an hour. Please help.