nightwatchjs parallel mode selenium hub docker compose - javascript

I'm trying to run tests in parallel written using nightwatchjs in Docker using Selenium Hub. I'm able to get the tests to run in parallel in Docker without Selenium Hub, however, some child processes will timeout causing multiple retries. The results are very inconsistent. I'm hoping to use Selenium Hub or something similar to remove the timeouts and retries so the test results are more consistent, stable, and do not timeout.
However, now when I run docker-compose run --rm nightwatch, using the following code, the selenium server will start in parallel mode and multiple child processes will be started, however, only the first one will execute. Then the other child processes will get Error retrieving a new session from the selenium server. Connection refused! Is selenium server started? Am I missing something to get the nightwatchjs tests to run in parallel without timing out?
nightwatch.conf.js
module.exports = {
src_folders: ['tests'],
output_folder: 'reports',
custom_commands_path: '',
custom_assertions_path: '',
page_objects_path: 'page_objects',
test_workers: true,
live_output: true,
detailed_output: true,
selenium: {
start_process: true,
server_path: './bin/selenium-server-standalone-3.0.1.jar',
log_path: '',
host: '127.0.0.1',
port: 4444,
cli_args: {
'webdriver.chrome.driver' : './node_modules/chromedriver/bin/chromedriver'
}
},
test_settings: {
default: {
launch_url: 'https://example.com',
selenium_port: 4444,
selenium_host: 'hub',
silent: true,
screenshots: {
'enabled': false,
'path': ''
},
desiredCapabilities: {
browserName: 'chrome',
javascriptEnabled: true,
acceptSslCerts: true,
chromeOptions: {
args: [
'--window-size=1024,768',
'--no-sandbox'
]
}
},
globals: {
waitForConditionTimeout: 20000,
asyncHookTimeout: 70000
}
}
};
docker-compose.yml
version: '2'
services:
nightwatch:
build:
context: .
command: /bin/sh -c "node ./node_modules/nightwatch/bin/nightwatch"
links:
- chrome
- hub
volumes:
- .:/opt/nightwatch
chrome:
environment:
VIRTUAL_HOST: node.chrome.docker
HUB_PORT_4444_TCP_ADDR: hub
HUB_PORT_4444_TCP_PORT: 4444
image: selenium/node-chrome:3.1.0-astatine
links:
- hub
hub:
ports:
- 4444:4444
image: selenium/hub:3.1.0-astatine
Dockerfile
FROM java:8-jre
## Node.js setup
RUN curl -sL https://deb.nodesource.com/setup_6.x | bash -
RUN apt-get install -y nodejs
RUN npm config set spin false
WORKDIR /app
COPY . ./
RUN npm install

The docker node images are configured to run only one browser instance. You can change this by overriding environment variables, like so:
chrome:
environment:
VIRTUAL_HOST: node.chrome.docker
HUB_PORT_4444_TCP_ADDR: hub
HUB_PORT_4444_TCP_PORT: 4444
NODE_MAX_INSTANCES: 5
NODE_MAX_SESSION: 5
image: selenium/node-chrome:3.1.0-astatine
links:
- hub
In case you're interested, I discovered this by looking at the Dockerfile source.

Related

Copying .env files To Mutliple Host Machines w/ Pm2

I'm trying to deploy my Node.js script to multiple hosts using Pm2's deploy process.
It's working fine using a single host, with the following ecosystem.config.js file:
require("dotenv").config({ path: `./envs/.production.env` });
const path = require("path");
module.exports = {
apps: [
{
name: process.env.APP_NAME,
interpreter: process.env.NODE_PATH,
cwd: process.env.PROJECT_PATH
script: "dist/index.js",
instances: process.env.INSTANCES || 0,
exec_mode: "cluster",
env: {
...process.env,
},
},
],
deploy: {
production: {
user: "harrison",
host: process.env.HOST,
key: "~/.ssh/id_rsa",
ref: "origin/master",
repo: process.env.GIT_REPO,
path: process.env.PROJECT_PATH,
// Copy keys to server
"pre-deploy-local": `scp -Cr envs harrison#${process.env.HOST}:${process.env.PROJECT_PATH}/current`,
// Build app and restart PM2 processes
"post-deploy": `yarn install --ignore-engines && \
pwd && \
yarn prod:build && \
yarn prod:serve`,
},
},
};
In order to deploy it to multiple hosts, the PM2 documentation is quite simple: Just add multiple host names. Ok, easy enough. Within my .env file, I'm using a series of IP addresses separated by commas, then splitting those into an array inside my config file, like this:
host: process.env.HOST.split(",");
However, copying over my .env files to the multiple hosts is not quite so easy.
How can I configure the "pre-deploy-local" portion of this ecosystem file to scp my .env files to every host machine?
Ended up running a bash script. The list of HOSTS is in my .env.production file, separated by commas, like this
HOSTS=123.12.134.122,134.135.134.134
To pass them to the Pm2 host, replace each comma with a space and pass them into the bash script as arguments. Then, execute that bash script on the deploy.
My ecosystem file now looks like this:
// PM2 CONFIGURATION FOR PRODUCTION BUILDS
require("dotenv").config({ path: `./envs/.production.env` });
const path = require("path");
const hosts = process.env.HOSTS.replace(/,/g, " ");
module.exports = {
apps: [
{
name: process.env.APP_NAME,
args: ["--color"],
interpreter: process.env.NODE_PATH,
cwd: path.resolve(process.env.PROJECT_PATH, "current"), // Path holding the current version of our app (where post-deploy runs)
script: "dist/index.js", // Location of
instances: process.env.INSTANCES || 0,
exec_mode: "cluster",
env: {
...process.env,
},
},
],
deploy: {
production: {
user: "harrison",
host: process.env.HOSTS.split(","),
key: "~/.ssh/id_rsa2",
ref: "origin/master",
repo: process.env.GIT_REPO,
// Where to deploy on the server
path: process.env.PROJECT_PATH,
// Pass hosts as arguments to .env copy script
"pre-deploy-local": `./deployEnvs.sh ${
process.env.PROJECT_PATH
} ${hosts}`,
"post-deploy": `yarn install --ignore-engines && \
yarn prod:build && \
yarn prod:serve`,
},
},
};
And the bash script called deployEnvs.sh looks like this:
#!/bin/bash
PROJECT_PATH="${1}"
for HOST in "${#:2}"
do
scp -Cr envs "harrison#${HOST}:${PROJECT_PATH}/current"
done

Can I Make the `seleniumAddress` field in protractor.config.js take parameters?

I have a Windows box and an Ubuntu box which I run my automated tests on. Currently, in my protractor.config.js file I have two seleniumAddress fields under my multiCapabilities: [{}] section and just comment out one or the other depending on which environment I would like to run in.
Is there a way to parameterize the seleniumAddress: so I can tell from my command line which environment to run in?
Something like this: gulp e2e --suite <suiteName> --baseUrl <URL>
--environment Windows
Here is my current multiCapabilities section from my protractor conf file:
multiCapabilities: [{
browserName: 'chrome',
// seleniumAddress: "URL to webdriver-manager Windows Box",
seleniumAddress: "URL to webdriver-manager Ubuntu Box",
platform: 'ANY',
version: 'ANY',
chromeOptions: {
args: ['--no-sandbox', '--test-type=browser', '--lang=en', '--window-size=1680,1050'],
prefs: {
'credentials_enable_service': false,
'profile': {
'password_manager_enabled': false
},
download: {
prompt_for_download: false,
directory_upgrade: true,
default_directory: 'C:\\downloads\\'
},
},
}
// shardTestFiles: true,
// maxInstances: 2
}],
Protractor is run on Node.js, so you should be able to pass an argument (a little more complicated), or easier, set an environmental variable:
Protractor conf snippet from the Protractor website with environmental variable logic added:
// Use the Windows selenium if the environmental variable IS_WINDOWS is set.
const seleniumServer = process.env.IS_WINDOWS ?
'https://path/to/windows-silenium' : 'https://path-to-default-selenium';
exports.config = {
// The address of a running selenium server.
seleniumAddress: seleniumServer,
// Capabilities to be passed to the webdriver instance.
capabilities: {
'browserName': 'chrome'
},
// Spec patterns are relative to the configuration file location passed
// to protractor (in this example conf.js).
// They may include glob patterns.
specs: ['example-spec.js'],
// Options to be passed to Jasmine-node.
jasmineNodeOpts: {
showColors: true, // Use colors in the command line report.
}
};
I'm not quite sure what you would want to choose from (and I don't use gulp), but for the snippet above, you would probably use:
IS_WINDOWS=true gulp e2e --suite <suiteName> --baseUrl <URL>

Running protractor config results 'This webpage is not available'

I'm trying to test protractor on a vanilla.js app and when I run protractor basicConf.js
I am getting below error :
This webpage is not available ERR_CONNECTION_REFUSED
This is my test:
describe('foo', function() {
beforeEach(function() {
browser.get('index.html');
});
it('should return the same result as browser.findElement', function() {
$('#newItem').sendKeys('sdg');
element('#addBtn').click().then(function(){
});
});
})
And my protractor config:
// The main suite of Protractor tests.
exports.config = {
seleniumAddress: 'http://localhost:4444/wd/hub',
framework: 'jasmine2',
// Spec patterns are relative to this directory.
specs: [
'spec.js'
],
// Exclude patterns are relative to this directory.
exclude: [
'basic/exclude*.js'
],
capabilities: {'browserName': 'chrome'},
baseUrl: 'http://localhost:' + ( '8082'),
jasmineNodeOpts: {
isVerbose: true,
realtimeFailure: true
},
params: {
login: {
user: 'Jane',
password: '1234'
}
}
};
Any ideas what I need to do to start fixing this?
I have run both:
protactor npm install -g protractor
webdriver webdriver-manager update
Error connection gets refused if either the webdriver server isn't started or there is a configuration compatibility issue with your protractor and browser. Looking at your config file and config data, there is no such issue. However, you should start your webdriver before running your tests. Open a command prompt in windows or terminal in mac and then run the following command to start the selenium webdriver -
webdriver-manager start
Later run your protractor scripts with the command that you already have. Hope this helps.
Looking over your test I believe the issue originates from the address that you are passing to the browser.get() function. You'll want to either reference the baseUrl you setup in the config file and append the "index.html" piece in your test or adjust the baseUrl and reference that in your beforeEach function. Try one of the following:
...
baseUrl: 'http://localhost:8082',
...
browser.get(browser.baseUrl + '/index.html');
or
...
baseUrl: 'http://localhost:8082/',
...
browser.get(browser.baseUrl);
or
browser.get('http://localhost:8082/index.html');
Also you could try this:
...
baseUrl: 'http://localhost:8082/index.html');
...
browser.get(browser.baseUrl);

