This is a really interesting question. Our organization has been probing how much of our CI/CD pipeline can be done in a serverless fashion. This is right up that alley.
Unfortunately, I don't think there is an elegant way to run protractor
from another Node script. That is, protractor
doesn't seem to expose an API that makes it easy to consume in such a manner.
It's been asked for, but (as a relative newcomer to protractor
) the comment right before the issue was closed doesn't contain enough detail for me to know how to take that approach. So, the not-so-elegant approach:
Child Process
Prior comments notwithstanding, you can indeed run protractor
from within another Node script, including a Node script executing in AWS' Lambda environment. There may be prettier/better ways to do this, but I took this answer and based the following Lambda function on it:
'use strict';
module.exports.runtest = (event, context, callback) => {
var npm = require('npm');
var path = require('path');
var childProcess = require('child_process');
var args = ['conf.js'];
npm.load({}, function() {
var child = childProcess
.fork(path.join(npm.root, 'protractor/bin/protractor'), args)
.on('close', function(errorCode) {
const response = {
statusCode: 200,
body: JSON.stringify({
message: `Selenium Test executed on BrowserStack! Child process Error Code: ${errorCode}`,
}),
};
callback(null, response);
});
process.on('SIGINT', child.kill);
});
};
var args = ['conf.js'];
points to the protractor
config file, which in turn points to the test (index.js
in this case):
exports.config = {
'specs': ['./index.js'],
'seleniumAddress': 'http://hub-cloud.browserstack.com/wd/hub',
'capabilities': {
'browserstack.user': '<BROWSERSTACK_USER>',
'browserstack.key': '<BROWSERSTACK_KEY>',
'browserName': 'chrome'
}
};
Repository here.
Notes
npm
is a runtime dependency using this approach, meaning it has to be packaged into your deployable. This makes for a relatively large lambda function. At ~20mb, it's big enough that you don't get to edit code inline in the AWS console anymore. An approach that didn't package npm
as a runtime dependency would be much nicer.
- Don't forget Lambda has a hard 5 minute time limit. Your tests will need to complete in less time than that.
- Watch the clock. In many instances, my toy example only uses a browser for a couple of seconds, but the overhead (of connecting to BrowserStack, mostly, I presume) makes the Lambda take 12-30 seconds altogether. Paying for 30 seconds of compute to use a browser for 2.5 seconds doesn't sound like a win. Larger batches of tests might be less wasteful.
- You do get CloudWatch logging of the child process without doing any extra plumbing yourself, which is nice.
- Disclaimer: My example has only been happy-path tested, and I'm no expert on child processes in Node.