Подробнее о Sikuli в автоматизации тестирования

от автора

Вступление

Sikuli — это API позволяющая писать на Jython сценарии автоматизации опираясь на визуальную составляющую любой программы/сайта и т.д. Особенно приятна для автоматизации Flash.
О Sikuli написано мало статей и большинство из них обзорные. Ещё меньше русскоязычного хелпа, и ещё меньше примеров кода. И отсутствие последнего пожалуй самое трагичное для тестировщика ПО который столкнулся в работе с необходимостью автоматизировать какой либо флэш. Как раз это и подтолкнуло меня написать более ёмкую статью по Sikuli и описать несколько подробнее некоторые особенности использования.

Установка

Для установки и правильной работы Sikuli вам понадобится:
1. Java шестой версии и обязательно 32х разрядная.
2. Дистрибутив
3. Пакет обновлений.

В связи с тем, что Sikuli идет только в 32-разрядной комплектации, то для правильной работы на 64х-битных системах в обязательном порядке ставим Java 6u38 32х (с 7й версией не работает).
Так же необходимо поставить пакет обновлений. Устанавливается легко. Просто копируется из архива (пункт 3) содержимое папки «Sikuli-IDE» в папку с установленной программой «C:\Program Files (x86)\Sikuli X», кстати не меняйте папку установки назначенную по умолчанию.
Если вдруг что не так, вот ссылочка для почитать.

Функционал и особенности.

Снимок экрана image
Применяется для выделения определённой области экрана и последующем созданием паттерна image
При нажатии на паттерн появится окно «Настройка шаблонов» image
С вкладками всё примитивно и ясно. Единственное отмечу что на вкладке «смещение цели» целью является то место куда переместиться курсор и произведет клик/ввод. Причём место клика может лежать далеко за пределами паттерна.

Теперь о особенностях.
*****.png это название искомого рисунка который должен лежать в папке заранее сохраненного проекта. image
similar = схожесть, где 1=100% (лучше не использовать ибо находит не всегда), а например 0,85 (через точку) = 85%, что на мой взгляд самое оптимальное значение.
targetOffset(x,y)) и тут важно что координаты «x» и «y» это смещение цели от центра паттерна.

Выделение области/wait()/Click()

image
Великолепная функция и что самое главное в крайней степени полезная.
Многие говорят что Sikuli плохо соображает в работе и ошибается ещё здорово. Я же с этим в корне не согласен и считаю, что грамотный подход значительно увеличивает производительность программы.

Эта функция задает активную область экрана.
image
в которой будет производиться поиск искомого паттерна.
Можно ещё и вот так:

Region(x,y,w,h).find(Pattern("*****.png".similar(0.85)targetOffset(x,y))) 

Она крайне полезна если нам нужно чтобы скрипт реагировал на изменения оперативно, не тормозил систему.
Как пример:
из всего нашего большого экрана мы выбираем только небольшую область где каждый раз появляется заветная кнопочка. image
Далее описываем что в этой области нам надо искать и что с этим потом делать.
image
Для того чтобы оптимизировать процесс нам нужно запустить этот скрипт и чтоб он за нас 1 раз совершил клик. После мы переходим на вкладку «Сообщение» где видим координаты клика.
image
Далее делаем цикл и и делаем клик по координатам (это при условии что кнопка всегда будет появляться в одном и том же месте).
Схожесть в поиске делаем около 70 процентов, быстрее найдёт, ожидание 999…
image
По итогу мы имеем практически моментальное срабатывание.

Find()

Функция find() ищет паттерн. Но вот зачем? Всё просто. Один раз нашел, а дальше он будет знать где находится найденный объект всегда. Как применить на практике:
Имеем много чего либо… image
И нажимать это «что либо» программе придется долго и упорно…
Для того чтобы программа знала куда нажимать, нужно выставить targetOffset()
image
Повторяем для каждой цели, присваиваем переменные, оптимизируем если поле с множеством находится в одном и том же месте.

разворачивать тут

image

Далее мы можем найденные зоны использовать как хотим. Причём клик будет происходить без задержек на поиск и т.д.
image

Остальной функционал рассматривать не буду он примитивен и прост.

Примеры

Сценарий должен быть вменяемый!

image

Создание функции yan(). Первое обращение к функции вызовет команду find(), последующие обращения вызовут click().

image

Через диалоговое окно задаем количество циклов.

image

функция try / except и какая она хорошая.

image

И в завершение бот по отсылке подарков друзьям (коих может быть 5к) в игре DOTD

