SikuliX - кросс-платформенная визуальная среда создания сценариев-скриптов. При помощи этих скриптов можно взаимодействовать с любыми интерфейсами, отображаемым на мониторе. Например, следить за изображением с вебкамерами, программировать поведение игровых ботов, серфить в интернете и, конечно, тестировать любые интерфейсы любых программ.
Сценарии-скрипты могут быть написаны на Python, Jython, Ruby. Но не стоит пугаться, если вы не знаете этих языков. При помощи SikuliX IDE вы сможете создать сценарий просто накликав его мышкой, чем мы и займемся.
Главное, что надо запомнить: Сикули - это просто.
Зачем SikuliX нужен программисту 1С
В платформе 8.3 появился функционал клиента тестирования, который позволяет проверить очень многое. По сути можно имитировать поведение пользователя.
Однако, если у вас 8.2 - вам не доступен этот функционал. Протестировать интерфейс вы сможете только при помощи сторонних программных средств. И здесь есть из чего выбрать.
Что же можно использовать?
- AutoIt - целый язык для автоматизации. AutoIt использует симуляцию нажатия клавиш, движений мыши и манипуляции с окнами, элементами управления. Это позволяет автоматизировать задачи пользователя Windows, обойдя нехватку подобного функционала в других языках программирования и в 1С 8.2 в том числе.
- AutoHotkey - аналогичная вышеназванной программа для написания макросов по автоматизации действий. Пожалуй, AHK даже более известен, в сравнении с AutoIt.
Из плюсов подобного ПО - можно сделать все, что хочешь. Но минусы перевешивают. Как человек, написавший не одно приложение на AutoIt могу констатировать: процесс разработки не быстрый, отладка своеобразна, реализация может зависеть от разрядности системы, имеются нюансы, связанные с ОС.
Количество кода, требующегося для решения нашей задачи (напомню, это тестирование интерфейсов): несколько десятков строк.
И все-таки Sikuli
После беглого знакомства с SikuliX для меня стали очевидны следующие преимущества этого продукта:
- Сценарий тестирования накликивается мышкой
- Причем накликивается очень быстро
- Отладка интуитивно понятна, не вызывает вопросов
- Результаты тестирования можно встраивать в существующие фреймворки тестирования (в нашем примере это будет xUnitFor1C)
- Можно интегрировать в сборочную линию
- Осваивается очень быстро
Установка SikuliX
Важное вступление!
1. С кириллицей у меня SikuliX подружить так и не получилось. Поэтому все имена, пути и т.д. - только латиница.
2. Отдельной разговор про имя пользователя. Библиотеки сикули устанавливаются в папку c:\Users\<ИмяПользователя>\AppData\Roaming\Sikulix\. Если имя пользователь, под которым планируется работа набран в кириллице - сикули не встанет. Но выход есть: можно сменить название папки (но не самой учетки). Об этом будет дальше.
3. Регистр в именах скриптов важен 1С.sikuli и 1с.sikuli - два разных скрипта, пусть у вас и Windows
4. Все выполнялось на "железном" компьютере с windows 7(х64), платформой 8.2.19.130, 8.2.19.83.
SikuliX - набор java-скриптов и библиотек. Для инсталляции нам потребуется еще и JAVA. Минимальные требования к Java согласно сайту разработчиков (от декабря 2017) http://sikulix.com/quickstart/ это версия 7 (JRE или JDK). Думаю, у большинства уже все установлено. Проверить версию можно простой командой:
Последний стабильный релиз Сикули можно взять отсюда: https://launchpad.net/sikuli/sikulix/1.1.1
Хотя лично я пользовался последними ночными версиями сборки, которые взял из девелопмента: https://raiman.github.io/SikuliX-2014/nightly.html (там есть ссылочка с jar)
У SikuliX нетривиальный инсталлятор. Качаем jar-файл, перемещаем его в папку, где планируете разместить SikuliX. У меня это, как видим, C:\SikuliX (диск и папка не играют роли). Начинаем установку командой:
java -jar sikulixsetup-1.1.2-20171218.172518-66-forsetup.jar
В вашем случае, имя файла будет другое.
Установщик начинает работу и предлагает выбрать один из вариантов. Выбираем как на скриншоте первый пункт, который проинсталлирует нам SikuliX вместе с его IDE:
Далее продолжаем инсталляцию поддакивая установщику:
И только в одном месте мы скажем нет. Дело в том, что на этапе установки Jython 2.7.0 скрипт так и не захотел запускаться и пришлось переинсталлировать Сикули. Поэтому на этом этапе отвечаем "NO" и устанавливаем Jython 2.5.4:
Кстати, если что-то пошло не так можно все пересоздать. Для этого удаляем все из установочной директории и повторяем установку как надо.
Если установка прошла успешно должно появиться окошко вида:
Если его нет, значит что-то сделано не так. Обратите внимание на кириллицу, Jython, перечитайте эту инструкцию по установке сначала. И переустановите Sikuli.
Наш первый Hello World
Запустим Sikuli IDE. Для этого выполним команду (можно ее вывести в ярлыки):
runsikulix.cmd
Запускается среда разработки. Выглядит довольно просто. Сюда можно кодить в Pyton-е. Но мы хотим быстрого старта и программирования мышкой. Начнем.
Программируем мышкой
Давайте заставим Сикули создать новый текстовый документ в 1С.
Для начала запустим 1С в режиме предприятия. Напомню, у меня это 8.2. Конечно, по-честному, нам надо создать скрипт, который сам запускает 1С, но это будет позже.
Итак, 1С-ка запущена. У меня это голая конфигурация без всего.
В Сикули кликаем на команду click и в рабочую область попадает новая команда:
Жмем на значок фотокамеры в этой команде и Сикули предлагает нам выбрать область, на которую нужно кликнуть. Мы хотим кликнуть на пиктограмму нового документа. Выделяем область с пиктограмкой:
Тут сразу возникает вопрос, почему такая большая область. Может нужно выбрать только сам значок? Более большая область позволяет Сикули выбрать именно стандартную панель. Вдруг на мониторе сейчас есть другое приложение с аналогичной иконкой. Или может быть такой значок есть на форме ранее открытой в 1С.
Вот, что у нас получилось:
Давайте сразу попробуем выполнить этот скрипт и нажмем на кнопку "Выполнить". Естественно, нам предложат сохранить нашу работу, согласимся:
Пронаблюдав выполнение скрипты мы увидим, что клик попадает в центр (у меня получается в пункт меню "Правка"). Скорректируем нажатие именно на значок. Для этого кликнем на нашу картинку в Сикули и откроется окно "Настройка шаблонов"
Перейдем на закладку Смещение цели и укажем нужный нам значок, кликнув по нему. Видим, что перекрестие из центра картинки сместилось на центр значка "Новый документ", жмем "Ок":
Выполним наш скрипт. Теперь все отлично, открылось окошко выбора типа нового документа:
Если бы нас интересовала графическая схема, можно было бы аналогичным способом выбрать этот пункт, но нам нужен Текстовый документ, а он уже выбран. Можем нажать на кнопку ОК, или нажать Enter на клавиатуре. Выполним последнее, ибо это проще. Введем две команды:
sleep(1) позволит сделать секундную паузу, чтобы окно успело открыться перед тем, как мы пошлем "в него" наш Enter.
type(Key.ENTER) - как раз передает Enter.
И финальный аккорд - вывод нашего "Hello, World!"
Здесь как мы видим команда Paste, а не Type. Почему? Потому что Sikuli при помощи этой команды может ввести только латиницу. А вот команда Paste вставит нужную нам строку в любой кодировке.
Вот как это работает
Все так просто! Давайте сделаем настоящий тест.
Тестируем интерфейс формы
Итак, давайте протестируем небольшой функционал. Добавим справочник с парой реквизитов и форму элемента.
По условию выдуманного техзадания при изменении содержимого Реквизита1 в окно сообщений должна выводиться фраза "Шеф, все пропало" и Реквизит2 становится невидимым.
Реализация функционала в модуле формы будет совсем простой:
Процедура Реквизит1ПриИзменении(Элемент)
Сообщить("Шеф, все пропало");
ЭлементыФормы.Реквизит2.Видимость=Ложь;
КонецПроцедуры
При реализации теперь не буду тщательно детализировать каждый чих, лучше обильно откомментирую код.
Сценарий у меня получился вот таким. Все прекрасно работает в Sikuli IDE (но все-таки это еще не финальная версия)
(Полный текст сценария размещен в исходниках в конце статьи)
Про ошибки в Sikuli IDE и логи
Кстати, совсем забыл про работу с ошибками. Вы, наверняка, уже наделали ошибок в своих скриптах и получили красные ромбики. Тут все красиво и прозрачно. Если что-то пошло не так, то сообщение проиллюстрирует проблему:
Лог показывает всю последовательность действий. Что у Sikuli получилось, что нет. Строки с ошибками нас будут интересовать на этапе "разбора полетов" и тут нам поможет правильное именование наших картинок.
Да-да, картинки по которым ходит/кликает Сикули можно переименовывать. Но только не забываем, что только в латиницу.
Согласитесь, что фраза
FindFailed: soobshenie_pro_Shefa.png: (113x17) in S(0)[0,0 1920x1080] E:Y, T:3,0
выглядит понятнее стандартного сообщения:
FindFailed: 1514017498867.png: (113x17) in S(0)[0,0 1920x1080] E:Y, T:3,0
Возможно, вы сразу догадаетесь, что нужно сделать не прибегая к IDE.
Автоматизируем запуск наших Sikuli-сценарии
До этого момента мы тестировали все "руками" в Sikuli IDE. Настало время автоматизировать наше тестирование интерфейса. Давайте создадим скрипт, который при выполнении сделает за нас все: запустит 1С-ку, прогонит сценарий, сохранит результаты для последующего анализа, и закроет сеанс.
Варианты скриптов могут быть разными, можно написать на чем удобно вам: bat-файл, onescript, powershell-скрипт.
Я сделаю bat-файл. Просто потому что его использовал и писал любой из нас. Никаких преимуществ перед другими способами он не имеет.
Если вы используете onescript, то лучше попрактиковаться в нем. Тем более, что у него есть возможность удалить запущенный процесс, если что-то пойдет не так. Под onescript есть библиотеки, которые позволяют настроить запуск 1С-ки, не морочась с путями и т.д.
Итак, чтобы не усложнять, все-таки сейчас у нас будет bat-файл.
Сам запускающий батник имеет вид:
Сначала стартует 1С-ка. Далее поочередно запускаются jar-файлы со сценариями тестов. Конечно, это место нужно улучшить, получив все названия сценариев из самой папки, но пока не хочется усложнять восприятие.
Последняя строка - завершение работы самой 1С причем через Sikuli.
Все скрипты пишут в файл .log в собственную папку Sikuli-скрипта. Это важно: по содержимому этого файла мы потом определим, чем все закончилось.
Сам скрипт Sikuli чуть поправлен. Здесь появились чудо-конструкции с исполнением кода в попытке и повторное использование сценария закрытия всех окон.
Попытка необходима для того, чтобы выполнение bat-скрипта не прерывалось, даже если что-то в сценарии пойдет не так - элементарно он упадет.
Закрытие окон необходимо для того, чтобы "понаоткрытое" другими сценариями не мешало выполниться текущему sikuli-скрипту.
Простейший отчет по тестированию
Все запускается, выполняется, открывается и успешно закрывается. А где результат? А результаты в файлах .log. Дополним наш скрипт созданием простейшего файла-отчета.
Для этого создадим простейшую обработку 1С, которая проинспектирует логи и создаст файл отчета:
Процедура ПриОткрытии()
Попытка
СформироватьОтчетОТестированииИнтерфейса();
Исключение
ЗаписьЖурналаРегистрации("Ошибка записи отчета о тестировании интерфейса",УровеньЖурналаРегистрации.Ошибка,ОписаниеОшибки());
КонецПопытки;
ЗавершитьРаботуСистемы(Истина);
КонецПроцедуры
Процедура СформироватьОтчетОТестированииИнтерфейса()
МассивПараметров = РазложитьСтрокуВМассивПодстрок_(ПараметрЗапуска,";");
Если НЕ МассивПараметров.Количество()=2 Тогда
Возврат
КонецЕсли;
ПутьККаталогамСикули = МассивПараметров[0];
ПутьКФайлуОтчета = МассивПараметров[1];
Текст = новый ТекстовыйДокумент;
Текст.ДобавитьСтроку(Формат(ТекущаяДата(),"ДЛФ=DT"));
МассивЛогФайлов = НайтиФайлы(ПутьККаталогамСикули,".log",Истина);
Для каждого ФайлЛога Из МассивЛогФайлов Цикл
ПутьККаталогу = ФайлЛога.Путь;
ЕстьОшибка = ?(ВЛогеЕстьОшибка(ФайлЛога.ПолноеИмя),"OK","error");
Текст.ДобавитьСтроку(ПутьККаталогу+": "+ЕстьОшибка);
КонецЦикла;
Текст.Записать(ПутьКФайлуОтчета,КодировкаТекста.ANSI);
КонецПроцедуры
Функция ВЛогеЕстьОшибка(ПутьКФайлу)
Текст = новый ЧтениеТекста(ПутьКФайлу);
Строка = Текст.Прочитать();
Если Найти(нРег(Строка),"[error]")>0 Тогда
Возврат Ложь;
Иначе
Возврат Истина;
КонецЕсли;
КонецФункции
Функция РазложитьСтрокуВМассивПодстрок_(Знач Строка, Знач Разделитель = ";") Экспорт
Результат = Новый Массив;
Позиция = Найти(Строка, Разделитель);
Пока Позиция > 0 Цикл
Подстрока = Лев(Строка, Позиция - 1);
Если Не ПустаяСтрока(Подстрока) Тогда
Результат.Добавить(Подстрока);
КонецЕсли;
Строка = Сред(Строка, Позиция + СтрДлина(Разделитель));
Позиция = Найти(Строка, Разделитель);
КонецЦикла;
Если Не ПустаяСтрока(Строка) Тогда
Результат.Добавить(Строка);
КонецЕсли;
Возврат Результат;
КонецФункции
Дополним наш bat-ник еще одной строчкой.
rem Создаем простой отчет
%exe1cv8% ENTERPRISE /IBNAME "Тестовая82" /UseHwLisenses /Lru /VLru /DisplayAllFunctions /O Normal /Execute %ProjectPath%СоздатьОтчетИЗакрыть1С.epf /C"%ProjectPath%;%ProjectPath%\otchet.txt"
Теперь мы получаем вот такой простенький отчет по тестированию интерфейса:
Его можно смело отправлять на почту ответственным, дополнив эту обработку функционалом отправки почты.
Красивый отчет по тестированию
Но хочется большего. Точнее большого, красивого и подробного. Например, в виде Allure-report как на картинке:
Для получения красивого отчета можно воспользоваться функционалом фреймворков Vanessa-Behavior или XUnitFor1C. Для моей реализации выберу последний.
Создам простой тест-обработку. Для тех, кто работал с xUnit ничего нового – это стандартный текст обработки с необходимыми процедурами для запуска фреймворка. Вся «соль» содержится в последней однобуквенной процедуре. Сам модуль объекта:
Перем КонтекстЯдра;
Перем ТестируемаяФорма;
Перем НужноИсключениеЕслиНеНайденоДокументов;
//{ интерфейс тестирования
// директива препроцессора нужна для исключения ошибки загрузки в толстом клиенте управляемого приложения
#Если ТолстыйКлиентОбычноеПриложение Тогда
Процедура Инициализация(КонтекстЯдраПараметр) Экспорт
КонтекстЯдра = КонтекстЯдраПараметр;
КонецПроцедуры
Процедура ПередЗапускомТеста() Экспорт
НачатьТранзакцию();
КонецПроцедуры
Процедура ПослеЗапускаТеста() Экспорт
Если ТранзакцияАктивна() Тогда
ОтменитьТранзакцию();
КонецЕсли;
КонецПроцедуры
Процедура ЗаполнитьНаборТестов(НаборТестов) Экспорт
НаборТестов.СлучайныйПорядокВыполнения();
НаборТестов.Добавить("_");
КонецПроцедуры
Процедура _() Экспорт
Попытка
ПутьКЭтойОбработке = КонтекстЯдра.ТекущийКонтейнер.Строки[0].Путь;
Исключение
ВызватьИсключение "Не нашли путь к обработке в КонтекстЯдра.ТекущийКонтейнер.Строки[0].Путь";
КонецПопытки;
Ф = новый Файл(ПутьКЭтойОбработке);
ПутьКЛогу = Ф.Путь+".log";
Ф = новый Файл(ПутьКЛогу);
Если НЕ Ф.Существует() Тогда
ВызватьИсключение "Не найден лог тестирования интерфейса";
КонецЕсли;
Текст = новый ЧтениеТекста(ПутьКЛогу);
Прочитанное = Текст.Прочитать();
Если Найти(Прочитанное,"[error]")>0 Тогда
ВызватьИсключение Прочитанное;
КонецЕсли;
//Сообщить(КонтекстЯдра.Путь);
КонецПроцедуры
#КонецЕсли
Сохраняем тест с красноречивым именем, которое расскажет благодарным потомкам, что же все-таки тут проверялось. Кладем этот файл в папку к Sikuli-скрипту.
Если у нас несколько тестов, то копируем этот же файл в другие папки, только переименовывая его. Этот копи-паст отлично работает в дженкинсе (см. первый скриншот с Allure-отчетом).
Стандартно запускаем xUnitFor1C, указывает корневую папку с нашими sikuli-скриптами. хUnitFor1C сам прочтет все тесты, которые ему предстоит выполнить:
После запуска часть тестов позеленеет, часть покраснеет, а в перечне ошибок будут как раз содержимое наших файлов .log. Посмотрев в ошибки мы скажем себе спасибо за то, что понятно называли картинки и нам, скорее всего, не придется долго воспроизводить проблему (на скриншоте я как раз этим моментом пренебрег):
Собственно, наша задача решена. Техзадание выполнено, протестировано, отчет сформирован. Уже в этом виде решение приобрело законченный вид.
Пойдем чуть дальше. Типа бонус!
Добавляем красивый отчет в сборочную линию
Скрипт тестирования интерфейса у нас есть, дело за малым - интегрировать запуск XUnit в нашу сборочную линию, вместе с генерацией отчета. Про запуск xUnitFor1C из командной строки можно прочитать на вики xUnitFor1C.
Моя итоговая строка запуска выглядит вот так:
chcp 65001
set runsikulicmd=c:\sikuliX\runsikulix.cmd
set ProjectPath=c:\test_sikuli\sikuli\
set exe1cv8="C:\Program Files (x86)\1cv82\8.2.19.83\bin\1cv8.exe"
set ConnectionString=/F"C:\Тестовая82_Инфостарт"
set TestTools=C:\TestTools\xUnitFor1C_82
rem запуск 1С, в котором будем тестировать интерфейс
start "1c" /MAX %exe1cv8% ENTERPRISE %ConnectionString% /UseHwLisenses /Lru /VLru /DisplayAllFunctions /O Normal
rem поочередный запуск всех тестов
rem Тест, который пройдет
set TECNAME=VsePropalo2.sikuli\
del /F %ProjectPath%%TECNAME%.log
call %runsikulicmd% -r %ProjectPath%%TECNAME% > %ProjectPath%%TECNAME%.log
rem Тест, который завалится
set TECNAME=No.sikuli\
del /F %ProjectPath%%TECNAME%.log
call %runsikulicmd% -r %ProjectPath%%TECNAME% > %ProjectPath%%TECNAME%.log
rem Закрываем 1с
set TECNAME=close1c.sikuli\
call %runsikulicmd% -r %ProjectPath%%TECNAME% > %ProjectPath%%TECNAME%.log
rem Создаем папку под отчеты
set TESTReportFOLDER="%WORKSPACE%\allure-results\"
RMDIR /S /Q %TESTReportFOLDER%
MD %TESTReportFOLDER%
rem Создаем Аллюр-отчет при помощи xUnitFor1C
%exe1cv8% ENTERPRISE %ConnectionString% /UseHwLisenses /DisplayAllFunctions /O Normal /Execute "%TestTools%\xddTestRunner.epf" /C "xddRun ЗагрузчикКаталога ""%ProjectPath%""; xddReport ГенераторОтчетаAllureXML ""%WORKSPACE%\allure-results\report_ordinary.xml""; xddShutdown;"
Внимание, это уже не запуск на моем компьютере, это уже bat-ник в Jenkins. Я сознательно опускаю детали установки Allure локально. Он локально-то по большому счету и не нужен. У меня, например, не стоит. А вот на сборочной линии мы активно пользуемся его наглядным функционалом.
Про установку Allure, Jenkins и прочего инструментария есть статьи на инфостарте и других ресурсах. Считаю, что тема слишком объемна и бессмысленно описывать это здесь.
Все скрипты и bat-файлы выкладываю в одном архиве, так как финальные тексты могут несколько отличаться от ранних скриншотов для статьи.
Итоги
SikuliX – это мощный и удобный инструмент для тестирования интерфейса. Наверняка, с его помощью можно решить еще не одну задачу. Программа проста, неприхотлива, имеет запуск из командной строки. Из зависимостей только Java (напоминаю, Sikuli – кроссплатформенна).
Что еще не сказано. Примечания
- На разных скриншотах фигурируют разные пути C:\SikuliX, D:\SikuliX – не обращайте внимание, часть картинок с Jenkins, часть с собственного компьютера, никакой магии.
- Для простоты я не использовал никакие логины-пароли и не проводил проверку под всякими ролями. Это остается за рамками данной статьи, но сложностей здесь немного.
- Глядя на итоговый скрипт для Jenkins можно похихикать над «сборочной линией» - ее тут, конечно, нет.
- В моем случае slave-нода запускается с экранным разрешением 1024х768. Запуск осуществляется под пользователем, для которого настроен автологин. И это следует учесть при создании Sikuli-сценариев. Возможно, есть более удачный способ запуска. Как проверить разрешение – в отчете есть информация на эту тему:
- Пока работает Sikuli-скрипт - другие задачи с всплывающими окнами могут нарушать работу сценариев. Решение тривиальное - ничего больше не запускать во время тестирования или выделить отдельную машину.
- Sikuli - в переводе с древнего индейского языка означает «глаз бога». Ох, уж эти разработчики и кулхацкеры...
Ссылки
Традиционно даю ссылки на полезную информацию для решивших пойти sikuli-путем:
- Сайт проекта SikuliX: http://sikulix.com/
- FAQ по сикули на сайте разработчиков: https://answers.launchpad.net/sikuli/+faqs
- Кучка sikuli-скриптов внутри Vanessa-Behavior - рекомендую подсматривать в своих поделках. И спасибо Леониду Паутову.
- xUnitFor1C и статья на инфостарте xUnitFor1C - набор инструментов для выполнения тестирования (модульного/юнит, приемочного, сценарного для 1С 8.3, интеграционного)
- Vanessa-Behavior и хорошая статья зачем он нужен: //infostart.ru/public/545730/
- Для тех, кто хочет узнать больше про страшные слова BDD, Jenkins, VB, onescript, xunit, docker рекомендую курсы Часть 1 и Часть 2
- Autoit - еще одна возможная среда для тестирования
- Шильдик - удобная идентификация конфигураторов (как пример поделки на AutoIt)
Вроде все... Спасибо всем осилившим.