├── .gitignore ├── README.md ├── additional_info.md ├── blazedemo_app ├── Dockerfile ├── conftest.py ├── docker-entry.sh ├── helpers │ ├── __init__.py │ └── helpers.py ├── requirements.txt └── tests │ └── test_purchase_tickets.py ├── pipeline └── Jenkinsfile ├── scripts ├── generate_allure_report.bash └── run_tests.bash ├── selenium-automation-run └── Dockerfile ├── selenium-base-image ├── Dockerfile └── xvfb-chromium └── shark.png /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/.name 2 | .idea/misc.xml 3 | .idea/modules.xml 4 | .idea/workspace.xml 5 | 6 | *.pyc 7 | .idea/preferred-vcs.xml 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # selenium-docker-allure 2 | Running Selenium tests under py.test convention with docker support. 3 | 4 | ![Carpe Diem - Seize the day](shark.png?raw=true "Carpe Diem") 5 | 6 | ## Requirements 7 | 8 | - Docker 9 | 10 | ### Run tests and generate results 11 | ```bash 12 | # Run with py.test arguments (-v for verbose output) 13 | $ ./scripts/run_tests.bash --env=$ENV blazedemo_app/tests/test_purhcase_tickets.py -v 14 | ``` 15 | 16 | ### Run allure to generate allure report 17 | ```bash 18 | $ ./scripts/generate-allure-report.bash blazedemo_app 19 | ``` 20 | 21 | ### Open allure report 22 | ```bash 23 | $ cd ./blazedemo_app/allure-report/ 24 | $ python -m SimpleHTTPServer 8000 25 | $ open http://localhost:8000 26 | ``` 27 | 28 | ### Integrate tests inside Jenkins Pipeline 29 | ```bash 30 | 0. (Make sure your Jenkins Pipeline is supported by Docker and have Allure and Slack plugins installed) 31 | 1. Create Jenkins Pipeline job 32 | 2. Connect the job with pipeline/Jenkinsfile 33 | 3. Run the job 34 | ``` 35 | 36 | ## Motivation 37 | 38 | This project allows other developers to understand how to: 39 | 1. Create auto tests in python under py.test convention 40 | 2. Run tests with Docker 41 | 3. Export results into Allure report 42 | 4. Integrate tests inside Jenkins Pipeline 43 | 44 | ## Links 45 | 46 | [Additional info](./additional_info.md) 47 | 48 | ## Contributors 49 | 50 | Gilad Peleg 51 | Elad Kollender 52 | Eliran Shani 53 | 54 | ## License 55 | 56 | MIT 57 | -------------------------------------------------------------------------------- /additional_info.md: -------------------------------------------------------------------------------- 1 | ---------- 2 | 3 | 1. Selenium WebDriver 4 | ------------- 5 | 6 | WebDriver is an open source tool for automated testing of webapps across many browsers. It provides capabilities for navigating to web pages, user input, JavaScript execution, and more. If you wish to create automated tests and monitor the quality of your product, Selenium WebDriver is one of the top tools to achieve exactly that. 7 | 8 | > **Note**: read more about **Selenium WebDriver** [here](http://www.seleniumhq.org/docs/03_webdriver.jsp) 9 | 10 | 2. Python & WebDriver 11 | ------------- 12 | 13 | Selenium Python bindings provides a simple API to write functional/acceptance tests using Selenium WebDriver. Through Selenium Python API you can access all functionalities of Selenium WebDriver in an intuitive way. 14 | 15 | Selenium Python bindings provide a convenient API to access Selenium WebDrivers like Firefox, Ie, Chrome, Remote etc. The current supported Python versions are 2.7, 3.2 and above. 16 | 17 | > **Note**: read more about **Python & WebDriver** [here](http://selenium-python.readthedocs.io/api.html) 18 | 19 | 3. chromeDriver 20 | ------------- 21 | 22 | ChromeDriver is a standalone server which implements WebDriver's wire protocol for Chromium. ChromeDriver is available for Chrome on Android and Chrome on Desktop (Mac, Linux, Windows and ChromeOS). 23 | 24 | > **Note**: read more about **chromeDriver** [here](https://sites.google.com/a/chromium.org/chromedriver/) 25 | 26 | PyCharm 27 | ------------- 28 | 29 | PyCharm provides smart code completion, code inspections, on-the-fly error highlighting and quick-fixes, along with automated code refactorings and rich navigation capabilities. 30 | 31 | > **Note**: read more about **Python & WebDriver** [here](http://selenium-python.readthedocs.io/api.html) 32 | 33 | PyTest 34 | ------------- 35 | 36 | The pytest framework makes it easy to write small tests, yet scales to support complex functional testing for applications and libraries. 37 | 38 | > **Note**: read more about **Py.Test** [here](http://doc.pytest.org/en/latest/) 39 | 40 | Allure reports 41 | ------------- 42 | 43 | Allure - an open-source framework designed to create test execution reports with good representation of test execution output 44 | 45 | > **Note**: read more about **Allure reports** [here](http://allure.qatools.ru/) 46 | 47 | 48 | Virtual Environment 49 | ------------- 50 | 51 | A Virtual Environment is a tool to keep the dependencies required by different projects in separate places, by creating virtual Python environments for them. It solves the “Project X depends on version 1.x but, Project Y needs 4.x” dilemma, and keeps your global site-packages directory clean and manageable. 52 | 53 | > **Note**: read more about **Virtual Environment** [here](http://docs.python-guide.org/en/latest/dev/virtualenvs/) 54 | 55 | Requirements.txt 56 | ------------- 57 | 58 | requirements-txt - generate requirements.txt (python packages) 59 | 60 | > **Note**: read more about **Requirements.txt** [here](https://pypi.python.org/pypi/requirements-txt) 61 | 62 | 63 | Docker 64 | ------------- 65 | 66 | Docker is an open platform for developers and sysadmins to build, ship, and run distributed applications, whether on laptops, data center VMs, or the cloud. 67 | 68 | > **Note**: read more about **Docker** [here](https://www.docker.com/what-docker) 69 | 70 | 71 | Docker hub 72 | ------------- 73 | 74 | Dev-test pipeline automation, 100,000+ free apps, public and private registries. 75 | 76 | > **Note**: read more about **Docker** [here](https://hub.docker.com/) 77 | 78 | 79 | Jenkins 80 | ------------- 81 | 82 | Jenkins is an award-winning, cross-platform, continuous integration and continuous delivery application that increases your productivity. Use Jenkins to build and test your software projects continuously making it easier for developers to integrate changes to the project, and making it easier for users to obtain a fresh build. It also allows you to continuously deliver your software by providing powerful ways to define your build pipelines and integrating with a large number of testing and deployment technologies. 83 | 84 | > **Note**: read more about **Jenkins** [here](https://wiki.jenkins-ci.org/display/JENKINS/Meet+Jenkins) 85 | 86 | ---------- 87 | -------------------------------------------------------------------------------- /blazedemo_app/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM blazemeter/selenium-framework 2 | 3 | # create project folder with the name code 4 | RUN mkdir /code 5 | 6 | # project scope 7 | WORKDIR /code 8 | 9 | # install requirements 10 | COPY requirements.txt . 11 | RUN pip install -r requirements.txt 12 | 13 | # Set Dokcer entry 14 | RUN pwd 15 | COPY ./docker-entry.sh /code 16 | ENTRYPOINT ["/code/docker-entry.sh"] 17 | -------------------------------------------------------------------------------- /blazedemo_app/conftest.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | from selenium import webdriver 3 | import helpers.helpers as utils 4 | 5 | 6 | # Screenshot in case of any test failure 7 | def pytest_exception_interact(node, report): 8 | if node and report.failed: 9 | class_name = node._nodeid.replace(".py::", "_class_") 10 | name = "{0}_{1}".format(class_name, url) 11 | utils.save_screenshot(node.funcargs.get("driver"), name) 12 | 13 | 14 | # Create driver and url command line addoption 15 | def pytest_addoption(parser): 16 | parser.addoption("--driver", action="store", default="chrome", help="Type in browser type") 17 | parser.addoption("--url", action="store", default="http://blazedemo.com", help="url") 18 | 19 | 20 | # Create driver fixture that initiates chrome 21 | @pytest.fixture(scope="module", autouse=True) 22 | def driver(request): 23 | browser = request.config.getoption("--driver") 24 | if browser == 'chrome': 25 | browser = webdriver.Chrome() 26 | browser.get("about:blank") 27 | browser.implicitly_wait(10) 28 | return browser 29 | else: 30 | print 'only chrome is supported at the moment' 31 | 32 | 33 | # Create url fixture 34 | @pytest.fixture(scope="module") 35 | def url(request): 36 | return request.config.getoption("--url") 37 | -------------------------------------------------------------------------------- /blazedemo_app/docker-entry.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # run py.test ($@ to derive parameters from commandline) 4 | py.test --alluredir=allure-results $@ & 5 | pid="$!" 6 | 7 | # trap process id to stop script using Control+C 8 | trap "echo '=== Stopping PID $pid ==='; kill -SIGTERM $pid" SIGINT SIGTERM 9 | 10 | wait $pid -------------------------------------------------------------------------------- /blazedemo_app/helpers/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eliranshani/selenium-docker-allure/e44cd9177d5e20fbf82b4c5abb6e52ddc2d6c6d6/blazedemo_app/helpers/__init__.py -------------------------------------------------------------------------------- /blazedemo_app/helpers/helpers.py: -------------------------------------------------------------------------------- 1 | import allure 2 | import moment 3 | import os 4 | import string 5 | from selenium.webdriver.support.ui import WebDriverWait 6 | from selenium.webdriver.support import expected_conditions as EC 7 | from selenium.common.exceptions import TimeoutException 8 | from allure.constants import AttachmentType 9 | 10 | now = moment.now().strftime("%d-%m-%Y") 11 | path = os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(__file__)), os.pardir)) 12 | screen_dir = os.path.join(path, "screenshot", str(now)) 13 | 14 | 15 | def screen_path(): 16 | global screen_dir 17 | if not os.path.exists(screen_dir): 18 | os.makedirs(screen_dir) 19 | os.chmod(screen_dir, 0755) 20 | return screen_dir 21 | 22 | 23 | def remove_special_characters(text): 24 | return text.translate(string.maketrans('', ''), '\ / : * ? " < > |') 25 | 26 | 27 | def save_screenshot(driver, name): 28 | _name = remove_special_characters(name) 29 | driver.get_screenshot_as_file(os.path.join(screen_path(), _name + '-' + now + ".png")) 30 | allure.attach(_name + "-" + now, driver.get_screenshot_as_png(), type=AttachmentType.PNG) 31 | 32 | 33 | def find_element(driver, by_type, locator): 34 | delay = 3 # seconds 35 | try: 36 | return WebDriverWait(driver, delay).until(EC.presence_of_element_located((by_type, locator))) 37 | 38 | except TimeoutException: 39 | print "element {} was not found".format(locator) 40 | 41 | 42 | def click(driver, by_type, locator): 43 | el = find_element(driver, by_type, locator) 44 | el.click() 45 | 46 | 47 | def type_text(driver, text, by_type, locator): 48 | el = find_element(driver, by_type, locator) 49 | el.click() 50 | el.send_keys(text) 51 | 52 | 53 | def get_text(driver, by_type, locator): 54 | el = find_element(driver, by_type, locator) 55 | return el.text 56 | -------------------------------------------------------------------------------- /blazedemo_app/requirements.txt: -------------------------------------------------------------------------------- 1 | arrow==0.8.0 2 | colorama==0.3.7 3 | enum34==1.1.6 4 | lxml==3.6.0 5 | moment==0.5.1 6 | namedlist==1.7 7 | py==1.4.31 8 | pytest==3.5.0 9 | pytest-allure-adaptor==1.7.10 10 | pytest-gitignore==1.3 11 | python-dateutil==2.5.3 12 | pytz==2016.4 13 | selenium==2.53.5 14 | six==1.10.0 15 | times==0.7 16 | -------------------------------------------------------------------------------- /blazedemo_app/tests/test_purchase_tickets.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | import helpers.helpers as utils 3 | import pytest 4 | from selenium.webdriver.common.by import By 5 | 6 | 7 | def submit_form(driver): 8 | driver.find_element(By.XPATH, "//input[@type='submit']").click() 9 | 10 | 11 | def find_flight_in_dropdown(dropdown_element, expected_flight): 12 | for option in dropdown_element.find_elements_by_tag_name('option'): 13 | if option.text == expected_flight: 14 | option.click() 15 | 16 | 17 | def choose_departure_flight(driver, departure_flight): 18 | from_port_dropdown = utils.find_element(driver, By.NAME, "fromPort") 19 | find_flight_in_dropdown(dropdown_element=from_port_dropdown, expected_flight=departure_flight) 20 | 21 | 22 | def choose_arrival_flight(driver, arrival_flight): 23 | to_port_dropdown = utils.find_element(driver, By.NAME, "toPort") 24 | find_flight_in_dropdown(dropdown_element=to_port_dropdown, expected_flight=arrival_flight) 25 | 26 | 27 | @pytest.fixture(scope="function") 28 | def open_blazedemo(driver, url): 29 | driver.get(url) 30 | driver.find_element(By.TAG_NAME, "form") 31 | assert driver.title == "BlazeDemo" 32 | 33 | 34 | @pytest.mark.parametrize('from_port, to_port', [ 35 | ("Paris", "Buenos Aires"), 36 | ("Philadelphia", "Rome"), 37 | ("Boston", "London"), 38 | ("Portland", "Berlin"), 39 | ("San Diego", "New York"), 40 | ("Mexico City", "Dublin"), 41 | # fail on purpose to verify screenshot was added to allure report 42 | ("Tel Aviv", "Dubai") 43 | ]) 44 | def test_find_flights(driver, open_blazedemo, from_port, to_port): 45 | 46 | # Find flight 47 | choose_departure_flight(driver, departure_flight=from_port) 48 | choose_arrival_flight(driver, arrival_flight=to_port) 49 | submit_form(driver) 50 | 51 | assert from_port in utils.get_text(driver, By.TAG_NAME, "h3"), "{} was not found".format(from_port) 52 | assert to_port in utils.get_text(driver, By.TAG_NAME, "h3"), "{} was not found".format(to_port) 53 | assert "reserve.php" in driver.current_url 54 | 55 | # Choose flight 56 | submit_form(driver) 57 | 58 | assert from_port in utils.get_text(driver, By.TAG_NAME, "h2"), "{} was not found".format(from_port) 59 | assert to_port in utils.get_text(driver, By.TAG_NAME, "h2"), "{} was not found".format(to_port) 60 | assert "purchase.php" in driver.current_url 61 | 62 | # Purchase flight 63 | submit_form(driver) 64 | 65 | assert "Thank you for your purchase today!" in utils.get_text(driver, By.TAG_NAME, "h1") 66 | assert "confirmation.php" in driver.current_url 67 | 68 | 69 | def test_teardown(driver): 70 | driver.quit() 71 | -------------------------------------------------------------------------------- /pipeline/Jenkinsfile: -------------------------------------------------------------------------------- 1 | pipeline 2 | { 3 | parameters 4 | { 5 | // Define DRIVER parameter for running the test 6 | choice(name: 'DRIVER', description: 'Choose browser', choices: 'chrome\nfirefox\nheadless') 7 | 8 | // Define test path to run 9 | string(name: 'TESTS_TO_RUN', defaultValue: 'tests/test_purchase_tickets.py', description: 'choose test to run') 10 | } 11 | 12 | options 13 | { 14 | // keep last 100 builds 15 | buildDiscarder(logRotator(numToKeepStr: '100')) 16 | 17 | // add timestamp 18 | timestamps() 19 | } 20 | agent any // run the pipeline on any available node 21 | stages 22 | { 23 | stage('SCM: code update') 24 | { 25 | steps 26 | { 27 | // checking out repository 28 | checkout([ 29 | $class: 'GitSCM', branches: [[name: 'master']], 30 | userRemoteConfigs: [[url: 'https://github.com/eliranshani/selenium-docker-allure.git']] 31 | ]) 32 | 33 | // Create Allure report folders and grant relevant permissions 34 | sh "mkdir -p ./blazedemo_app/allure-results" 35 | sh "rm -rf ./blazedemo_app/allure-results/*" 36 | sh "chown jenkins:jenkins ./blazedemo_app/allure-results" 37 | } 38 | } 39 | stage('Docker build') 40 | { 41 | steps 42 | { 43 | script 44 | { 45 | // copying and building selenium base 46 | sh "cp selenium-base-image/Dockerfile ." 47 | docker.build("blazemeter/selenium_base") 48 | 49 | // copying and building selenium image 50 | sh "cp selenium-automation-run/Dockerfile ." 51 | docker.build("blazemeter/selenium_image") 52 | } 53 | } 54 | } 55 | stage('Run test') 56 | { 57 | steps 58 | { 59 | script 60 | { 61 | try 62 | { 63 | // creating timestamp 64 | def now = new Date() 65 | tstamp = now.format("yyyyMMdd-HH:mm:ss.SSSS", TimeZone.getTimeZone('UTC')) 66 | 67 | // running selenium tests using pytest via docker 68 | sh "docker run " + 69 | "--privileged " + // The --privileged flag gives all capabilities to the container, 70 | "--shm-size=1g " + // shared memory size is set to 1G to prevent chromedriver memory leak 71 | "--rm " + // remove container at the end of the session 72 | "-e PYTHONPATH=/code/ " + // environment variable support 73 | "-w=/code " + // setting working directory 74 | "-v `pwd`/blazedemo_app:/code " + // mount git repository to the container 75 | "blazemeter/selenium_image:latest " + // the specific image that being used (latest image by default) 76 | "-v" // verbose (for debugging purpose) 77 | } 78 | catch (error) 79 | { 80 | echo error.message 81 | } 82 | } 83 | } 84 | } 85 | } 86 | post 87 | { 88 | always 89 | { 90 | // Generate Allure Report 91 | generateAllureReport() 92 | 93 | // Send Slack notification 94 | sendSlackNotification() 95 | } 96 | } 97 | } 98 | 99 | // Generate Allure report function 100 | def generateAllureReport() 101 | { 102 | try 103 | { 104 | allure([ 105 | commandline : '2.5.0', 106 | includeProperties: false, 107 | jdk : '', 108 | properties : [[key: 'allure.tests.management.pattern', value: 'http://tms.company.com/%s']], 109 | reportBuildPolicy: 'ALWAYS', 110 | results : [[path: 'blazedemo_app/allure-results']] 111 | ]) 112 | } 113 | catch (error) 114 | { 115 | error.message 116 | } 117 | } 118 | 119 | // Send Slack notification function 120 | def sendSlackNotification() 121 | { 122 | // build status of null means successful 123 | buildStatus = currentBuild.result 124 | 125 | // Default values 126 | def subject = "${buildStatus}: Job '${env.JOB_NAME} [${env.BUILD_NUMBER}]'" 127 | def summary = "${subject} (${env.BUILD_URL})" 128 | 129 | // Set notification color based on build status 130 | if (buildStatus == 'STARTED') { 131 | color = 'YELLOW' 132 | colorCode = '#FFFF00' 133 | 134 | } else if (buildStatus == 'SUCCESS') { 135 | color = 'GREEN' 136 | colorCode = '#00FF00' 137 | 138 | } else { 139 | color = 'RED' 140 | colorCode = '#FF0000' 141 | } 142 | 143 | // Set slack channel 144 | channel = "jenkins_notifications" 145 | 146 | // Send notifications 147 | slackSend (color: colorCode, message: summary, channel: "#${channel}" ) 148 | } -------------------------------------------------------------------------------- /scripts/generate_allure_report.bash: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # pull allure report image from docker hub 4 | ALLURE_IMAGE=beeete2/docker-allure2 5 | 6 | # create relevant folder structure for allure report 7 | ALLURE_CONFIG_DIR=allure-config 8 | ALLURE_REPORT_DIR=allure-report 9 | ALLURE_RESULTS_DIR=allure-results 10 | PROJECT_DIR=${1:-blazedemo_app} 11 | 12 | # Delete any previous allure reports 13 | rm -rf $PROJECT_DIR/$ALLURE_REPORT_DIR 14 | 15 | # run allure image to generate allure report based on latest test results 16 | docker run --rm \ 17 | -v $(pwd)/$PROJECT_DIR/$ALLURE_REPORT_DIR:/$ALLURE_REPORT_DIR \ 18 | -v $(pwd)/$PROJECT_DIR/$ALLURE_RESULTS_DIR:/$ALLURE_RESULTS_DIR \ 19 | -v $(pwd)/$PROJECT_DIR/$ALLURE_CONFIG_DIR:/$ALLURE_CONFIG_DIR \ 20 | $ALLURE_IMAGE allure generate /$ALLURE_RESULTS_DIR -o /$ALLURE_REPORT_DIR -------------------------------------------------------------------------------- /scripts/run_tests.bash: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Declaring pytest arguments 4 | export PYTEST_ARGUMENTS=${@:-tests/test_purchase_tickets.py} 5 | 6 | # Set tag names to folders 7 | export AUTOMATION_IMAGE=blazemeter/selenium-framework 8 | export PROJECT_IMAGE=blazemeter/blazedemo-app-selenium 9 | 10 | export ALLURE_RESULTS_DIR=allure-results 11 | export PROJECT_DIR=blazedemo_app 12 | 13 | # Create tags for selenium-base-image and the project folder 14 | docker build selenium-base-image -t ${AUTOMATION_IMAGE} 15 | docker build ${PROJECT_DIR} -t ${PROJECT_IMAGE} 16 | 17 | 18 | # Run Selenium py.test with script arguments 19 | # Map allure output xml to image folder 20 | # Map root folder to image folder 21 | # Set the working directory as the root folder in the image 22 | # Set the PYTHONPATH to the root folder in the image 23 | # Run the project image as declared above 24 | docker run --rm --privileged \ 25 | -v $(pwd)/$PROJECT_DIR/$ALLURE_RESULTS_DIR:/code/$ALLURE_RESULTS_DIR \ 26 | -v $(pwd)/blazedemo_app/:/code/ \ 27 | -w=/code \ 28 | -e PYTHONPATH=/code/ \ 29 | ${PROJECT_IMAGE} \ 30 | "$PYTEST_ARGUMENTS" 31 | 32 | # to cleanup python compiled files 33 | find . -name "*.pyc" -exec rm -rf {} \; -------------------------------------------------------------------------------- /selenium-automation-run/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM blazemeter/selenium_base:latest 2 | 3 | # pip 4 | COPY blazedemo_app/requirements.txt /tmp/requirements.txt 5 | RUN pip install -r /tmp/requirements.txt 6 | RUN easy_install -U setuptools 7 | RUN pip install pytest-dependency 8 | 9 | # Dokcer entry 10 | COPY blazedemo_app/docker-entry.sh . 11 | ENTRYPOINT ["/docker-entry.sh"] 12 | 13 | CMD ["/bin/true"] 14 | -------------------------------------------------------------------------------- /selenium-base-image/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:2.7-stretch 2 | 3 | RUN apt-get update && apt-get install -yq \ 4 | firefox-esr=52.6.0esr-1~deb9u1 \ 5 | chromium=62.0.3202.89-1~deb9u1 \ 6 | git-core=1:2.11.0-3+deb9u2 \ 7 | xvfb=2:1.19.2-1+deb9u2 \ 8 | xsel=1.2.0-2+b1 \ 9 | unzip=6.0-21 \ 10 | python-pytest=3.0.6-1 \ 11 | libgconf2-4=3.2.6-4+b1 \ 12 | libncurses5=6.0+20161126-1+deb9u2 \ 13 | libxml2-dev=2.9.4+dfsg1-2.2+deb9u2 \ 14 | libxslt-dev \ 15 | libz-dev \ 16 | xclip=0.12+svn84-4+b1 17 | 18 | # GeckoDriver v0.19.1 19 | RUN wget -q "https://github.com/mozilla/geckodriver/releases/download/v0.19.1/geckodriver-v0.19.1-linux64.tar.gz" -O /tmp/geckodriver.tgz \ 20 | && tar zxf /tmp/geckodriver.tgz -C /usr/bin/ \ 21 | && rm /tmp/geckodriver.tgz 22 | 23 | # chromeDriver v2.35 24 | RUN wget -q "https://chromedriver.storage.googleapis.com/2.35/chromedriver_linux64.zip" -O /tmp/chromedriver.zip \ 25 | && unzip /tmp/chromedriver.zip -d /usr/bin/ \ 26 | && rm /tmp/chromedriver.zip 27 | 28 | # xvfb - X server display 29 | ADD selenium-base-image/xvfb-chromium /usr/bin/xvfb-chromium 30 | RUN ln -s /usr/bin/xvfb-chromium /usr/bin/google-chrome \ 31 | && chmod 777 /usr/bin/xvfb-chromium 32 | 33 | # create symlinks to chromedriver and geckodriver (to the PATH) 34 | RUN ln -s /usr/bin/geckodriver /usr/bin/chromium-browser \ 35 | && chmod 777 /usr/bin/geckodriver \ 36 | && chmod 777 /usr/bin/chromium-browser 37 | -------------------------------------------------------------------------------- /selenium-base-image/xvfb-chromium: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | _kill_procs() { 4 | kill -TERM $chromium 5 | wait $chromium 6 | kill -TERM $xvfb 7 | } 8 | 9 | # Setup a trap to catch SIGTERM and relay it to child processes 10 | trap _kill_procs SIGTERM 11 | 12 | XVFB_WHD=${XVFB_WHD:-1280x720x16} 13 | 14 | # Start Xvfb 15 | Xvfb :99 -ac -screen 0 $XVFB_WHD -nolisten tcp & 16 | xvfb=$! 17 | 18 | export DISPLAY=:99 19 | 20 | chromium --no-sandbox $@ & 21 | chromium=$! 22 | 23 | wait $chromium 24 | wait $xvfb -------------------------------------------------------------------------------- /shark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eliranshani/selenium-docker-allure/e44cd9177d5e20fbf82b4c5abb6e52ddc2d6c6d6/shark.png --------------------------------------------------------------------------------