mirror of
https://github.com/openzim/zimit.git
synced 2025-09-22 11:22:23 -04:00
Automate daily tests of ZIM behavior - Youtube only for now
This commit is contained in:
parent
751e10473a
commit
6d078c4dcf
27
.github/workflows/DailyTests.yaml
vendored
Normal file
27
.github/workflows/DailyTests.yaml
vendored
Normal file
@ -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"
|
@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Add `--custom-behaviors` argument to support path/HTTP(S) URL custom behaviors to pass to the crawler (#313)
|
- Add `--custom-behaviors` argument to support path/HTTP(S) URL custom behaviors to pass to the crawler (#313)
|
||||||
|
- Add daily automated end-to-end tests of a page with Youtube player (#330)
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
@ -39,6 +39,7 @@ test = [
|
|||||||
dev = [
|
dev = [
|
||||||
"pre-commit==3.7.1",
|
"pre-commit==3.7.1",
|
||||||
"debugpy==1.8.1",
|
"debugpy==1.8.1",
|
||||||
|
"selenium==4.23.0", # used in daily tests, convenient for dev purpose (autocompletion)
|
||||||
"zimit[scripts]",
|
"zimit[scripts]",
|
||||||
"zimit[lint]",
|
"zimit[lint]",
|
||||||
"zimit[test]",
|
"zimit[test]",
|
||||||
|
75
tests-daily/Dockerfile
Normal file
75
tests-daily/Dockerfile
Normal file
@ -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
|
124
tests-daily/daily.py
Normal file
124
tests-daily/daily.py
Normal file
@ -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")
|
Loading…
x
Reference in New Issue
Block a user