mirror of https://github.com/OpenVidu/openvidu.git
openvidu-deployment-tester: Add recording and call parametrizable tests
parent
868835bb91
commit
11e5888747
|
@ -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 && \
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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")
|
|
@ -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)
|
|
@ -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)
|
Loading…
Reference in New Issue