В данной статье отражена попытка применить модель детекции для UI-тестирования.
Предполагалось, что внедрение ML должно позволить (даже при полном изменении интерфейса) не переписывать автотесты и полностью исключить человеческий фактор при UI-тестировании.
Для автоматизации UI-тестировании использовались следующие инструменты:
Selenium – инструмент для автоматизации действий с браузером;
Pytest – инструмент для выполнения и проверки тестовых сценариев;
ML – обученная модель машинного обучения.
Для эксперимента была выбрана модель YOLOv8m. Для обучения модели применялся датасет от компании Ultralytics – Website Screenshots Datase, который представляет собой набор данных скриншотов 1 206 веб-сайтов. К большому сожалению в данном датасете наибольшую часть классов представляют собой button (кнопки), что сильно сказалось на качестве распознавания других классов.
Обучение модели:
!nvidia-smi import os HOME = os.getcwd() print(HOME) !pip install ultralytics==8.0.196 from IPython import display display.clear_output() import ultralytics ultralytics.checks() from ultralytics import YOLO from IPython.display import display, Image !mkdir {HOME}/datasets !pip install roboflow --quiet !pip install roboflow from roboflow import Roboflow rf = Roboflow(api_key="5Mar5Cz54g9Sq0KSRc8x") project = rf.workspace("roboflow-gw7yv").project("website-screenshots") dataset = project.version(1).download("yolov8") !yolo task=detect mode=train model=yolov8m.pt data={dataset.location}/data.yaml epochs=50 imgsz=800 plots=True !ls {HOME}/runs/detect/train/ Image(filename=f'{HOME}/runs/detect/train/confusion_matrix.png', width=600) Image(filename=f'{HOME}/runs/detect/train/results.png', width=600) Image(filename=f'{HOME}/runs/detect/train/val_batch0_pred.jpg', width=600) !yolo task=detect mode=val model={HOME}/runs/detect/train/weights/best.pt data={dataset.location}/data.yaml from google.colab import drive drive.mount('/content/drive') import shutil import os os.getcwd() sourcePath = "/content/runs/detect/train/weights/best.pt" destinationPath = "/content/drive/MyDrive/best.pt" shutil.copyfile(sourcePath, destinationPath) !yolo task=detect mode=predict model={HOME}/runs/detect/train/weights/best.pt conf=0.25 source={dataset.location}/test/images save=True import glob from IPython.display import Image, display for image_path in glob.glob(f'{HOME}/runs/detect/predict/*.jpg')[:3]: display(Image(filename=image_path, width=600)) print("\n") project.version(dataset.version).deploy(model_type="yolov8", model_path=f"{HOME}/runs/detect/train/") model = project.version(dataset.version).model import os, random test_set_loc = dataset.location + "/test/images/" random_test_image = random.choice(os.listdir(test_set_loc)) print("running inference on " + random_test_image) pred = model.predict(test_set_loc + random_test_image, confidence=40, overlap=30).json() pred from ultralytics import YOLO model.export()
Упрощенно процесс автоматизации UI-тестирования выглядит следующим образом (на примере распознавания кнопок):
1. С помощью Selenium создается скриншот веб-сайта.
2. Полученный скриншот сохраняется, а затем передается в обученную модель.
3. Модель находит нужные классы.
4. Затем, модель определяет координаты всех распознанных изображений и возвращает результат в виде json формата с указанием центра координат объекта – x и y и ширину и высоту распознанного объекта.
5. Найденные координаты передаются в Selenium и с помощью Pytest проверяется корректность работы найденного объекта.
Тестирование работы кнопки с помощью предварительно обученной модели YOLOv8m:
from selenium import webdriver from selenium.webdriver.common.by import By import time from selenium.webdriver.common.action_chains import ActionChains import pytest import json from PIL import Image import easyocr from ultralytics import YOLO @pytest.fixture def browser(): driver = webdriver.Firefox() yield driver driver.quit() def test_ckic(browser): browser.set_window_size(1024,768) browser.get("https://guru.qahacking.ru") path = "sait_1.png" browser.save_screenshot(path) model = YOLO('best.pt') prediction = model.predict(path) for r in prediction: x=r.tojson() elements = json.loads(x) text=[] button=[] for i in elements: if i['name']=='text': text.append(i) if i['name']=='button': button.append(i) im = Image.open(path) for i in button: x1=int(i['box']['x1']) x2=int(i['box']['x2']) y1=int(i['box']['y1']) y2=int(i['box']['y2']) im_crop = im.crop((x1, y1, x2, y2)) im_crop.save('imeg.png') print(easyocr.Reader(["ru"]).readtext('imeg.png', detail=0, paragraph=True, text_threshold=0.8)) actions = ActionChains(browser) actions.move_by_offset(x1, y1).perform() time.sleep(5) actions.click().perform() time.sleep(5) assert browser.current_url == 'https://ermita.one/matricy-kompetencij/'
Спасибо за внимание.
