Due to my circumstances for the current project I need to use 2 docker images together for selenium testing.
One is called Zalenium. I have it up and working via the docker-compose demo. Its basically like the selenium docker repo except that this can record video and show you live progress.
zalenium:
image: "dosel/zalenium"
container_name: zalenium
hostname: zalenium
tty: true
volumes:
- /Users/josephastrahan/seluser/videos:/home/seluser/videos
- /var/run/docker.sock:/var/run/docker.sock
- /usr/bin/docker:/usr/bin/docker
ports:
- 4444:4444
command: >
start --chromeContainers 1
--firefoxContainers 1
--maxDockerSeleniumContainers 8
--screenWidth 800 --screenHeight 600
--timeZone "Europe/Berlin"
--videoRecordingEnabled true
--sauceLabsEnabled false
--browserStackEnabled false
--testingBotEnabled false
--startTunnel false
environment:
- HOST_UID
- HOST_GID
- SAUCE_USERNAME
- SAUCE_ACCESS_KEY
- BROWSER_STACK_USER
- BROWSER_STACK_KEY
- TESTINGBOT_KEY
- TESTINGBOT_SECRET
The other image is a NodeJS server pre-installed with Mocha and the nodejs (npm package) of selenium-webdriver so that I can run the commands to trigger browser automation. Details on this here (https://github.com/SeleniumHQ/selenium/tree/master/javascript/node/selenium-webdriver) and here (https://hub.docker.com/r/qmu1/selenium-webdriver-node/)
You can see Zalenium running from docker compose just fine here. I can see the time updating every second correctly so its definitely showing a live view.
According to the documentation for the other docker container I'm using which is here (https://hub.docker.com/r/qmu1/selenium-webdriver-node/), I should be able to run tests simply with a docker command like this.
HERE=$(pwd)
echo ""
echo "----------------------------"
echo "Running an example"
echo "----------------------------"
echo ""
docker run -it --rm \
-v $HERE:/workspace \
qmu1/selenium-webdriver-node:latest /bin/sh -c "
mocha sample.js --timeout=10000
"
I changed this command to fit my needs until it seemed liked it worked.
docker run -it --rm --net=distributiontech_default -v $HERE:/workspace qmu1/selenium-webdriver-node:latest /bin/sh -c "mocha tests/seleniumtest.js --timeout=10000"
I got the response:
all modules are ready!
0 passing (1ms)
Problem is... on Zalenium I didn't see anything happen on the viewer to verify it was even working?
My selenium script looks like below.
//Run using this project (https://github.com/qmu/dockerfiles/blob/master/src/selenium-webdriver-node/example/bin/run)
"use strict";
const webdriver = require('selenium-webdriver'),
By = webdriver.By,
until = webdriver.until,
test = require('selenium-webdriver/testing');
const expect = require('expect.js');
const assert = require('assert');
// var driver = new webdriver.Builder()
// .withCapabilities(webdriver.Capabilities.chrome())
// .usingServer('http://localhost:4444/wd/hub')
// .build();
var driver = new webdriver.Builder()
.forBrowser('firefox')
.usingServer('http://zalenium:4444/wd/hub')
.build();
driver.get('http://www.google.com');
driver.findElement(webdriver.By.name('q')).sendKeys('simple programmer');
driver.findElement(webdriver.By.name('btnG')).click();
//driver.quit();
console.log('all modules are ready!');
I tried without the --net command and with... and no luck. Just so you can see the network details and containers running. You can see that zalenium is added to the distributiontech_default network.
How do I connect the docker container running the selenium code to the docker hub running Zalenium?
I tried changing this to...
var driver = new webdriver.Builder()
.forBrowser('firefox')
.usingServer('http://localhost:4444/wd/hub')
.build();
but no luck either. I can put any fake address I want where it says localhost and it doesn't seem to throw any errors or anything either oddly enough.
Well I have no idea what I did exactly, but one of these steps got it to work all the sudden. I think it was the way I was writing the script.
First to do the mocha test with the docker container here is the command I used.
docker run -it --rm --net=distributiontech_main -v $HERE:/workspace qmu1/selenium-webdriver-node:latest /bin/sh -c "mocha tests/seleniumtest.js --timeout=10000"
Note that you will want to be on the correct --net (network) and volume the correct location and use correct .js filepath for yourself.
My composer file I was using I added to the very bottom
networks:
main:
Then for each service I put...
networks:
- main
The network name will default to the name your project is in with an _ and the name you define in the composer file. Use the command docker network ls
to view your current networks. You can clear old unused ones with docker network rm networknamehere
, just don't remove bridge, host or none as they are defaults.
This step to put on the networks might not be necessary since one is created for you by default from docker compose. You can see it by using the docker network ls
command.
An Example selenium file that worked for me was this...
"use strict";
var webdriver = require('selenium-webdriver'),
{ describe, it, after, before } = require('selenium-webdriver/testing'),
By = webdriver.By,
until = webdriver.until;
var driver;
describe('Login Test', function () {
this.timeout(50000);//50 seconds
beforeEach(function(){
driver = new webdriver.Builder()
.withCapabilities({'browserName': 'chrome','name':'Chrome Test','tz':'America/Los_Angeles','build':'Chrome Build','idleTimeout':'60'})
.usingServer('http://zalenium:4444/wd/hub')
.build();
driver.get('http://distribution.tech.sel');
});
afterEach(function(){
driver.quit();
});
//this.timeout(20000);
it('Should show welcome message after entering credentials', function () {
driver.findElement(By.name('_username')).sendKeys('**');
driver.findElement(By.name('_password')).sendKeys('**');
driver.findElement(By.css("button")).click();
});
it('The title should say something interesting', function () {
});
it('And this thing too...', function () {
});
});
Notice the key here is I refer to zalenium which is not on the same network, .usingServer('http://zalenium:4444/wd/hub')
, this resolves the ip address automatically and the script is able to find the zalenium server easily.
The other thing is since I have my website on another container I added this to make accessing it easier in the composer file.
networks:
main:
aliases:
- distribution.tech.sel
This replaces
networks:
-main
It creates an alias so you can use a domain name to refer to the project when accessing it. Technically in my composer file I called the service 'web' and I could access it that way, but my site uses the domain name information to decide if its in beta or dev mode so it was important to give a proper domain when connecting to it in my case.
Hope this helps someone.
Example entire dockercompose.yml file
version: "3"
services:
dblive:
image: mysql:5.5.52
volumes:
- ./db_data_live:/var/lib/mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: **
MYSQL_DATABASE: **
MYSQL_USER: **
MYSQL_PASSWORD: **
networks:
- main
dbdev:
image: mysql:5.5.52
volumes:
- ./db_data_dev:/var/lib/mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: **
MYSQL_DATABASE: **
MYSQL_USER: **
MYSQL_PASSWORD: **
networks:
- main
phpmyadmin:
depends_on:
- dblive
- dbdev
image: phpmyadmin/phpmyadmin
environment:
PMA_ARBITRARY : 1
restart: always
ports:
- "8081:80"
networks:
- main
zalenium:
image: "dosel/zalenium"
container_name: zalenium
hostname: zalenium
tty: true
volumes:
- /Users/josephastrahan/seluser/videos:/home/seluser/videos
- /var/run/docker.sock:/var/run/docker.sock
- /usr/bin/docker:/usr/bin/docker
ports:
- 4444:4444
command: >
start --chromeContainers 2
--firefoxContainers 2
--maxDockerSeleniumContainers 8
--screenWidth 800 --screenHeight 600
--timeZone "America/Los_Angeles"
--videoRecordingEnabled true
--sauceLabsEnabled false
--browserStackEnabled false
--testingBotEnabled false
--startTunnel false
environment:
- HOST_UID
- HOST_GID
- SAUCE_USERNAME
- SAUCE_ACCESS_KEY
- BROWSER_STACK_USER
- BROWSER_STACK_KEY
- TESTINGBOT_KEY
- TESTINGBOT_SECRET
networks:
main:
aliases:
- zalenium.test
web:
#build: ./
depends_on:
- dblive
- dbdev
- zalenium
image: **
volumes:
- ./web:/var/www
- ./config/custom.php.ini:/etc/php5/apache2/conf.d/custom.php.ini
- ./logs/apache_error.log:/var/log/apache2/error.log
- ./logs/apache_access.log:/var/log/apache2/access.log
- ./config/apache_default.conf:/etc/apache2/sites-available/000-default.conf
- ./config/apache_default-ssl.conf:/etc/apache2/sites-available/default-ssl.conf
- ./config/ssl/apache.key:/etc/apache2/ssl/apache.key
- ./config/ssl/apache.crt:/etc/apache2/ssl/apache.crt
- ./web/public_html/livesite:/app
- ./web/public_html/devsite:/appdev
restart: always
ports:
#Standard HTTP Port
- "80:80"
#Below allows access to local computer from outside ports
- "8080:80"
#Standard SSH Port
- "443:443"
#Below allows access to local computer from outside ports for SSH Testing
- "4443:443"
extra_hosts:
- "distribution.tech:127.0.0.1"
- "dev.distribution.tech:127.0.0.1"
- "distribution.tech.local:127.0.0.1"
- "dev.distribution.tech.local:127.0.0.1"
networks:
main:
aliases:
- distribution.tech.sel
# external_links:
# - web:dev.distribution.tech
# - web:distribution.tech
networks:
main: