Search code examples
node.jsseleniumdockerdocker-networkzalenium

Run Selenium Commands For Zalenium from another Docker Container


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.

enter image description here

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.

enter image description here

enter image description here

enter image description here

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.


Solution

  • 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: