Вступление
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», кстати не меняйте папку установки назначенную по умолчанию.
Если вдруг что не так, вот ссылочка для почитать.
Функционал и особенности.
Снимок экрана
Применяется для выделения определённой области экрана и последующем созданием паттерна
При нажатии на паттерн появится окно «Настройка шаблонов»
С вкладками всё примитивно и ясно. Единственное отмечу что на вкладке «смещение цели» целью является то место куда переместиться курсор и произведет клик/ввод. Причём место клика может лежать далеко за пределами паттерна.
Теперь о особенностях.
*****.png это название искомого рисунка который должен лежать в папке заранее сохраненного проекта.
similar = схожесть, где 1=100% (лучше не использовать ибо находит не всегда), а например 0,85 (через точку) = 85%, что на мой взгляд самое оптимальное значение.
targetOffset(x,y)) и тут важно что координаты «x» и «y» это смещение цели от центра паттерна.
Выделение области/wait()/Click()
Великолепная функция и что самое главное в крайней степени полезная.
Многие говорят что Sikuli плохо соображает в работе и ошибается ещё здорово. Я же с этим в корне не согласен и считаю, что грамотный подход значительно увеличивает производительность программы.
Эта функция задает активную область экрана.
в которой будет производиться поиск искомого паттерна.
Можно ещё и вот так:
Region(x,y,w,h).find(Pattern("*****.png".similar(0.85)targetOffset(x,y)))
Она крайне полезна если нам нужно чтобы скрипт реагировал на изменения оперативно, не тормозил систему.
Как пример:
из всего нашего большого экрана мы выбираем только небольшую область где каждый раз появляется заветная кнопочка.
Далее описываем что в этой области нам надо искать и что с этим потом делать.
Для того чтобы оптимизировать процесс нам нужно запустить этот скрипт и чтоб он за нас 1 раз совершил клик. После мы переходим на вкладку «Сообщение» где видим координаты клика.
Далее делаем цикл и и делаем клик по координатам (это при условии что кнопка всегда будет появляться в одном и том же месте).
Схожесть в поиске делаем около 70 процентов, быстрее найдёт, ожидание 999…
По итогу мы имеем практически моментальное срабатывание.
Find()
Функция find() ищет паттерн. Но вот зачем? Всё просто. Один раз нашел, а дальше он будет знать где находится найденный объект всегда. Как применить на практике:
Имеем много чего либо…
И нажимать это «что либо» программе придется долго и упорно…
Для того чтобы программа знала куда нажимать, нужно выставить targetOffset()
Повторяем для каждой цели, присваиваем переменные, оптимизируем если поле с множеством находится в одном и том же месте.
Далее мы можем найденные зоны использовать как хотим. Причём клик будет происходить без задержек на поиск и т.д.
Остальной функционал рассматривать не буду он примитивен и прост.
Примеры
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.
Это ещё далеко не всё и будет обязательно ещё. Но на данном этапе считаю, что основную идею я выразил.
Буду рад фидбэку.
Если есть вопросы по Sikuli, то пишите.
Следующим разом скорее всего расскажу как Sikuli научить распознавать текст и записывать лог ошибок в отдельный файл.
Спасибо за внимание.
ссылка на оригинал статьи http://habrahabr.ru/post/163883/
Добавить комментарий