openvidu-deployment-tester: Add recording and call parametrizable tests

pull/797/head
cruizba 2023-03-29 18:28:05 +02:00
parent 868835bb91
commit 11e5888747
6 changed files with 207 additions and 49 deletions

View File

@ -14,7 +14,8 @@ RUN apt-get update && \
x11-utils \
wget \
python3 \
python3-pip
python3-pip \
ffmpeg
# Install latest chrome
RUN wget -q https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb && \

View File

@ -1,4 +1,6 @@
selenium==4.8.2
webdriver-manager==3.8.5
prettytable==3.6.0
beautifulsoup4==4.12.0
beautifulsoup4==4.12.0
opencv-python-headless==4.7.0.72
numpy==1.24.2

View File

@ -9,12 +9,17 @@ def test_parser(subparsers, command):
test_parser = subparsers.add_parser(command)
test_parser.add_argument("--openvidu-url", required=True, help="OpenVidu URL to test")
test_parser.add_argument("--openvidu-secret", required=True, help="OpenVidu secret used for OpenVidu API")
test_parser.add_argument("--browser", required=True, choices=["chrome", "firefox"], help="Browser to test")
test_parser.add_argument("--turn", required=False, default=False, action='store_true', help="Force TURN usage. Only available for Firefox")
# Basic test specific parameter
if command == "basic-test":
test_parser.add_argument("--openvidu-edition", required=True, choices=["ce", "pro", "enterprise"], help="OpenVidu edition to test")
test_parser.add_argument("--browser", required=True, choices=["chrome", "firefox"], help="Browser to test")
test_parser.add_argument("--turn", required=False, default=False, action='store_true', help="Force TURN usage. Only available for Firefox")
elif command == "recording-test":
if command.startswith("call-test"):
test_parser.add_argument("--openvidu-call-url", required=True, help="OpenVidu Call URL to test")
test_parser.add_argument("--number-of-clients", required=False, nargs='?', help="Number of clients to test", const=4, default=4, type=int)
test_parser.add_argument("--openvidu-call-username", required=True, help="OpenVidu Call user to test")
test_parser.add_argument("--openvidu-call-password", required=True, help="OpenVidu Call password to test")
def initialize_parser():
parser = argparse.ArgumentParser()
@ -22,13 +27,7 @@ def initialize_parser():
install_drivers_parser(subparsers)
test_parser(subparsers, "basic-test")
test_parser(subparsers, "call-test-recording")
test_parser(subparsers, "call-test")
return parser
def print_args(args):
print("Executing command: " + args.command)
for arg, value in vars(args).items():
if arg != 'command':
if arg == 'openvidu-secret':
value = '********'
print(f"\t{arg}: {value}")
return parser

View File

@ -5,7 +5,6 @@ import tests
# Define your commands here
def install_drivers(args):
cli_utils.print_args(args)
utils.install_drivers(args.chrome_version, args.gecko_version)
# Define the command-line arguments
@ -21,5 +20,9 @@ if args.command == "install-drivers":
install_drivers(args)
elif args.command == "basic-test":
tests.basic_test(args)
elif args.command == "call-test-recording":
tests.call_recording_test(args)
elif args.command == "call-test":
tests.call_test(args)
else:
print("Error: No command specified")

View File

@ -1,38 +1,26 @@
import utils
import time
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from requests.auth import HTTPBasicAuth
import requests
def basic_test(args):
print("Running basic test with args:", args)
driver = utils.runBrowser(args.browser, args.turn)
base_url = args.openvidu_url
if args.openvidu_edition == "ce":
url_test = args.openvidu_url + '/dashboard'
driver.get(url_test)
elem = driver.find_element(By.ID,'test-btn')
elem.send_keys(Keys.RETURN)
elem = driver.find_element(By.NAME, 'secret')
elem.send_keys(args.openvidu_secret)
elem = driver.find_element(By.ID, 'join-btn')
elem.send_keys(Keys.RETURN)
driver.get(f"{base_url}/dashboard")
driver.find_element(By.ID, 'test-btn').send_keys(Keys.RETURN)
driver.find_element(By.NAME, 'secret').send_keys(args.openvidu_secret)
driver.find_element(By.ID, 'join-btn').send_keys(Keys.RETURN)
elif args.openvidu_edition == "pro":
url_test = args.openvidu_url + '/inspector'
driver.get(url_test)
elem = driver.find_element(By.ID, 'secret-input')
elem.send_keys(args.openvidu_secret)
elem = driver.find_element(By.ID, 'login-btn')
elem.send_keys(Keys.RETURN)
# print('data:image/png;base64,' + self.driver.get_screenshot_as_base64())
elem = driver.find_element(By.ID,'menu-test-btn')
elem.send_keys(Keys.RETURN)
elem = driver.find_element(By.ID,'test-btn')
elem.send_keys(Keys.RETURN)
driver.get(f"{base_url}/inspector")
driver.find_element(By.ID, 'secret-input').send_keys(args.openvidu_secret)
driver.find_element(By.ID, 'login-btn').send_keys(Keys.RETURN)
driver.find_element(By.ID, 'menu-test-btn').send_keys(Keys.RETURN)
driver.find_element(By.ID, 'test-btn').send_keys(Keys.RETURN)
else:
print("Error: Invalid OpenVidu edition specified")
exit(1)
@ -44,9 +32,75 @@ def basic_test(args):
except:
video_error = True
finally:
# print('data:image/png;base64,' + driver.get_screenshot_as_base64())
if args.browser == "firefox":
utils.print_candidates(driver)
if video_error == True:
raise Exception('Error. No video detected')
if video_error:
raise Exception('Error. No video detected')
def call_recording_test(args):
print("Testing recording with OpenVidu Call with args:", args)
driver = utils.runBrowser(args.browser, args.turn)
driver.get(args.openvidu_call_url)
utils.call_login(driver, args.openvidu_call_username, args.openvidu_call_password)
session_name = utils.call_session(driver, args.number_of_clients)
print('Starting recording')
driver.find_element(By.ID, 'activities-panel-btn').send_keys(Keys.RETURN)
time.sleep(5)
driver.find_element(By.ID, 'mat-expansion-panel-header-0').send_keys(Keys.RETURN)
time.sleep(5)
driver.find_element(By.ID, 'start-recording-btn').send_keys(Keys.RETURN)
print('Recording started')
time.sleep(10)
print('Stopping recording')
driver.find_element(By.ID, 'stop-recording-btn').send_keys(Keys.RETURN)
print('Recording stopped')
time.sleep(5)
utils.close_all_tabs(driver, args.browser)
print(f'Downloading recording from {args.openvidu_url}/openvidu/recordings/{session_name}/{session_name}.mp4')
url = f'{args.openvidu_url}/openvidu/recordings/{session_name}/{session_name}.mp4'
if args.browser == "chrome":
print("Checking if recording is green (Default video color from chrome emulated video is green)")
is_green = utils.is_video_green(url, HTTPBasicAuth('OPENVIDUAPP', args.openvidu_secret), f'{session_name}.mp4')
is_video_valid = utils.is_video_valid(url, HTTPBasicAuth('OPENVIDUAPP', args.openvidu_secret), f'{session_name}.mp4')
print("Recording is", "green" if is_green else "not green")
if not is_green or not is_video_valid:
exit(1)
elif args.browser == "firefox":
# Close all tabs
print("Checking if recording is a valid video")
is_valid = utils.is_video_valid(url, HTTPBasicAuth('OPENVIDUAPP', args.openvidu_secret), f'{session_name}.mp4')
print("Recording is", "valid" if is_valid else "not valid")
if not is_valid:
exit(1)
print('Removing recording')
url = f'{args.openvidu_url}/openvidu/api/recordings/stop/{session_name}'
requests.delete(url, auth=HTTPBasicAuth('OPENVIDUAPP', args.openvidu_secret), verify=False)
def call_test(args):
print(f"Testing recording with OpenVidu Call with args: {args}")
driver = utils.runBrowser(args.browser, args.turn)
driver.get(args.openvidu_call_url)
utils.call_login(driver, args.openvidu_call_username, args.openvidu_call_password)
utils.call_session(driver, args.number_of_clients)
time.sleep(5)
videos = driver.find_elements(By.TAG_NAME, 'video')
if len(videos) != args.number_of_clients:
raise Exception('Error. Number of videos is not equal to number of clients')
for i, video in enumerate(videos):
current_time = float(video.get_attribute('currentTime'))
print(f'Video {i} is playing. Current time: {current_time}')
if current_time < 1:
raise Exception('Error. Video is not playing')
utils.close_all_tabs(driver, args.browser)