Settings.MoveMouseDelay = 0.02  def f5():     while "f5":         click(Pattern("KyddinsmapsD-1.png").targetOffset(-41,0))         sleep(5)         if exists(Pattern("1344731699750.png").similar(0.90),10):             continue         else:             pass         try:             wait(Pattern("CLOSElah.png").similar(0.85),25)         except:             continue         try:             click(Pattern("CLOSElah.png").similar(0.85).targetOffset(1,-6))             dragDrop(Location(1430,388), Location(1431,435)) # 435             break         except:             pass def send_frend():     click(Location(849,495))     sleep(1)     click(Location(578,695))     sleep(1)  def pre_click_frend():     click(Location(713,300))     click(Location(713,315))  def click_frend():     click(Location(713,332))     click(Location(714,348))     click(Location(714,364))     click(Location(715,380))     click(Location(714,396))     click(Location(713,412))     click(Location(713,427))     click(Location(713,444))     click(Location(713,460))     click(Location(713,474))     click(Location(713,490))     click(Location(715,506))     click(Location(714,522))     click(Location(714,537))     click(Location(713,554))          click(Location(923,541)), click(Location(923,541)), click(Location(923,541)), click(Location(923,541)), click(Location(923,541)), click(Location(923,541)),      click(Location(923,541)), click(Location(923,541)), click(Location(923,541)), click(Location(923,541)), click(Location(923,541)), click(Location(923,541)),      click(Location(923,541)), click(Location(923,541))          sleep(1)     click(Location(713,288))     click(Location(713,304))     click(Location(713,320))     click(Location(713,336))     click(Location(713,352))     click(Location(713,368))     click(Location(713,384))     click(Location(713,400))     click(Location(713,416))     click(Location(713,432))     click(Location(713,448))     click(Location(713,464))     click(Location(713,480))     click(Location(713,496))     click(Location(713,512))     click(Location(713,528))     click(Location(713,544))          click(Location(923,541)), click(Location(923,541)), click(Location(923,541)), click(Location(923,541)), click(Location(923,541)), click(Location(923,541)),      click(Location(923,541)), click(Location(923,541)), click(Location(923,541)), click(Location(923,541)), click(Location(923,541)), click(Location(923,541)),      click(Location(923,541))          sleep(1)     click(Location(713,300)),     click(Location(713,315))     click(Location(713,332))     click(Location(714,348))     click(Location(714,364))     click(Location(715,380))     click(Location(714,396))     click(Location(713,412))     click(Location(713,427))     click(Location(713,444))     click(Location(713,460))     click(Location(713,474))     click(Location(713,490))     click(Location(715,506))     click(Location(714,522))     click(Location(714,537))     sleep(1)  def send_fb():     click(Location(756,760))     sleep(2)     try:         click(Pattern("0TIIp3BHTb33.png").targetOffset(-2,1))     except:         pass  def off (event):          popup("The program is completed.\nCreator of this miracle: Grumo Van Blum.\nIf you have questions about using this program, please contact us by e-mail: grumovanblum@gmail.com\nGood Luck 8c)")     exit()   popup("If you want to stop the script, press: 'Ctrl' + 'Alt' + 'Space'")  Env.addHotkey(Key.SPACE, KeyModifier.ALT+KeyModifier.CTRL, off)  click(Pattern("1344836792562.png").similar(0.88)) n = 0 n = int(input("How many cycles you want to run?"))    while n > 0:     f5()     while "cycle":         if n == 0:             break         else:                          send_frend()             if exists(Pattern("Jd.png").similar(0.96),1):                 popup("Friends come to an end :)")                 n=0                 continue             else:                 pre_click_frend()                 sleep(1)                 if exists(Pattern("Youcanontysd.png").similar(0.95),1):                     f5()                     send_frend()                     pre_click_frend()                 else:                     pass             click_frend()             send_fb()             n -= 1             if n == 0:                 break             else:                 sleep(3)   

И видео о том как он работает (снимал в режиме отладки).

Используемые полезности

Alt+Shift+c остановит исполнение скрипта и вернёт IDE.

Выставляем время перемещения курсора:

Settings.MoveMouseDelay = 0.02   

Присваиваем сочетаниям клавиш какое либо событие:

def off (event):     exit() Env.addHotkey(Key.SPACE, KeyModifier.ALT+KeyModifier.CTRL, off) 

Вызов инициируемого диалогового окна:

n = int(input("А сколько раз будем проверять?")) 

Бездействие в 1 сек:

sleep(1) 

Если у вас после вставки скопированного текста код паттерна или региона заменился на картинку просто нажмите 1 или 2 раза сочетание клавиш Ctrl+z.
image

Это ещё далеко не всё и будет обязательно ещё. Но на данном этапе считаю, что основную идею я выразил.
Буду рад фидбэку.
Если есть вопросы по Sikuli, то пишите.

Следующим разом скорее всего расскажу как Sikuli научить распознавать текст и записывать лог ошибок в отдельный файл.

Спасибо за внимание.

ссылка на оригинал статьи http://habrahabr.ru/post/163883/


Комментарии

Один комментарий на ««Подробнее о Sikuli в автоматизации тестирования»»

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *