Selenium: Снятие скриншотов веб-страницы целиком

Эта статья завершает серию, посвящённую снятию скриншотов при выполнении автотестов, разработанных с использованием Selenium и TestNG.

Предыдущие статьи:

Здесь речь пойдёт о снятии скриншотов страницы целиком – не только видимой её части, но и тех частей, которые можно увидеть лишь проскроллировав окно браузера. Я расскажу про два способа снятия таких “пейджшотов”:

  • средствами только Selenium;
  • при помощи AutoIt и какой-нибудь внешней утилиты снятия скриншотов, умеющей автоматически скроллировать окна.

Первый способ работает как при локальном, так и при удалённом запуске тестов, но поддерживаются только браузеры Internet Explorer и FireFox. Второй способ пригоден только при локальном запуске тестов, а поддержка браузеров определяется возможностями используемой внешней утилиты-скриншотера.

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

Всё нижеописанное в виде исходного кода на языке Java вы сможете найти в приложенном файле, ссылка на который находится в конце статьи.

Конфигурирование скриншотера

Если вы пользуетесь связкой TestNG + Selenium, вы наверняка знаете, что TestNG позволяет задавать параметры в конфигурационном файле, где описываются тестовые наборы (этот файл обычно называется testng.xml). Однако я не очень люблю этот способ (причины этой нелюбви оставим пока в стороне, про это будет отдельная статья), поэтому в файле testng.xml я предпочитаю делать ссылку на отдельный конфигурационный файл, в котором уже описываются все параметры.

Именно так мы мы поступим и в этом случае. В файле testng.xml будет добавлена вот такая ссылка:

<parameter name="screenshoter.properties" value="/screenshoter.properties" />

Обратите внимание на то, что ссылка начинается со слеша, это ссылка на Java-ресурс, её поиск будет производиться во всех директориях и файлах, которые включены в CLASSPATH.

А вот что находится в файле screenshoter.properties:

mode = autoit

selenium.entirePage = true
selenium.background = white

autoit.path = C:/Program Files/AutoIt3/AutoIt3.exe
autoit.script = take_screenshot.au3

Первая строчка – указание механизма снятия скриншотов: либо средствами Selenium, либо при помощи AutoIt. А далее настраиваются параметры для каждого из механизмов. Назначение параметров, надеюсь, интуитивно понятно из их названия, но тем не менее, про них будет чуть подробнее написано ниже в соответствующих разделах.

В классе TestNgHelper, который находится в приложенном к этой статье файле, есть два интересных метода – configureScreenshoter, который инициализирует скриншотер: в зависимости от значения параметра mode создаётся либо SeleniumScreenshoter, либо AutoItScreenshoter, а затем этот скриншотер в методе setTestContext помещается в тестовый контекст, откуда он может быть извлечён любым тестом или листенером.

Да-да, скриншоты можно снимать и непосредственно в тестах, там, где вам это потребовалось, но про это я расскажу в отдельной статье, посвящённой инъекциям в TestNG.

Следует отметить, что теперь для автоматического снятия скриншотов при неуспешном завершении тестов нам достаточно иметь один единственный универсальный листенер ScreenshotListener, который будет использовать ранее сконфигурированный скриншотер, находящийся в тестовом контексте. Многочисленные реализации листенеров, которые я описывал во второй статье этой серии, были “расклонированы” исключительно для удобства объяснения.

Подключить этот листенер можно одним из трёх способов:

  • добавив тестовому классу аннотацию @Listeners({ScreenshotListener.class})
  • добавив в файл testng.xml инструкцию <listeners><listener class-name="ru.st.selenium.ScreenshotListener"></listener></listeners>
  • указав при запуске TestNG опцию -listener ru.st.selenium.ScreenshotListener

А теперь, когда я рассказал, как этим пользоваться, пришло время объяснить, когда оно работает, а когда нет.

Снятие скриншотов средствами Selenium

Класс SeleniumScreenshoter реализует наиболее универсальный способ снятия скриншотов средствами Selenium – он использует методы captureScreenshotAsString либо captureEntirePageScreenshotToString в зависимости от значения параметра selenium.entirePage. Если значение этого параметра установлено в false, делается снимок экрана, а если параметр имеет значение true, тогда Selenium делает попытку снять “пейджшот”, то есть получить изображение всей веб-страницы целиком, включая невидимые области, скрытые за границами окна браузера.

Этот способ не требует никаких дополнительных инструментов и утилит, работает как при локальном, так и при удалённом выполнении тестов. Казалось бы чего ещё желать. Однако не обошлось без большущей ложки дёгтя – снятие “пейджшотов” работает только в FireFox в режимах *firefox и *chrome и в Internet Explorer в режиме *iexploreproxy (а в IE9 мне не удалось заставить его работать даже в этом режиме). Иными словами, как раз в тех браузерах, где чаще всего сбоят тесты, мы и не имеем возможности снимать “пейджшоты”, приходится ограничиваться лишь видимой частью страницы.

Однако на свете существует великое множество инструментов для снятия скриншотов, которые либо поддерживают автоскроллирование, либо имеют функцию расширения окна за пределы экрана. И то и другое даёт возможность снимать “пейджшоты”. Но как прикрутить это к Selenium и TestNG? И вот тут приходит на помощь AutoIt и AutoItScreenshoter.

Снятие “пейджшотов” внешним инструментом

Чтобы использовать внешний инструмент для автоматического снятия скриншотов, надо его предварительно должным образом настроить, а также подготовить небольшой скрипт для инструмента AutoIt, который принимает на вход два параметра: 1) название окна браузера и 2) путь к файлу, в который необходимо сохранить снятый скриншот. Ссылку на этот скрипт следует прописать в конфигурационном файле в качестве значения параметра autoit.script, а также надо указать mode = autoit.

В приложенном файле (ищите в конце статьи) имеется достаточно универсальный скрипт take_screenshot.au3, который предполагает, что внешний скриншотер:

  • запускается по горячей клавише Ctrl-Alt-PrintScreen,
  • ожидает, пока пользователь кликнет в окно, с которого нужно снять скриншот,
  • делает снимок в соответствии с предварительно сделанными настройками,
  • выводит диалоговое окно для сохранения скриншота.

Я использовал этот скрипт без каких-либо изменений с самыми различными скриншотерами – SnagIt, HyperSnap, PicPick. Почему мне потребовались разные утилиты? Потому что они тоже не все одинаково хорошо работают с различными браузерами. Но об этом я расскажу как-нибудь в другой раз.

Разумеется, этот способ работает только при локальном запуске тестов. Но зато теперь мы имеем возможность выбирать из огромного числа инструментов снятия скриншотов, так что наверняка найдётся подходящий даже для самого капризного браузера.

Ах да, ну и конечно нужно ещё не забыть установить AutoIt :)

Ну вот и всё, что я хотел рассказать про снятие скриншотов при выполнении тестов с использованием Selenium и TestNG. Осталось лишь дать ссылку на файл, который содержит исходный код всего этого хозяйства: SeleniumScreenshots3.zip