Всем привет.
Была задача написать небольшой тест для проверки работоспособности canvas элемента на странице. Как-бы смоук тест на то, не отвалилась ли БД или еще какой из элементов. Для мониторинга. Решил использовать Python, Selenium Webdriver, OpenCV. Нашел статью, где популярно разжевано: HTML <canvas> testing with Selenium and OpenCV
Все сделал, настроил. Вроде работает. Но столкнулся с проблемой и не знаю как решить.
Проблема: если после нахождения элемента на странице и клика по нему доабвить поиск другого элемента и клика уже по нему, то второй клик не отрабатывает (метод вроде отрабатывает, то глазами вижу что действия, которое должно быть после клика - нет).
Модуль поисковика элемента:
graphical_locator.py
import cv2
import numpy
from io import BytesIO
from PIL import Image
class GraphicalLocator(object):
def __init__(self, img_path):
self.locator = img_path
# x, y position in pixels counting from left, top corner
self.x = None
self.y = None
self.img = cv2.imread(img_path)
self.width = self.img.shape[1]
self.height = self.img.shape[0]
self.threshold = None
@property
def center_x(self):
if self.x and self.width:
return self.x + int(self.width / 2)
else:
None
@property
def center_y(self):
if self.y and self.height:
return self.y + int(self.height / 2)
else:
None
# Clear last found coordinates
def find_me(self, drv):
self.x = self.y = None
# Get current screenshot of a web page
scr = drv.get_screenshot_as_png()
# Convert img to BytesIO
scr = Image.open(BytesIO(scr))
# Convert to format accepted by OpenCV
scr = numpy.asarray(
scr,
dtype=numpy.float32
).astype(numpy.uint8)
# Convert image from BGR to RGB format
scr = cv2.cvtColor(scr, cv2.COLOR_BGR2RGB)
# Image matching works only on gray images
# (color conversion from RGB/BGR to GRAY scale)
img_match = cv2.minMaxLoc(
cv2.matchTemplate(
cv2.cvtColor(
scr,
cv2.COLOR_RGB2GRAY
),
cv2.cvtColor(
self.img,
cv2.COLOR_BGR2GRAY
),
cv2.TM_CCOEFF_NORMED
)
)
# Calculate position of found element
self.x = img_match[3][0]
self.y = img_match[3][1]
# From full screenshot crop part that matches template image
scr_crop = scr[
self.y: (self.y + self.height),
self.x: (self.x + self.width)
]
# Calculate colors histogram of both template# and matching images and
# compare them
scr_hist = cv2.calcHist(
[scr_crop],
[0, 1, 2],
None,
[8, 8, 8],
[0, 256, 0, 256, 0, 256]
)
img_hist = cv2.calcHist(
[self.img],
[0, 1, 2],
None,
[8, 8, 8],
[0, 256, 0, 256, 0, 256]
)
comp_hist = cv2.compareHist(
img_hist,
scr_hist,
cv2.HISTCMP_CORREL
)
# Save treshold matches of: graphical image and image histogram
self.threshold = {
'shape': round(img_match[1], 2),
'histogram': round(comp_hist, 2)
}
# Return image with blue rectangle around match
return cv2.rectangle(
scr,
(self.x, self.y),
(self.x + self.width, self.y + self.height),
(0, 0, 255),
2
)
Модуль проверки:
check.py
import time
import os
from selenium.webdriver.common.action_chains import ActionChains
from .graphical_locator import GraphicalLocator
def check(driver):
def click(path, shape, histogram):
button = GraphicalLocator(
os.path.abspath(path))
button.find_me(driver)
is_found = False
print("\nSHAPE: ", path, button.threshold['shape'])
print("\nHISTOGRAM: ", path, button.threshold['histogram'])
if button.threshold['shape'] >= shape and \
button.threshold['histogram'] >= histogram:
is_found = True
if is_found:
action = ActionChains(driver)
action.move_by_offset(button.center_x, button.center_y)
action.click()
action.perform()
print("\nALREADY CLICKED")
time.sleep(2)
return True
return False
if click(
path="checks/elements/button_1.png",
shape=0.56,
histogram=0.97,
):
return click(
path="checks/elements/button_2.png",
shape=0.56,
histogram=0.53,
)
В итоге, первый клик проходит, это видно, а второй по коду проходит (click() возвращает True), но по факту нет. Кто с таким сталкивался? Куда копать?
Думал проблема в не очистке координат, но нет. Я же использую новый инстанс ActionChains. Как и GraphicalLocator.
python==3.5.2
selenium==3.14.0
chromedriver==2.45
opencv-python==3.4.4.19
numpy==1.15.4
Pillow==5.3.0
chrome==71.0.3578.98