-
-
Notifications
You must be signed in to change notification settings - Fork 28
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #351 from openzim/automated_daily_tests
Automate daily tests of ZIM behavior - Youtube only for now
- Loading branch information
Showing
5 changed files
with
228 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
name: DailyTests | ||
|
||
on: | ||
schedule: | ||
- cron: "0 4 * * *" | ||
workflow_dispatch: | ||
|
||
|
||
jobs: | ||
run-daily-tests: | ||
runs-on: ubuntu-22.04 | ||
|
||
steps: | ||
- name: checkout | ||
uses: actions/checkout@v4 | ||
|
||
- name: build zimit image | ||
run: docker build -t local-zimit . | ||
|
||
- name: run crawl of test website | ||
run: docker run -v $PWD/output3:/output local-zimit zimit --url https://website.test.openzim.org/ --name tests_eng_test-website --zim-file tests_eng_test-website.zim | ||
|
||
- name: build selenium test image | ||
run: docker build -t local-selenium tests-daily | ||
|
||
- name: run integration test suite | ||
run: docker run -v $PWD/tests-daily/daily.py:/app/daily.py -v $PWD/output3:/output local-selenium bash -c "cd /app && pytest -h && pytest -v --log-level=INFO --log-format='%(levelname)s - %(message)s' daily.py" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
# Let's extract kiwix-tools as usual on alpine temporary build container | ||
FROM alpine:3.18 as kiwix-serve | ||
LABEL org.opencontainers.image.source https://github.com/openzim/kiwix-tools | ||
|
||
# TARGETPLATFORM is injected by docker build | ||
ARG TARGETPLATFORM | ||
ARG KIWIX_TOOLS_VERSION | ||
|
||
RUN set -e && \ | ||
# default (no KIWIX_TOOLS_VERSION set) to today's nightly | ||
if [ -z "$KIWIX_TOOLS_VERSION" ] ; then KIWIX_TOOLS_VERSION=$(date +"%Y-%m-%d") ; fi && \ | ||
apk --no-cache add dumb-init curl && \ | ||
echo "TARGETPLATFORM: $TARGETPLATFORM" && \ | ||
if [ "$TARGETPLATFORM" = "linux/386" ]; then ARCH="i586"; \ | ||
# linux/arm64/v8 points to linux/arm64 | ||
elif [ "$TARGETPLATFORM" = "linux/arm64/v8" \ | ||
-o "$TARGETPLATFORM" = "linux/arm64" ]; then ARCH="aarch64"; \ | ||
# linux/arm translates to linux/arm/v7 | ||
elif [ "$TARGETPLATFORM" = "linux/arm/v7" ]; then ARCH="armv8"; \ | ||
elif [ "$TARGETPLATFORM" = "linux/arm/v6" ]; then ARCH="armv6"; \ | ||
elif [ "$TARGETPLATFORM" = "linux/amd64/v3" \ | ||
-o "$TARGETPLATFORM" = "linux/amd64/v2" \ | ||
-o "$TARGETPLATFORM" = "linux/amd64" ]; then ARCH="x86_64"; \ | ||
# we dont suppot any other arch so let it fail | ||
else ARCH="unknown"; fi && \ | ||
# download requested kiwix-tools version | ||
url="http://mirror.download.kiwix.org/nightly/$KIWIX_TOOLS_VERSION/kiwix-tools_linux-$ARCH-$KIWIX_TOOLS_VERSION.tar.gz" && \ | ||
echo "URL: $url" && \ | ||
mkdir /kiwix-serve && \ | ||
curl -k -L $url | tar -xz -C /kiwix-serve --strip-components 1 | ||
|
||
# Build real "workload" container | ||
FROM python:3.12-slim-bookworm | ||
|
||
# Add kiwix-serve | ||
COPY --from=kiwix-serve /kiwix-serve /usr/local/bin | ||
|
||
# Update apt + install dependencies + install Google Chrome dependencies + clean-up apt lists | ||
RUN apt-get update -y && \ | ||
apt-get install -qqy wget xvfb unzip jq && \ | ||
apt-get install -qqy libxss1 libappindicator1 libgconf-2-4 \ | ||
fonts-liberation libasound2 libnspr4 libnss3 libx11-xcb1 libxtst6 lsb-release xdg-utils \ | ||
libgbm1 libnss3 libatk-bridge2.0-0 libgtk-3-0 libx11-xcb1 libxcb-dri3-0 && \ | ||
rm -rf /var/lib/apt/lists/* | ||
|
||
# Fetch the latest version numbers and URLs for Chrome and ChromeDriver | ||
RUN wget -q -O /tmp/versions.json https://googlechromelabs.github.io/chrome-for-testing/last-known-good-versions-with-downloads.json | ||
|
||
# Install chrome | ||
RUN CHROME_URL=$(jq -r '.channels.Stable.downloads.chrome[] | select(.platform=="linux64") | .url' /tmp/versions.json) && \ | ||
wget -q --continue -O /tmp/chrome-linux64.zip $CHROME_URL && \ | ||
unzip /tmp/chrome-linux64.zip -d /opt/chrome | ||
|
||
RUN chmod +x /opt/chrome/chrome-linux64/chrome | ||
|
||
# Install chromedriver | ||
RUN CHROMEDRIVER_URL=$(jq -r '.channels.Stable.downloads.chromedriver[] | select(.platform=="linux64") | .url' /tmp/versions.json) && \ | ||
wget -q --continue -O /tmp/chromedriver-linux64.zip $CHROMEDRIVER_URL && \ | ||
unzip /tmp/chromedriver-linux64.zip -d /opt/chromedriver && \ | ||
chmod +x /opt/chromedriver/chromedriver-linux64/chromedriver | ||
|
||
# Set up Chromedriver Environment variables | ||
ENV CHROMEDRIVER_DIR /opt/chromedriver | ||
ENV PATH $CHROMEDRIVER_DIR:$PATH | ||
|
||
# Clean up | ||
RUN rm /tmp/chrome-linux64.zip /tmp/chromedriver-linux64.zip /tmp/versions.json | ||
|
||
# Update pip, install selenium, create work directory | ||
RUN \ | ||
python -m pip install --no-cache-dir -U \ | ||
pip \ | ||
selenium==4.23.0 \ | ||
pytest==8.2.2 \ | ||
&& mkdir -p /work |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
import logging | ||
import subprocess | ||
from time import sleep | ||
|
||
import pytest | ||
from selenium import webdriver | ||
from selenium.webdriver.chrome.options import Options | ||
from selenium.webdriver.chrome.service import Service as ChromeService | ||
from selenium.webdriver.common.by import By | ||
from selenium.webdriver.support import expected_conditions | ||
from selenium.webdriver.support.ui import WebDriverWait | ||
|
||
KIWIX_SERVE_START_SLEEP = 1 | ||
|
||
ZIM_NAME = "tests_eng_test-website" | ||
YOUTUBE_VIDEO_PATH = "youtube.fuzzy.replayweb.page/embed/g5skcrNXdDM" | ||
|
||
CHECK_VIDEO_IS_PLAYING_AFTER_SECS = 30 | ||
|
||
logger = logging.getLogger(__name__) | ||
|
||
|
||
@pytest.fixture(scope="module") | ||
def chrome_driver(): | ||
"""Start chrome and setup chrome driver / selenium""" | ||
|
||
logger.info("Starting Chrome") | ||
chrome_options = Options() | ||
chrome_options.add_argument("--headless") | ||
chrome_options.add_argument("--no-sandbox") | ||
# Other options of interest: | ||
# --disable-dev-shm-usage (not needed anymore with recent chrome versions) | ||
# --disable-gpu (important for some versions of Chrome) | ||
# --remote-debugging-port=9222 (should you need to remote debug) | ||
|
||
# Set path to Chrome binary | ||
chrome_options.binary_location = "/opt/chrome/chrome-linux64/chrome" | ||
|
||
# Set path to ChromeDriver | ||
chrome_service = ChromeService( | ||
executable_path="/opt/chromedriver/chromedriver-linux64/chromedriver" | ||
) | ||
|
||
# Set up driver | ||
driver = webdriver.Chrome(service=chrome_service, options=chrome_options) | ||
|
||
yield driver | ||
|
||
# Cleanup | ||
logger.info("Quitting Chrome") | ||
driver.quit() | ||
|
||
|
||
@pytest.fixture(scope="module") | ||
def kiwix_serve(): | ||
"""Start kiwix-serve with given ZIM""" | ||
|
||
logger.info("Starting kiwix-serve") | ||
process = subprocess.Popen( | ||
[ | ||
"/usr/bin/env", | ||
"/usr/local/bin/kiwix-serve", | ||
f"/output/{ZIM_NAME}.zim", | ||
] | ||
) | ||
|
||
logger.info( | ||
f"Waiting {KIWIX_SERVE_START_SLEEP} secs to be 'sure' that kiwix-serve is ready" | ||
) | ||
sleep(KIWIX_SERVE_START_SLEEP) | ||
|
||
if process.poll() is not None: | ||
raise Exception("kiwix-serve has terminated too early") | ||
|
||
yield process | ||
|
||
# Cleanup | ||
logger.info("Quitting kiwix-serve") | ||
process.terminate() | ||
|
||
|
||
def test_youtube_video(chrome_driver, kiwix_serve): # noqa: ARG001 | ||
"""Test that youtube video loads, and still plays after a while""" | ||
|
||
chrome_driver.get(f"http://localhost:80/content/{ZIM_NAME}/{YOUTUBE_VIDEO_PATH}") | ||
|
||
if chrome_driver.title == "Content not found": | ||
raise Exception("Wrong URL, kiwix-serve said that content is not found") | ||
|
||
button = WebDriverWait(chrome_driver, 1).until( | ||
expected_conditions.presence_of_element_located( | ||
(By.XPATH, "//button[@title='Play']") | ||
) | ||
) | ||
|
||
logger.info("Play button found in page") | ||
|
||
button.click() | ||
|
||
video = WebDriverWait(chrome_driver, 1).until( | ||
expected_conditions.presence_of_element_located((By.TAG_NAME, "video")) | ||
) | ||
|
||
logger.info("Video found in page") | ||
|
||
# arguments[0] is the video tag passed to execute_script | ||
if not chrome_driver.execute_script("return arguments[0].paused === false", video): | ||
raise Exception("Video is not playing, failed to start probably") | ||
|
||
logger.info("Video is playing") | ||
|
||
logger.info( | ||
f"Waiting {CHECK_VIDEO_IS_PLAYING_AFTER_SECS} secs to check video is still " | ||
"playing" | ||
) | ||
sleep(CHECK_VIDEO_IS_PLAYING_AFTER_SECS) | ||
|
||
# arguments[0] is the video tag passed to execute_script | ||
if not chrome_driver.execute_script("return arguments[0].paused === false", video): | ||
raise Exception( | ||
"Video is not playing anymore after " | ||
f"{CHECK_VIDEO_IS_PLAYING_AFTER_SECS} secs" | ||
) | ||
logger.info("Video is still playing") |