From 0fbbfe3c7af6fe89053d3a0c8c1b6314d498158c Mon Sep 17 00:00:00 2001 From: Paul Podgorsek Date: Wed, 7 Feb 2024 16:12:23 +0000 Subject: [PATCH 1/2] Issue #376 - Cannot install easily custom libraries --- .github/workflows/docker-build.yml | 167 +++++++++++++++++-------- Dockerfile | 7 ++ README.md | 23 ++++ bin/run-tests-in-virtual-screen.sh | 11 ++ test/pip-dependencies/main.robot | 20 +++ test/pip-dependencies/requirements.txt | 2 + 6 files changed, 175 insertions(+), 55 deletions(-) create mode 100644 test/pip-dependencies/main.robot create mode 100644 test/pip-dependencies/requirements.txt diff --git a/.github/workflows/docker-build.yml b/.github/workflows/docker-build.yml index 98a5584..807ff34 100644 --- a/.github/workflows/docker-build.yml +++ b/.github/workflows/docker-build.yml @@ -37,44 +37,124 @@ jobs: run: podman build . --tag $IMAGE_NAME --file Dockerfile - name: Basic Test - run: - podman run --shm-size=1g -v `pwd`/test:/opt/robotframework/tests:Z -e BROWSER=$BROWSER $IMAGE_NAME + run: | + podman run --shm-size=1g \ + -v `pwd`/test/browser-library.robot:/opt/robotframework/tests/browser-library.robot:Z \ + -v `pwd`/test/faker.robot:/opt/robotframework/tests/faker.robot:Z \ + -v `pwd`/test/requests.robot:/opt/robotframework/tests/requests.robot:Z \ + -v `pwd`/test/selenium.robot:/opt/robotframework/tests/selenium.robot:Z \ + -v `pwd`/test/timezones.robot:/opt/robotframework/tests/timezones.robot:Z \ + -e BROWSER=$BROWSER \ + $IMAGE_NAME + - name: Test dependency installation + run: | + podman run --shm-size=1g \ + -v `pwd`/test/pip-dependencies/main.robot:/opt/robotframework/tests/pip-dependencies.robot:Z \ + -v `pwd`/test/pip-dependencies/requirements.txt:/opt/robotframework/pip-requirements.txt:Z \ + -e BROWSER=$BROWSER \ + $IMAGE_NAME - name: Colour Depth 16 Test - run: - podman run --shm-size=1g -v `pwd`/test:/opt/robotframework/tests:Z -e BROWSER=$BROWSER -e SCREEN_COLOUR_DEPTH=16 $IMAGE_NAME + run: | + podman run --shm-size=1g \ + -v `pwd`/test/browser-library.robot:/opt/robotframework/tests/browser-library.robot:Z \ + -v `pwd`/test/selenium.robot:/opt/robotframework/tests/selenium.robot:Z \ + -e BROWSER=$BROWSER \ + -e SCREEN_COLOUR_DEPTH=16 \ + $IMAGE_NAME - name: Screen Width 800x600 Test - run: - podman run --shm-size=1g -v `pwd`/test:/opt/robotframework/tests:Z -e BROWSER=$BROWSER -e SCREEN_WIDTH=800 -e SCREEN_HEIGHT=600 $IMAGE_NAME + run: | + podman run --shm-size=1g \ + -v `pwd`/test/browser-library.robot:/opt/robotframework/tests/browser-library.robot:Z \ + -v `pwd`/test/selenium.robot:/opt/robotframework/tests/selenium.robot:Z \ + -e BROWSER=$BROWSER \ + -e SCREEN_WIDTH=800 \ + -e SCREEN_HEIGHT=600 \ + $IMAGE_NAME - name: Screen Width 1024x768 Test - run: - podman run --shm-size=1g -v `pwd`/test:/opt/robotframework/tests:Z -e BROWSER=$BROWSER -e SCREEN_WIDTH=1024 -e SCREEN_HEIGHT=768 $IMAGE_NAME + run: | + podman run --shm-size=1g \ + -v `pwd`/test/browser-library.robot:/opt/robotframework/tests/browser-library.robot:Z \ + -v `pwd`/test/selenium.robot:/opt/robotframework/tests/selenium.robot:Z \ + -e BROWSER=$BROWSER \ + -e SCREEN_WIDTH=1024 \ + -e SCREEN_HEIGHT=768 \ + $IMAGE_NAME - name: Screen Width 1280x1024 Test - run: - podman run --shm-size=1g -v `pwd`/test:/opt/robotframework/tests:Z -e BROWSER=$BROWSER -e SCREEN_WIDTH=1280 -e SCREEN_HEIGHT=1024 $IMAGE_NAME + run: | + podman run --shm-size=1g \ + -v `pwd`/test/browser-library.robot:/opt/robotframework/tests/browser-library.robot:Z \ + -v `pwd`/test/selenium.robot:/opt/robotframework/tests/selenium.robot:Z \ + -e BROWSER=$BROWSER \ + -e SCREEN_WIDTH=1280 \ + -e SCREEN_HEIGHT=1024 \ + $IMAGE_NAME - name: Screen Width 2560x1440 Test - run: - podman run --shm-size=1g -v `pwd`/test:/opt/robotframework/tests:Z -e BROWSER=$BROWSER -e SCREEN_WIDTH=2560 -e SCREEN_HEIGHT=1440 $IMAGE_NAME + run: | + podman run --shm-size=1g \ + -v `pwd`/test/browser-library.robot:/opt/robotframework/tests/browser-library.robot:Z \ + -v `pwd`/test/selenium.robot:/opt/robotframework/tests/selenium.robot:Z \ + -e BROWSER=$BROWSER \ + -e SCREEN_WIDTH=2560 \ + -e SCREEN_HEIGHT=1440 \ + $IMAGE_NAME - name: Screen Width 3840x2160 Test - run: - podman run --shm-size=1g -v `pwd`/test:/opt/robotframework/tests:Z -e BROWSER=$BROWSER -e SCREEN_WIDTH=3840 -e SCREEN_HEIGHT=2160 $IMAGE_NAME + run: | + podman run --shm-size=1g \ + -v `pwd`/test/browser-library.robot:/opt/robotframework/tests/browser-library.robot:Z \ + -v `pwd`/test/selenium.robot:/opt/robotframework/tests/selenium.robot:Z \ + -e BROWSER=$BROWSER \ + -e SCREEN_WIDTH=3840 \ + -e SCREEN_HEIGHT=2160 \ + $IMAGE_NAME - name: Debug Log Level Test run: - podman run --shm-size=1g -v `pwd`/test:/opt/robotframework/tests:Z -e BROWSER=$BROWSER -e ROBOT_OPTIONS="--loglevel DEBUG" $IMAGE_NAME + podman run --shm-size=1g \ + -v `pwd`/test/faker.robot:/opt/robotframework/tests/faker.robot:Z \ + -e BROWSER=$BROWSER \ + -e ROBOT_OPTIONS="--loglevel DEBUG" \ + $IMAGE_NAME - name: Basic Multithreaded Test - run: - podman run --shm-size=1g -v `pwd`/test:/opt/robotframework/tests:Z -e BROWSER=$BROWSER -e ROBOT_THREADS=4 $IMAGE_NAME + run: | + podman run --shm-size=1g \ + -v `pwd`/test/browser-library.robot:/opt/robotframework/tests/browser-library.robot:Z \ + -v `pwd`/test/faker.robot:/opt/robotframework/tests/faker.robot:Z \ + -v `pwd`/test/requests.robot:/opt/robotframework/tests/requests.robot:Z \ + -v `pwd`/test/selenium.robot:/opt/robotframework/tests/selenium.robot:Z \ + -v `pwd`/test/timezones.robot:/opt/robotframework/tests/timezones.robot:Z \ + -e BROWSER=$BROWSER \ + -e ROBOT_THREADS=4 \ + $IMAGE_NAME - name: Test Level Multithreaded Test - run: - podman run --shm-size=1g -v `pwd`/test:/opt/robotframework/tests:Z -e BROWSER=$BROWSER -e ROBOT_THREADS=4 -e PABOT_OPTIONS="--testlevelsplit" $IMAGE_NAME + run: | + podman run --shm-size=1g \ + -v `pwd`/test/browser-library.robot:/opt/robotframework/tests/browser-library.robot:Z \ + -v `pwd`/test/faker.robot:/opt/robotframework/tests/faker.robot:Z \ + -v `pwd`/test/requests.robot:/opt/robotframework/tests/requests.robot:Z \ + -v `pwd`/test/selenium.robot:/opt/robotframework/tests/selenium.robot:Z \ + -v `pwd`/test/timezones.robot:/opt/robotframework/tests/timezones.robot:Z \ + -e BROWSER=$BROWSER \ + -e ROBOT_THREADS=4 \ + -e PABOT_OPTIONS="--testlevelsplit" \ + $IMAGE_NAME - name: Custom User Test - run: - podman run --user=2000 --shm-size=1g -v `pwd`/test:/opt/robotframework/tests:Z -e BROWSER=$BROWSER $IMAGE_NAME + run: | + podman run --user=2000 --shm-size=1g \ + -v `pwd`/test/faker.robot:/opt/robotframework/tests/faker.robot:Z \ + -e BROWSER=$BROWSER \ + $IMAGE_NAME - name: Custom User and Group Test - run: - podman run --user=2000:2000 --shm-size=1g -v `pwd`/test:/opt/robotframework/tests:Z -e BROWSER=$BROWSER $IMAGE_NAME + run: | + podman run --user=2000:2000 --shm-size=1g \ + -v `pwd`/test/faker.robot:/opt/robotframework/tests/faker.robot:Z \ + -e BROWSER=$BROWSER \ + $IMAGE_NAME - name: Datetime - run: - podman run --user=2000:2000 --shm-size=1g -v `pwd`/test:/opt/robotframework/tests:Z -e BROWSER=$BROWSER -e TZ="America/New_York" $IMAGE_NAME + run: | + podman run --user=2000:2000 --shm-size=1g \ + -v `pwd`/test/timezones.robot:/opt/robotframework/tests/timezones.robot:Z \ + -e BROWSER=$BROWSER \ + -e TZ="America/New_York" \ + $IMAGE_NAME # Build and run tests for Microsoft Edge. # This must be processed separately from Firefox and Chrome, due to the Browser library not handling Microsoft Edge by default @@ -98,23 +178,24 @@ jobs: -v `pwd`/test/timezones.robot:/opt/robotframework/tests/timezones.robot:Z \ -e BROWSER=$BROWSER \ $IMAGE_NAME + - name: Test dependency installation + run: | + podman run --shm-size=1g \ + -v `pwd`/test/pip-dependencies/main.robot:/opt/robotframework/tests/pip-dependencies.robot:Z \ + -v `pwd`/test/pip-dependencies/requirements.txt:/opt/robotframework/pip-requirements.txt:Z \ + -e BROWSER=$BROWSER \ + $IMAGE_NAME - name: Colour Depth 16 Test run: | podman run --shm-size=1g \ - -v `pwd`/test/faker.robot:/opt/robotframework/tests/faker.robot:Z \ - -v `pwd`/test/requests.robot:/opt/robotframework/tests/requests.robot:Z \ -v `pwd`/test/selenium.robot:/opt/robotframework/tests/selenium.robot:Z \ - -v `pwd`/test/timezones.robot:/opt/robotframework/tests/timezones.robot:Z \ -e BROWSER=$BROWSER \ -e SCREEN_COLOUR_DEPTH=16 \ $IMAGE_NAME - name: Screen Width 800x600 Test run: | podman run --shm-size=1g \ - -v `pwd`/test/faker.robot:/opt/robotframework/tests/faker.robot:Z \ - -v `pwd`/test/requests.robot:/opt/robotframework/tests/requests.robot:Z \ -v `pwd`/test/selenium.robot:/opt/robotframework/tests/selenium.robot:Z \ - -v `pwd`/test/timezones.robot:/opt/robotframework/tests/timezones.robot:Z \ -e BROWSER=$BROWSER \ -e SCREEN_WIDTH=800 \ -e SCREEN_HEIGHT=600 \ @@ -122,10 +203,7 @@ jobs: - name: Screen Width 1024x768 Test run: | podman run --shm-size=1g \ - -v `pwd`/test/faker.robot:/opt/robotframework/tests/faker.robot:Z \ - -v `pwd`/test/requests.robot:/opt/robotframework/tests/requests.robot:Z \ -v `pwd`/test/selenium.robot:/opt/robotframework/tests/selenium.robot:Z \ - -v `pwd`/test/timezones.robot:/opt/robotframework/tests/timezones.robot:Z \ -e BROWSER=$BROWSER \ -e SCREEN_WIDTH=1024 \ -e SCREEN_HEIGHT=768 \ @@ -133,10 +211,7 @@ jobs: - name: Screen Width 1280x1024 Test run: | podman run --shm-size=1g \ - -v `pwd`/test/faker.robot:/opt/robotframework/tests/faker.robot:Z \ - -v `pwd`/test/requests.robot:/opt/robotframework/tests/requests.robot:Z \ -v `pwd`/test/selenium.robot:/opt/robotframework/tests/selenium.robot:Z \ - -v `pwd`/test/timezones.robot:/opt/robotframework/tests/timezones.robot:Z \ -e BROWSER=$BROWSER \ -e SCREEN_WIDTH=1280 \ -e SCREEN_HEIGHT=1024 \ @@ -144,10 +219,7 @@ jobs: - name: Screen Width 2560x1440 Test run: | podman run --shm-size=1g \ - -v `pwd`/test/faker.robot:/opt/robotframework/tests/faker.robot:Z \ - -v `pwd`/test/requests.robot:/opt/robotframework/tests/requests.robot:Z \ -v `pwd`/test/selenium.robot:/opt/robotframework/tests/selenium.robot:Z \ - -v `pwd`/test/timezones.robot:/opt/robotframework/tests/timezones.robot:Z \ -e BROWSER=$BROWSER \ -e SCREEN_WIDTH=2560 \ -e SCREEN_HEIGHT=1440 \ @@ -155,10 +227,7 @@ jobs: - name: Screen Width 3840x2160 Test run: | podman run --shm-size=1g \ - -v `pwd`/test/faker.robot:/opt/robotframework/tests/faker.robot:Z \ - -v `pwd`/test/requests.robot:/opt/robotframework/tests/requests.robot:Z \ -v `pwd`/test/selenium.robot:/opt/robotframework/tests/selenium.robot:Z \ - -v `pwd`/test/timezones.robot:/opt/robotframework/tests/timezones.robot:Z \ -e BROWSER=$BROWSER \ -e SCREEN_WIDTH=3840 \ -e SCREEN_HEIGHT=2160 \ @@ -167,9 +236,6 @@ jobs: run: | podman run --shm-size=1g \ -v `pwd`/test/faker.robot:/opt/robotframework/tests/faker.robot:Z \ - -v `pwd`/test/requests.robot:/opt/robotframework/tests/requests.robot:Z \ - -v `pwd`/test/selenium.robot:/opt/robotframework/tests/selenium.robot:Z \ - -v `pwd`/test/timezones.robot:/opt/robotframework/tests/timezones.robot:Z \ -e BROWSER=$BROWSER \ -e ROBOT_OPTIONS="--loglevel DEBUG" \ $IMAGE_NAME @@ -198,26 +264,17 @@ jobs: run: | podman run --user=2000 --shm-size=1g \ -v `pwd`/test/faker.robot:/opt/robotframework/tests/faker.robot:Z \ - -v `pwd`/test/requests.robot:/opt/robotframework/tests/requests.robot:Z \ - -v `pwd`/test/selenium.robot:/opt/robotframework/tests/selenium.robot:Z \ - -v `pwd`/test/timezones.robot:/opt/robotframework/tests/timezones.robot:Z \ -e BROWSER=$BROWSER \ $IMAGE_NAME - name: Custom User and Group Test run: | podman run --user=2000:2000 --shm-size=1g \ -v `pwd`/test/faker.robot:/opt/robotframework/tests/faker.robot:Z \ - -v `pwd`/test/requests.robot:/opt/robotframework/tests/requests.robot:Z \ - -v `pwd`/test/selenium.robot:/opt/robotframework/tests/selenium.robot:Z \ - -v `pwd`/test/timezones.robot:/opt/robotframework/tests/timezones.robot:Z \ -e BROWSER=$BROWSER \ $IMAGE_NAME - name: Datetime run: | podman run --user=2000:2000 --shm-size=1g \ - -v `pwd`/test/faker.robot:/opt/robotframework/tests/faker.robot:Z \ - -v `pwd`/test/requests.robot:/opt/robotframework/tests/requests.robot:Z \ - -v `pwd`/test/selenium.robot:/opt/robotframework/tests/selenium.robot:Z \ -v `pwd`/test/timezones.robot:/opt/robotframework/tests/timezones.robot:Z \ -e BROWSER=$BROWSER \ -e TZ="America/New_York" \ diff --git a/Dockerfile b/Dockerfile index 2f1b9ea..ab6b556 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,6 +3,9 @@ FROM fedora:39 MAINTAINER Paul Podgorsek LABEL description Robot Framework in Docker. +# Set the Python dependencies' directory environment variable +ENV ROBOT_DEPENDENCY_DIR /opt/robotframework/dependencies + # Set the reports directory environment variable ENV ROBOT_REPORTS_DIR /opt/robotframework/reports @@ -155,6 +158,10 @@ RUN chmod ugo+w /var/log \ # Update system path ENV PATH=/opt/robotframework/bin:/opt/robotframework/drivers:$PATH +# Ensure the directory for Python dependencies exists +RUN mkdir -p ${ROBOT_DEPENDENCY_DIR} \ + && chown ${ROBOT_UID}:${ROBOT_GID} ${ROBOT_DEPENDENCY_DIR} + # Set up a volume for the generated reports VOLUME ${ROBOT_REPORTS_DIR} diff --git a/README.md b/README.md index ef3af07..4d35ea0 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ * [Passing additional options](#passing-additional-options) * [Testing emails](#testing-emails) * [Dealing with Datetimes and Timezones](#dealing-with-datetimes-and-timezones) + * [Installing additional dependencies](#installing-additional-dependencies) * [Security consideration](#security-consideration) * [Continuous integration](#continuous-integration) * [Defining a test run ID](#defining-a-test-run-id) @@ -138,6 +139,28 @@ To set the timezone used inside the Docker image, you can set the `TZ` environme -e TZ=America/New_York \ ppodgorsek/robot-framework:latest +### Installing additional dependencies + +It is possible to install additional dependencies dynamically at runtime rather than having to extend this image. + +To do so, simply mount a text file containing the list of dependencies you would like to install using `pip`: (by default, this file is empty if not mounted) + + docker run \ + -v :/opt/robotframework/pip-requirements.txt:Z \ + -v :/opt/robotframework/tests:Z \ + ppodgorsek/robot-framework:latest + +The file must follow [Pip's official requirements file format](https://pip.pypa.io/en/stable/reference/requirements-file-format/). + +Here is a example of what such a file could contain: + +``` +robotframework-docker==1.4.2 +rpa==1.50.0 +``` + +**For large dependencies, it is still recommended to extend the project's image and to add them there, to avoid delaying the CI/CD pipelines with repeated dependency installations.** + ## Security consideration By default, containers are implicitly run using `--user=1000:1000`, please remember to adjust that command-line setting accordingly, for example: diff --git a/bin/run-tests-in-virtual-screen.sh b/bin/run-tests-in-virtual-screen.sh index 8e4d674..299b654 100755 --- a/bin/run-tests-in-virtual-screen.sh +++ b/bin/run-tests-in-virtual-screen.sh @@ -19,6 +19,17 @@ fi # Ensure the output folder exists mkdir -p ${ROBOT_REPORTS_FINAL_DIR} +# Check if additional dependencies should be installed via pip +if [ -e "/opt/robotframework/pip-requirements.txt" ] +then + echo "Installing pip dependencies..." + + mkdir -p ${ROBOT_DEPENDENCY_DIR} + pip install -r /opt/robotframework/pip-requirements.txt -t ${ROBOT_DEPENDENCY_DIR} + + export PYTHONPATH=${ROBOT_DEPENDENCY_DIR}:${PYTHONPATH} +fi + # No need for the overhead of Pabot if no parallelisation is required if [ $ROBOT_THREADS -eq 1 ] then diff --git a/test/pip-dependencies/main.robot b/test/pip-dependencies/main.robot new file mode 100644 index 0000000..dbdabb2 --- /dev/null +++ b/test/pip-dependencies/main.robot @@ -0,0 +1,20 @@ +# This test scenario was taken from https://github.com/FormulatedAutomation/robotframework-otp + +*** Settings *** +Library OTP +Library DateTime + +*** Variables *** +${SECRET} base32secret + +*** Test Cases *** +Get OTP from secret + ${otp}= Get OTP ${SECRET} + Log To Console ${SECRET} + Should Match Regexp ${otp} \\d{6} + +Get OTP from secret with time + ${timestamp}= Convert Date ${1402481262} epoch + ${otp}= Get OTP ${SECRET} ${timestamp} + Should Match Regexp ${otp} \\d{6} + Should Be Equal As Strings ${otp} 055118 diff --git a/test/pip-dependencies/requirements.txt b/test/pip-dependencies/requirements.txt new file mode 100644 index 0000000..af16842 --- /dev/null +++ b/test/pip-dependencies/requirements.txt @@ -0,0 +1,2 @@ +pyotp==2.9.0 +robotframework-otp==1.1.0 From 6ae3d095973472bc4bffdedc7ece955b1a7876d0 Mon Sep 17 00:00:00 2001 From: Paul Podgorsek Date: Wed, 7 Feb 2024 16:22:07 +0000 Subject: [PATCH 2/2] Issue #376 - Cannot install easily custom libraries * Fixed a syntax error --- .github/workflows/docker-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docker-build.yml b/.github/workflows/docker-build.yml index 807ff34..20c13f8 100644 --- a/.github/workflows/docker-build.yml +++ b/.github/workflows/docker-build.yml @@ -107,7 +107,7 @@ jobs: -e SCREEN_HEIGHT=2160 \ $IMAGE_NAME - name: Debug Log Level Test - run: + run: | podman run --shm-size=1g \ -v `pwd`/test/faker.robot:/opt/robotframework/tests/faker.robot:Z \ -e BROWSER=$BROWSER \