CI: Use selenium in Horizon tests

Change-Id: I814413fdb1a74675846a4ee2d5fbada9592fceef
Signed-off-by: Michal Nasiadka <mnasiadka@gmail.com>
This commit is contained in:
Michal Nasiadka 2025-10-21 15:52:34 +02:00
parent 77f7009654
commit e2a4e6c294
4 changed files with 199 additions and 2 deletions

View file

@ -19,3 +19,62 @@
until: dashboard_output.content.find('Login') != -1
retries: 30
delay: 10
- name: Check if testinfra subdirectory exists
ansible.builtin.stat:
path: "{{ zuul.project.src_dir }}/tests/testinfra"
register: testinfra_dir
- name: Run testinfra tests
when: testinfra_dir.stat.exists
block:
- name: Ensure testinfra subdirectory exists
ansible.builtin.file:
path: "/home/zuul/testinfra"
state: directory
- name: Ensure screenshots directory exists
ansible.builtin.file:
path: "/home/zuul/testinfra/screenshots"
state: directory
- name: Ensure required packages are installed
ansible.builtin.pip:
name:
- pytest-html
- pytest-testinfra
- selenium
virtualenv: "{{ kolla_ansible_venv_path }}"
virtualenv_command: "python3 -m venv"
- name: Run Selenium Firefox container (Docker)
become: true
when: container_engine == 'docker'
community.docker.docker_container:
name: "selenium"
detach: true
image: "quay.io/opendevmirror/selenium-standalone-firefox:latest"
network_mode: host
- name: Run Selenium Firefox container (Podman)
become: true
when: container_engine == 'podman'
containers.podman.podman_container:
name: "selenium"
detach: true
image: "quay.io/opendevmirror/selenium-standalone-firefox:latest"
network_mode: host
- name: Wait for port 444 to be up
ansible.builtin.wait_for:
port: 4444
- name: Run testinfra tests
ansible.builtin.shell:
cmd: >
. {{ kolla_ansible_venv_path }}/bin/activate &&
py.test
--junit-xml /home/zuul/testinfra/testinfra-junit.xml -o junit_family=xunit1
--html=/home/zuul/testinfra/test-results-testinfra.html --self-contained-html
-v tests/testinfra
chdir: "{{ zuul.project.src_dir }}"

View file

@ -7,6 +7,18 @@
zuul_work_dir: '/home/zuul/tempest'
tasks:
- name: Return artifact to Zuul
zuul_return:
data:
zuul:
artifacts:
- name: "TestInfra Unit Test Report"
url: "testinfra/test-results-testinfra.html"
metadata:
type: unit_test_report
- name: "TestInfra Screenshots"
url: "testinfra/screenshots"
# TODO(mhiner): Currently only Docker to Podman migration is tested.
# If we want to test the other direction we have to rework this.
- name: Change container engine after the migration
@ -76,6 +88,14 @@
ara_report_local_dir: "{{ zuul.executor.log_root }}/{{ inventory_hostname }}/ara-report"
kolla_ansible_local_src_dir: "{{ zuul.executor.work_root }}/src/{{ zuul.project.canonical_hostname }}/openstack/kolla-ansible"
tasks:
- name: Download testinfra to executor
synchronize:
src: "/home/zuul/testinfra"
dest: "{{ zuul.executor.log_root }}/"
mode: pull
# TODO(mnasiadka): Remove in G/2026.1 cycle
ignore_errors: true
- name: Check for existence of ara sqlite
stat:
path: "{{ ansible_env.HOME }}/.ara/server/ansible.sqlite"

View file

@ -0,0 +1,118 @@
# Copyright 2018 Red Hat, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import time
import yaml
from pathlib import Path
from selenium.common.exceptions import TimeoutException
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
home = Path.home()
subpath = '/testinfra/screenshots/'
screenshot_path = str(home) + subpath
with open("/etc/kolla/passwords.yml", 'r') as file:
passwords = yaml.safe_load(file)
admin_password = passwords.get('keystone_admin_password')
def test_horizon_screenshot(host):
firefox_options = webdriver.FirefoxOptions()
driver = webdriver.Remote(
command_executor='http://localhost:4444/wd/hub',
options=firefox_options)
horizon_url = "https://192.0.2.10"
try:
driver.get(horizon_url)
WebDriverWait(driver, 30).until(
lambda driver: driver.execute_script(
'return document.readyState') == 'complete')
time.sleep(5)
original_size = driver.get_window_size()
required_width = driver.execute_script(
'return document.body.parentNode.scrollWidth')
required_height = driver.execute_script(
'return document.body.parentNode.scrollHeight') + 100
driver.set_window_size(required_width, required_height)
driver.find_element(By.TAG_NAME, 'body').\
screenshot(screenshot_path + "horizon-main.png") # nosec B108
driver.set_window_size(
original_size['width'], original_size['height'])
assert 'Login' in driver.title # nosec B101
except TimeoutException as e:
raise e
finally:
driver.quit()
def test_horizon_login(host):
firefox_options = webdriver.FirefoxOptions()
driver = webdriver.Remote(
command_executor='http://localhost:4444/wd/hub',
options=firefox_options)
horizon_url = "https://192.0.2.10"
logout_url = '/'.join((
horizon_url,
'auth',
'logout'))
try:
driver.get(logout_url)
user_field = driver.find_element(By.ID, 'id_username')
user_field.send_keys('admin')
pass_field = driver.find_element(By.ID, 'id_password')
pass_field.send_keys(admin_password)
button = driver.find_element(By.CSS_SELECTOR, '.btn-primary')
button.click()
WebDriverWait(driver, 30).until(
lambda driver: driver.execute_script(
'return document.readyState') == 'complete')
time.sleep(10)
original_size = driver.get_window_size()
required_width = driver.execute_script(
'return document.body.parentNode.scrollWidth')
required_height = driver.execute_script(
'return document.body.parentNode.scrollHeight') + 100
driver.set_window_size(required_width, required_height)
driver.find_element(By.TAG_NAME, 'body').\
screenshot(screenshot_path + "horizon-logged-in.png") # nosec B108
driver.set_window_size(
original_size['width'], original_size['height'])
assert 'Overview - OpenStack Dashboard' in driver.title # nosec B101
except TimeoutException as e:
raise e
finally:
driver.quit()

View file

@ -8,8 +8,8 @@
- ^ansible/(action_plugins|filter_plugins|library|module_utils)/
- ^ansible/roles/(common|fluentd|glance|haproxy-config|heat|horizon|keystone|loadbalancer|loadbalancer-config|neutron|nova|nova-cell|openvswitch|placement|proxysql|rabbitmq)/
- ^kolla_ansible/
- ^roles/kolla-ansible-deploy/
- ^tests/test-(core-openstack|dashboard).sh
- ^roles/kolla-ansible-(deploy|test-dashboard)/
- ^tests/testinfra/test_horizon.py
- ^tools/init-runonce
- job: