Setting up Continuous Integration of Protractor using Jenkins - selenium

I am writing automation test scripts using Protractor and now I need to set up the CI for this using Jenkins.
Tasks it needs to perform are:
Starting the selenium standalon server.
Starting the test using conf.js file.
Stopping the selenium standalone server.
Can anyone help in this regard?

I created a small bash script to do this.
# start selenium
./node_modules/protractor/bin/webdriver-manager start > /dev/null 2>&1 &
# wait until selenium is up
while ! curl http://localhost:4444/wd/hub/status &>/dev/null; do :; done
# run the build
grunt cibuild --force
# stop selenium
curl -s -L http://localhost:4444/selenium-server/driver?cmd=shutDownSeleniumServer > /dev/null 2>&1
This script is invoked from a free-style project in jenkins (Build > Execute shell)
Then the test result report is generated by reading the protractor test results. Hence, you have to produce junit reports from protractor, (look here) :
onPrepare: function() {
// The require statement must be down here, since jasmine-reporters
// needs jasmine to be in the global and protractor does not guarantee
// this until inside the onPrepare function.
require('jasmine-reporters');
jasmine.getEnv().addReporter(
new jasmine.JUnitXmlReporter('xmloutput', true, true));
},
To make the report visible in jenkins i add a post build action in the job: Publish JUnit test result report:

Alternatively, you could run this as a Grunt Task. First install grunt on Jenkins. Install the NPM packages for protractor_webdriver and protractor. Setup the configuration file to point the the node_module path and config file paths.
http://sideroad.secret.jp/articles/grunt-on-jenkins/
Then install protractor node modules. The Gruntfile would look similar to this. I created a test directory where the conf and spec files would be located.
module.exports = function (grunt) {
grunt.initConfig({
protractor_webdriver: {
your_target: {
options: {
path: 'node_modules/protractor/bin/',
command: 'webdriver-manager start'
}
}
},
protractor: {
options: {
configFile: "node_modules/protractor/referenceConf.js", // Default config file
keepAlive: true, // If false, the grunt process stops when the test fails.
noColor: false, // If true, protractor will not use colors in its output.
args: {
// Arguments passed to the command
}
},
your_target: {
options: {
configFile: "test/conf.js", // Target-specific config file
args: {} // Target-specific arguments
}
}
}
});
grunt.registerTask('p:test', [
'protractor_webdriver',
'protractor'
]);
});

The newest protractor allows you to run the selenium standalone server directly from the conf.js (or whatever protractor entry point you have).
comment out (or delete) the seleniumAddress: 'http://localhost:4444/wd/hub', line, and replace it with seleniumServerJar: './node_modules/protractor/selenium/latest.jar'.
latest.jar isn't installed by default, I created it as a symlink to the latest version installed via npm install protractor --save. This gives longer life to my conf.js files in the same directory.
Within the ./node_modules/protractor/selenium/ folder I ran ln -s selenium-server-standalone-2.48.2.jar latest.jar

You can use Gulp which is far simpler.
After installing gulp in Jenkins System , you may install the npm dependencies(npm install) & run gulp tasks directly as windows batch command in Jenkins as below:
In the background to make selenium server up and running and providing various other parameters , you may use packages like 'gulp-angular-protractor' in the gulpfile.js as below:
gulpfile.js
'use strict';
var gulp = require('gulp'),
gulpProtractorAngular = require('gulp-angular-protractor'),
gulpStart = gulp.Gulp.prototype.start,
currentStartTaskName;
gulp.Gulp.prototype.start = function (task) {
currentStartTaskName = task;
gulpStart.apply(this, arguments);
};
function executeWebTests(suiteName, appName) {
return gulp.src([])
.pipe(gulpProtractorAngular({
'configFile': './conf.js',
'debug': false,
'autoStartStopServer': true,
args: [
'--suite', suiteName,
'--capabilities.browserName', 'chrome',
'--params.APPNAME', appName,
'--params.SUITENAME', currentStartTaskName,
'--capabilities.platformName', 'Windows'],
keepAlive: false
}))
.on('error', function (e) {
console.log('Ended with below ERROR::',e);
process.exit(1);
})
.on('end', function () {
console.log('Test complete');
process.exit();
});
}
gulp.task('RegressionSuiteTask', function () {
executeWebTests('regressionTests,','Application_Name');
});
conf.js
suites: {
regressionTests: ['testCases/**/*.js']//will run all specs in subfolders
},

I know this already resolved and want to target for beginner to create Jenkins job and running test. I suggest to use selenium-server-standalone jar in configuration file and call configuration file from Jenkins.
conf.js
..
exports.config = {
//seleniumAddress: 'http://localhost:4444/wd/hub',
seleniumServerJar: 'node_modules/protractor/node_modules/webdriver-manager/selenium/selenium-server-standalone-3.5.3.jar',
....
//html reporter logic
.....
Creating Jenkins Job
Install node js on Jenkins Server
Install Html Publisher Plugin for end to end testing report
Create Freestyle Project or whatever your needs
Go to Build Section -> Add build step and choose Execute Windows
batch command if Jenkins server in Windows otherwise choose Execute
Shell for Linux
Call conf.js (install packages and call your configuration file)
For reporting Got to Post-Build Actions Section -> Add Publish Html
Reports and call your report file (file assuming from root of your
project)
However you can customize execution command using gulp or similar other packages. Thanks

Related

How do I run my selenium-side-runner to execute my test against Firefox?

I just installed selenium-side-runner on Mac Mojave and am trying to run a test from the command line using a test I recorded in the IDE. My test file name is "myTest.side". I created a "myTest.side.yml" file to tell selenium-side-runner where my drivers are ...
capabilities:
chromeOptions:
binary: '/Users/davea/Documents/workspace/starter_project/selenium/chromedriver_mac'
firefoxOptions:
binary: '/Users/davea/Documents/workspace/starter_project/selenium/geckodriver_mac'
However, when I try and run my tests, I'm getting this error ...
localhost:selenium davea$ selenium-side-runner -c "browserName=firefox" myTest.side
info: Running myTest.side
FAIL ./DefaultSuite.test.js
● Test suite failed to run
The geckodriver executable could not be found on the current PATH. Please download the latest version from https://github.com/mozilla/geckodriver/releases/ and ensure it can be found on your PATH.
at findGeckoDriver (../../../../../../../usr/local/lib/node_modules/selenium-side-runner/node_modules/selenium-webdriver/firefox.js:444:11)
at new ServiceBuilder (../../../../../../../usr/local/lib/node_modules/selenium-side-runner/node_modules/selenium-webdriver/firefox.js:533:22)
at Function.createSession (../../../../../../../usr/local/lib/node_modules/selenium-side-runner/node_modules/selenium-webdriver/firefox.js:591:21)
at createDriver (../../../../../../../usr/local/lib/node_modules/selenium-side-runner/node_modules/selenium-webdriver/index.js:155:33)
at Builder.build (../../../../../../../usr/local/lib/node_modules/selenium-side-runner/node_modules/selenium-webdriver/index.js:670:16)
at buildDriver (../../../../../../../usr/local/lib/node_modules/selenium-side-runner/node_modules/jest-environment-selenium/dist/index.js:66:17)
at WebdriverEnvironment.setup (../../../../../../../usr/local/lib/node_modules/selenium-side-runner/node_modules/jest-environment-selenium/dist/index.js:37:32)
Test Suites: 1 failed, 1 total
How do I run my test from the command line using Firefox?
As commented earlier, the reason your code doesn't work is the file naming convention.
By default the selenium-side-runner will pick the file .side.yml and not <somename>.side.yml
So if you just rename the file, it should pickup the correct details for you
Update: 16th July
After lots of hours of debugging, it seems what you are experiencing is a bug. So what happens is quite visible in the error
at new ServiceBuilder (selenium-webdriver/chrome.js:232:13)
at getDefaultService (selenium-webdriver/chrome.js:321:22)
at Function.createSession (selenium-webdriver/chrome.js:694:44)
at createDriver (selenium-webdriver/index.js:155:33)
at Builder.build (selenium-webdriver/index.js:662:16)
at buildDriver (jest-environment-selenium/dist/index.js:73:17)
at WebdriverEnvironment.setup (jest-environment-selenium/dist/index.js:39:32)
selenium-side-runner use jest-environment-selenium package and calls the setup method with below code
async setup() {
await super.setup();
this.global.driver = await buildDriver(this.configuration);
}
Now this configuration is being passed using jest and is there in the package.json of the test files generated on the fly
As you can see the configuration is passed. Now if we look at the jest-environment-selenium and the buildDriver function
async function buildDriver(configuration) {
const driver = new _seleniumWebdriver2.default.Builder().withCapabilities(configuration.capabilities);
if (configuration.server) driver.usingServer(configuration.server);
if (configuration.proxyType) {
let prxy;
if (configuration.proxyType === 'socks') {
prxy = _proxy2.default.socks(configuration.proxyOptions.socksProxy, configuration.proxyOptions.socksVersion);
} else {
prxy = _proxy2.default[configuration.proxyType](configuration.proxyOptions);
}
driver.setProxy(prxy);
}
return driver.build();
}
The driver does get initiated with withCapabilities(configuration.capabilities) and the capabilites do have the driver path also, but it seems webdriver will do nothing of these options. The initiator needs do all the work
If I update the function like below
async function buildDriver(configuration) {
const driver = new _seleniumWebdriver2.default.Builder().withCapabilities(configuration.capabilities);
if (configuration.server) driver.usingServer(configuration.server);
if (configuration.proxyType) {
let prxy;
if (configuration.proxyType === 'socks') {
prxy = _proxy2.default.socks(configuration.proxyOptions.socksProxy, configuration.proxyOptions.socksVersion);
} else {
prxy = _proxy2.default[configuration.proxyType](configuration.proxyOptions);
}
driver.setProxy(prxy);
}
if (configuration.capabilities && configuration.capabilities.chromeOptions) {
var options = new _chrome.Options()
var service = new _chrome.ServiceBuilder(configuration.capabilities.chromeOptions.binary || null)
driver.setChromeService(service)
}
return driver.build();
}
And now the test starts working. The repo for jest-environment-selenium is available on below
https://github.com/applitools/jest-environment-selenium
You can report and discuss the issue. In the meantime can workaround the issue by running the command like below
$ PATH=/Users/davea/Documents/workspace/starter_project/selenium/:$PATH selenium-side-runner -c "browserName=firefox" myTest.side
Create a .side.yml file in the directory you'll be running your tests from. The runner will pick it up automatically. Here is an example of the file's contents. As is from Selenium Command-Line Runner.
So please make sure to change the name of the file.
Or you can use --config-file without changing the name of your file. --config-file will ignore the .side.yml and picks up the configuration from the specified path.
selenium-side-runner --config-file "/path/to/your/config.yaml"
Credit Goes of Selenium IDE Documenation

Automatically run webdriver for e2e test in Gulp

There is the following protractor.conf.js:
exports.config = {
framework: 'jasmine',
specs: ['e2e-tests/**/*.js'],
seleniumAddress: 'http://127.0.0.1:4444/wd/hub',
seleniumServerJar: './node_modules/protractor/selenium/selenium-server-standalone-2.47.1.jar'
}
Gulp task:
gulp.task('e2e-testing', ['webdriver_standalone'], function() {
gulp.src([]).pipe(protractor({ configFile: "protractor.conf.js" }))
.on('error', function(e) { throw e })
});
This code works good, but I must execute webdriver-manager start --standalone before starting e2e task. How can I omit it? How can I do it automatically? Thanks in advance
Just remove seleniumAddress config option in order to make Protractor instantiate a new server by itself when you start a test suite. Otherwise, if server address is specified, Protractor tries to connect to it rather then create a new one. Take a look at the section Starting the Server from a Test Script in the docs:
Please note that if you set seleniumAddress, the settings for
seleniumServerJar, seleniumPort, seleniumArgs, sauceUser and sauceKey
will be ignored.
Yes, we need to add the below in config.js
seleniumServerJar: 'path of jar file',
seleniumPort: '4444',
and remove seleniumAddress from the config file.
It works absolutely fine

How to set protractor(v1.4.0) baseUrl using protractor API instead of configuration file?

i use protractor v1.4.0 and I want to set protractor baseUrl from command line so i can't use
baseUrl: 'http://localhost:8000/',
config option in protractor configuration file. I want to define default value for base url with "params" option in protractor configuration file as follows:
params: {
baseUrl: 'http://localhost:8080/'
},
and then overwrite the default value by passing a new value from command line when i run protractor as follows:
protractor 'path_to_my_conf_file' --params.baseUrl http://localhost:80/
then in my spec file i need to set base url using protractor API, but i can't find how to do that.
The 1-st answer to the following question is exactly what i need but it doesn't work.
How can I add URL's dynamically to Protractor tests?
As another option, could also try browser.baseUrl = "https://test-url.com" in onPrepare (works in Protractor 1.4.0)
You can just change it from the command line like so:
protractor --baseUrl http://whateveryouwant
Run tests via grunt with grunt-protractor-runner and grunt-option libraries:
protractor: {
options: {
configFile: "path_to_my_conf_file",
args: {
baseUrl: grunt.option('baseUrl', 'http://localhost:80/')
}
}
}
Then, run the task via:
grunt protractor --baseUrl=http://mynewurl
And, to let it use the default baseUrl, just run:
grunt protractor
Use gulp for your test run; shown below is the gulpfile.js
var gulp = require('gulp');
var runSequence = require('run-sequence');
var protractor = require('gulp-protractor').protractor;
gulp.task('protractor', function() {
var configFile = 'test/e2e/protractor-config.js';
return gulp
.src(['./test/e2e/spec/sample.js'])
.pipe(protractor({
configFile: configFile,
args: ['--baseUrl', 'http://www.google.com']
}))
.on('error', function(e) { throw e; });
});
gulp.task('test', function(callback) {
runSequence(
'protractor',
callback
);
});
Task run:
gulp test

protractor could not find protractor/selenium/chromedriver.exe at codeship

i'm trying to configure the integration to run portractor tests.
I'm using grunt-protractor-runner task
with following configuration:
protractor: {
options: {
configFile: "protractor.conf.js", //your protractor config file
keepAlive: true, // If false, the grunt process stops when the test fails.
noColor: false, // If true, protractor will not use colors in its output.
args: {
// Arguments passed to the command
}
},
run: {},
chrome: {
options: {
args: {
browser: "chrome"
}
}
}
}
and here is grunt task which i use for running the protractor after the server is running:
grunt.registerTask('prot', [
'connect:test',
'replace:includemocks',//for uncommenting angular-mocks reference
'protractor:run',
'replace:removemocks',//for commenting out angular-mocks reference
]);
It is running well on my local machine, but at codeship i'm getting following error:
Error: Could not find chromedriver at /home/rof/src/bitbucket.org/myrepo/myFirstRepo/node_modules/grunt-protractor-runner/node_modules/protractor/selenium/chromedriver.exe
Which i guess, a result of not having this "chromedriver.exe" at this path.
How can i solve it in codeship environment?
Thanks forwards
Add postinstall to your package.json file and that way npm install will take care of placing the binaries for you ahead of time:
"scripts": {
"postinstall": "echo -n $NODE_ENV | \
grep -v 'production' && \
./node_modules/protractor/bin/webdriver-manager update || \
echo 'will skip the webdriver install/update in production'",
...
},
And don't forget to set NODE_ENV ... not setting it at all will result in echo 'will skip the webdriver install/update in production' piece running. Setting it to dev or staging will get desired results.
Short answer (pulkitsinghal gave the original solution):
./node_modules/grunt-protractor-runner/node_modules/protractor/bin/webdriver-manager update
I'm one of the founders at Codeship.
The error seems to be because you are trying to use the exe file, but we're on Linux on our system. Did you hardcode that executable?
Could you send us an in-app support request so we have a link to look at and can help you fix this?

Running DOH on the command line with node.js

My first attempt to run tests using Dojo 1.8.3 on the command line with
node was thwarted by this error message:
../dojo/dojo.js:15
ode:function(){return _25;},guardCheckComplete:_37};};if(1){var _38=location.p
^
ReferenceError: location is not defined
The workaround is to use the uncompressed source instead of the release,
since the optimized version only seems to work in a browser. Next I tried a configuration script
// bootstrap.js
dojoConfig = {
baseUrl: ".",
packages:[{name: 'dojo', location: '../dojo_src'}],
deps: ['./ui_test.js']
};
require('../dojo_src/dojo.js');
And a simple test
// ui_test.js
dojo.require("doh.runner");
doh.register("test_1", [
function four_eq_4() {
var x = 4;
doh.is(x.toString(), "4");
}
]);
doh.run();
console.log("done.");
When I run the tests doh.run() does not seem to have an effect
$ node bootstrap.js
done.
My directory structure:
/app
bootstrap.js
ui_test.js
/util/doh
/dojo_src
What is the correct way to use DOH on the command line?
The answer is simple, but not obvious. Run with load=doh to invoke the test runner.
$ node bootstrap.js load=odh