Intern - ReferenceError: document is not defined

Seeing this Error message when I'm trying to run Intern tests from within my test files dir. the (relevant) structure of the dir is:
test
resources
rest
pickup.js
cashManagement.js
gitignore
intern.js
packages.js
packages.sample.js
...
The inter.js contains references to testFile1.js and testFile2.js in the suites section. I played a bit with the way these 2 files are referenced and got a "Failed to load module..." error. So I guess now that's solved and the ReferenceError is the one I need to figure out. I did go over the existing threads and nothing seems to solve my issue. The full error message is pasted below. I'll gladly supply more relevant info if needed.
Thanks,
Eran
***ReferenceError: document is not defined**
at /Applications/dojo-release-1.10.2/dojo/has.js:31:33
at execModule (/Users/eranbrand/src/MobilePosSolution/ovc-build/ovc-repo/src/test/node_modules/intern/node_modules/dojo/dojo.js:515:54)
at /Users/eranbrand/src/MobilePosSolution/ovc-build/ovc-repo/src/test/node_modules/intern/node_modules/dojo/dojo.js:504:12
at Array.map (native)
at execModule (/Users/eranbrand/src/MobilePosSolution/ovc-build/ovc-repo/src/test/node_modules/intern/node_modules/dojo/dojo.js:499:17)
at /Users/eranbrand/src/MobilePosSolution/ovc-build/ovc-repo/src/test/node_modules/intern/node_modules/dojo/dojo.js:582:7
at guardCheckComplete (/Users/eranbrand/src/MobilePosSolution/ovc-build/ovc-repo/src/test/node_modules/intern/node_modules/dojo/dojo.js:566:4)
at checkComplete (/Users/eranbrand/src/MobilePosSolution/ovc-build/ovc-repo/src/test/node_modules/intern/node_modules/dojo/dojo.js:574:27)
at onLoadCallback (/Users/eranbrand/src/MobilePosSolution/ovc-build/ovc-repo/src/test/node_modules/intern/node_modules/dojo/dojo.js:656:7)
at /Users/eranbrand/src/MobilePosSolution/ovc-build/ovc-repo/src/test/node_modules/intern/node_modules/dojo/dojo.js:761:5*
Here's the content of the intern.js file:
// Learn more about configuring this file at <https://github.com/theintern/intern/wiki/Configuring-Intern>.
// These default settings work OK for most people. The options that *must* be changed below are the
// packages, suites, excludeInstrumentation, and (if you want functional tests) functionalSuites.
serviceURL = "http://ovc.local:8080/POSMClient/json/process/execute/";
define(['./packages'], function(Packages) {
var returnValue = {
// Configuration options for the module loader; any AMD configuration options supported by the specified AMD loader
// can be used here
loader: {
packages: Packages.packages
},
// The port on which the instrumenting proxy will listen
proxyPort: 9000,
// A fully qualified URL to the Intern proxy
proxyUrl: 'http://localhost:9000/',
// Default desired capabilities for all environments. Individual capabilities can be overridden by any of the
// specified browser environments in the `environments` array below as well. See
// https://code.google.com/p/selenium/wiki/DesiredCapabilities for standard Selenium capabilities and
// https://saucelabs.com/docs/additional-config#desired-capabilities for Sauce Labs capabilities.
// Note that the `build` capability will be filled in with the current commit ID from the Travis CI environment
// automatically
capabilities: {
'selenium-version': '2.39.0'
},
// Browsers to run integration testing against. Note that version numbers must be strings if used with Sauce
// OnDemand. Options that will be permutated are browserName, version, platform, and platformVersion; any other
// capabilities options specified for an environment will be copied as-is
environments: [/*
{ browserName: 'internet explorer', version: '11', platform: 'Windows 8.1' },
{ browserName: 'internet explorer', version: '10', platform: 'Windows 8' },
{ browserName: 'internet explorer', version: '9', platform: 'Windows 7' },
{ browserName: 'firefox', version: '27', platform: [ 'OS X 10.6', 'Windows 7', 'Linux' ] },
{ browserName: 'chrome', version: '32', platform: [ 'OS X 10.6', 'Windows 7', 'Linux' ] },
{ browserName: 'safari', version: '6', platform: 'OS X 10.8' },
{ browserName: 'safari', version: '7', platform: 'OS X 10.9' }*/
],
// Maximum number of simultaneous integration tests that should be executed on the remote WebDriver service
maxConcurrency: 3,
// Whether or not to start Sauce Connect before running tests
useSauceConnect: false,
// Connection information for the remote WebDriver service. If using Sauce Labs, keep your username and password
// in the SAUCE_USERNAME and SAUCE_ACCESS_KEY environment variables unless you are sure you will NEVER be
// publishing this configuration file somewhere
webdriver: {
host: 'localhost',
port: 4444
},
// The desired AMD loader to use when running unit tests (client.html/client.js). Omit to use the default Dojo
// loader
useLoader: {
'host-node': 'dojo/dojo',
'host-browser': 'node_modules/dojo/dojo.js'
},
// Non-functional test suite(s) to run in each browser
suites: [
"rest/pickup",
"rest/cashManagement"
],
// Functional test suite(s) to run in each browser once non-functional tests are completed
functionalSuites: [ /* 'myPackage/tests/functional' */ ],
// A regular expression matching URLs to files that should not be included in code coverage analysis
excludeInstrumentation: /^tests\//
}
return returnValue;
});
It looks like you're using the release build of Dojo, which assumes the document object will be available. To use that build you'll need to run intern with intern-runner or the browser client (client.html). If you'd prefer to run your tests with the node client (intern-client), you'll need to use the source distribution of Dojo or the dojo npm package.

Error using LiveReload on virtual machine with grunt

I am working with a virtualbox set up with vagrant/puphpet (ubuntu 12.04).
I set up grunt and contrib-watch successfully. I installed the chrome extension ... everything as specified here : https://github.com/gruntjs/grunt-contrib-watch#live-reloading
My Gruntfile is as follow :
module.exports = function(grunt)
{
require('load-grunt-tasks')(grunt);
grunt.initConfig({
compass: { // Task
dist: { // Target
options: { // Target options
sassDir: 'sass',
cssDir: 'css',
environment: 'development',
httpPath: '/',
imagesDir: 'img',
relativeAssets: true
}
}
},
watch: {
options: { livereload: true },
sass: {
files: ['sass/**/*.scss'],
tasks: ['compass'],
options: { spawn: false }
}
}
});
grunt.registerTask('default', ['compass']);
}
I run command "grunt watch" and it processes my sass right. But in Chrome's console I get the following error :
GET http://127.0.0.1:35729/livereload.js?ext=Chrome&extver=2.0.9
net::ERR_CONNECTION_REFUSED injected.js:116
If I add the script manualy in my view I still get the error :
GET http://localhost:35729/livereload.js net::ERR_CONNECTION_REFUSED
Any idea where this error could come from and why it's not loading the script ?
Your gruntfile looks alright.
It looks like your virtual machine refuses the connection. Make sure the live reload port is open in iptables.
In Ubuntu, that can be done simply with ufw:
sudo apt-get install ufw
sudo ufw enable
sudo ufw allow 35729/tcp

Categories

Resources