View File

@ -1,11 +1,16 @@
import time
import os
import cv2
import numpy as np
import requests
import subprocess
from webdriver_manager.chrome import ChromeDriverManager
from webdriver_manager.firefox import GeckoDriverManager
from selenium.webdriver.chrome.service import Service as ChromeService
from selenium.webdriver.firefox.service import Service as FirefoxService
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium import webdriver
from bs4 import BeautifulSoup
from prettytable import from_html_one
@ -46,8 +51,11 @@ def runChrome():
# Load version from file
chrome_version = None
with open("chrome_version", "r") as f:
chrome_version = f.read()
# Check if chrome version file exists and load it
if os.path.isfile("chrome_version"):
with open("chrome_version", "r") as f:
chrome_version = f.read()
print("Running chrome...")
print("Chrome version: ", chrome_version)
@ -68,8 +76,11 @@ def runFirefox(turn=False):
# Load version from file
gecko_version = None
with open("gecko_version", "r") as f:
gecko_version = f.read()
# Check if gecko version file exists and load it
if os.path.isfile("gecko_version"):
with open("gecko_version", "r") as f:
gecko_version = f.read()
print("Running firefox with Turn: ", turn)
print("Gecko version: ", gecko_version)
@ -120,4 +131,92 @@ def print_candidates(driver):
except:
print('[Warn] Some candidates may not appear in test result')
driver.switch_to.window(driver.window_handles[0])
driver.close()
driver.close()
def call_session(driver, num_of_clients):
print('First session entering')
session_name = driver.find_element(By.ID, 'session-name-input').get_attribute('value')
driver.find_element(By.ID, 'join-btn').send_keys(Keys.RETURN)
print('Joining user 1 to session', session_name)
driver.find_element(By.ID, 'join-button').send_keys(Keys.RETURN)
url_link = driver.current_url
for i in range(2, num_of_clients + 1):
print(f'Joining user {i} to session {session_name}')
driver.execute_script(f'window.open("{url_link}", "_blank");')
driver.switch_to.window(driver.window_handles[-1])
driver.find_element(By.ID, 'join-button').send_keys(Keys.RETURN)
time.sleep(5)
driver.switch_to.window(driver.window_handles[0])
return session_name
def call_login(driver, username, password):
print('Logging in')
driver.find_element(By.NAME, 'username').send_keys(username)
driver.find_element(By.NAME, 'password').send_keys(password)
driver.find_element(By.ID, 'join-btn').send_keys(Keys.RETURN)
def close_all_tabs(driver, browser):
if browser == 'firefox':
# Close all tabs
for i in range(0, len(driver.window_handles)):
driver.switch_to.window(driver.window_handles[0])
driver.close()
time.sleep(1)
def is_video_green(url, basic_auth, video_filename):
# Download the video from the URL
response = requests.get(url, auth=basic_auth, verify=False)
open(video_filename, 'wb').write(response.content)
# Read the video using OpenCV
cap = cv2.VideoCapture(video_filename)
# Parameters to calculate if the video is mostly green
total_frames = 0
green_frames = 0
green_threshold = 0.8
while cap.isOpened():
ret, frame = cap.read()
if not ret:
break
total_frames += 1
# Define green ranges in the RGB color space
lower_green = np.array([0, 100, 0])
upper_green = np.array([100, 255, 100])
# Create a mask to select only green pixels
mask = cv2.inRange(frame, lower_green, upper_green)
# Calculate the percentage of green pixels in the frame
green_ratio = np.sum(mask == 255) / (mask.shape[0] * mask.shape[1])
if green_ratio > green_threshold:
green_frames += 1
# Clean up resources
cap.release()
# Remove the video file
os.remove(video_filename)
# Determine if the video is mostly green
return green_frames / total_frames > 0.8
def is_video_valid(url, basic_auth, video_filename):
response = requests.get(url, auth=basic_auth, verify=False)
open(video_filename, 'wb').write(response.content)
try:
cmd = ["ffprobe", "-v", "error", "-show_streams", "-select_streams", "v:0", video_filename]
output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
if output:
return True
except subprocess.CalledProcessError as e:
print(f"Error: {e}")
finally:
os.remove(video_filename)