Jenkins job doesnt continue after starting selenium server - selenium

I am building a jenkins job that needs to run some tests against a selenium server. I have have defined a stage where I start the selenium server in 1 container, and after that I want to run my tests from another container, against the selenium server.
The selenium server seems to start fine, but after that the job just hangs, displaying a spinner:
This is what my pipeline script looks like:
agent {
kubernetes {
defaultContainer 'jnlp'
yaml """
apiVersion: v1
kind: Pod
spec:
containers:
- name: node
image: node:12.14.1
- name: selenium
image: vvoyer/selenium-standalone
"""
}
}
stages {
stage('Checkout codebase') {
// do checkout
}
stage('start selenium') {
steps {
container('selenium') {
sh '''
selenium-standalone install
selenium-standalone start //script hangs after this command
'''
}
}
}
stage('test') {
steps {
container('node') {
//build test project & run tests
}
}
}
}
}
Can anyone tell me what I am doing wrong here and how I can fix it?

Yeah Thanks, solved similar error by adding '&' at the end of shell script step inside Jenkinsfile.
ex:
sh label: '',script: 'docker-compose -f TestAutomation_UI_API/docker-compose-v3.yml up --scale chrome=3 &'

Related

How to configure Nomad job for Selenium Grid

I'm trying to setup a Selenium Grid in Hashicorp Nomad but I don't know how to make the networking work.
What I want is to have one selenium-hub and 8 chrome-nodes. I found that I can only have multiple allocations of the node-task if I put the node-task into its own group.
Running it locally, I would start the grid like this:
docker network create grid
docker run -d -p 4442-4444:4442-4444 --net grid --name selenium-hub selenium/hub:4
docker run -d --net grid -e SE_EVENT_BUS_HOST=selenium-hub -e SE_EVENT_BUS_PUBLISH_PORT=4442 -e SE_EVENT_BUS_SUBSCRIBE_PORT=4443 -v /dev/shm:/dev/shm selenium/node-chrome:4
docker run -d --net grid -e SE_EVENT_BUS_HOST=selenium-hub -e SE_EVENT_BUS_PUBLISH_PORT=4442 -e SE_EVENT_BUS_SUBSCRIBE_PORT=4443 -v /dev/shm:/dev/shm selenium/node-chrome:4
...
How do I need to configure Network for this to work?
My current job looks like this:
job "selenium" {
datacenters = ["dc1"]
type = "service"
group "selenium_hub" {
network {
}
task "selenium_hub" {
driver = "docker"
config {
image = "selenium/hub:4"
}
}
}
group "selenium_nodes" {
count = 8
network {
}
task "selenium_node" {
driver = "docker"
env {
SE_EVENT_BUS_HOST = "selenium-hub"
SE_EVENT_BUS_PUBLISH_PORT = "4442"
SE_EVENT_BUS_SUBSCRIBE_PORT = "4443"
}
config {
image = "selenium/node-chrome:4"
}
}
}
}
If anyone comes across this, I've got it working like this:
job "selenium" {
datacenters = ["dc1"]
type = "service"
group "selenium_hub" {
network {
mode = "host"
}
task "selenium_hub" {
driver = "docker"
config {
image = "selenium/hub:3.141.59-20201010"
network_mode = "host"
}
}
}
group "selenium_nodes" {
count = 8
network {
mode = "host"
port "http" {}
}
task "selenium_node" {
driver = "docker"
env {
HUB_HOST = "localhost"
SE_OPTS = "-port ${NOMAD_PORT_http}"
}
config {
network_mode = "host"
image = "selenium/node-chrome:3.141.59-20201010"
}
}
}
}
I used Selenium 3 instead of 4 because we also had other issues with 4.
Since I've used host network and all nodes use the port 5555 I needed to pass a dynamic port (http) to Selenium via SE_OPTS environment variable.

Jenkins Pipeline: get github commit message into vareable and keep it between agents

I have Jenkins Declared Pipeline with two separate Docker containers.
And i need to use github commit message and other git data at Post part.
Because of two different agents for two docker containers i have agent none at top of the pipeline.
I use some trick to get GitHub commit message. I don't know how to get it simple way.
environment {
COMMIT_TEXT = sh (
script: 'git log --format="full" -1 ${GIT_COMMIT}',
returnStdout: true
).trim()
TextComment = 'Text from Variable'
}
I can't use environment with sh inside a top level with agent none,
so i need to pass variables to Past part other way.
Any ideas?
Thanks.
pipeline {
agent none
/* --- i can not use "sh" there becouse in can not to be ececuted with 'agent none'
environment {
COMMIT_TEXT = sh (
script: 'git log --format="full" -1 ${GIT_COMMIT}',
returnStdout: true
).trim()
TextComment = 'Text from Variable'
}
*/
stages {
stage('build container up') {
agent {
docker {
image 'container:local'
}
/* --- there is no reason to put variable there, becouse it will be dead with the container before Post processing.
environment {
COMMIT_TEXT = sh (
script: 'git log --format="full" -1 ${GIT_COMMIT}',
returnStdout: true
).trim()
TextComment = 'Text from Variable'
}
*/
}
stages {
stage('Build') {
steps{
git branch: 'testing-jenkinsfile', url: 'https://github.com/...git'
}
}
}
}
stage('Build image') {
steps {
script {
docker.build("walletapi:local")
}
}
}
stage('Run service container'){
agent {label 'master'}
steps {
sh 'docker run -it -d --name container01 \
container01:local'
}
}
}
}
post {
always {
script {
sh 'env'
}
}
}

How to set correct Selenium host for nightwatch e2e test on gitlab?

I would like to add some e2e tests for my vue.js application and run them in the pipeline.
The corresponding part in my gitlab-ci.yml looks like this:
e2e:
image: node:8
before_script:
- npm install
services:
- name: selenium/standalone-chrome
alias: chrome
stage: testing
script:
- cd online-leasing-frontend
- npm install
- npm run test:e2e
And my nightwatch.js config:
{
"selenium": {
"start_process": false
},
"test_settings": {
"default": {
"selenium_port": 4444,
"selenium_host": "chrome"
}
}
}
Is “selenium_host”: “chrome” the correct way of setting the host to the selenium service?
I get the following error indicating that my e2e test can’t connect to the selenium service:
Connection refused! Is selenium server started?
Any tips?
The problem was that according to this issue, Gitlab CI is using the Kubernetes Executor instead of the Docker Executor which is mapping all Services to 127.0.0.1. After setting the selenium_host to this address, everything worked.
{
"selenium": {
"start_process": false
},
"test_settings": {
"default": {
"selenium_port": 4444,
"selenium_host": "127.0.0.1",
}
}
}
On the Selenium Repo it says:
"When executing docker run for an image with Chrome or Firefox please either mount -v /dev/shm:/dev/shm or use the flag --shm-size=2g to use the host's shared memory."
I don't know gitlab-ci so well, but I'm afraid it is not possible to add this as parameter to a service.

PhantomJS timeout issue when running in headless mode in GitLab CI

I am trying to use GitLab CI to run some client-side unit test written using QUnit. Now to run the Qunit test I am using the grunt-contrib-qunit plugin. To run these tests in headless mode I am using this plugin which hosts it on a localhost server in a console and runs all unit tests. When running this project locally I am successfully able to run all the unit tests but when I checking in my code which kicks of the CI process, on GitLab, it fails on starting the phantomjs server and gives timeout error. I am also providing the jsbin link of the two text files which are basically the output of the unit test from my console. One file is of my local system and another is from the GitLab CI that runs on GitLab website when I check-in my code.
Local Console Output File Dump
Gitlab CI Output Dump
Adding my gitlab-ci.yaml file
image: node:4.2.2
before_script:
- dir
- cd sapui5_repo
- dir
- cd app-with-tests
build:
stage: build
script:
- npm i
- npm run test
cache:
policy: push
paths:
- node_modules
artifacts:
paths:
- built
Also adding my gruntfile if that helps
/* global module */
module.exports = function (grunt) {
grunt.initConfig({
qunit: {
all: {
options: {
timeout: 9000,
urls: [
"http://localhost:9000/webcontent/test/unit/unitTests.qunit.html"
]
}
},
//all: ["webcontent/test/unit/unitTests.qunit.html"],
options: {
timeout: 2000,
}
},
connect: {
options: {
//open: true,
},
first: {
options: {
port: 9000,
//livereload: 3500,
base: "./"
}
},
second: {
options: {
open: {
target: "http://localhost:9000/webcontent"
},
keepalive: true,
port: 9000,
livereload: 3501,
base: "./",
}
}
},
});
grunt.loadNpmTasks("grunt-contrib-connect");
grunt.loadNpmTasks("grunt-contrib-qunit");
grunt.registerTask("test", [
"connect:first", "qunit"
]);
grunt.registerTask("default", [
"connect:second"
]);
};

Setting up Continuous Integration of Protractor using Jenkins

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