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

Я уже давно не брал в руки шашки и Selenium, поэтому пришлось немного покопаться в интернете и поискать — что в этой ситуации делают умные люди. Решение, которое меня устроило в итоге, собрало несколько технологий: Java + Selenium + Junit + Allure + ffmpeg + VideoRecorder (by Pirogov). Но поскольку я все таки честно копался, пытаясь найти лучшее решение проблемы, то нашлось еще несколько альтернативных моему и более простых способов — как можно сделать слепок экрана.

Поскольку найденная информация, раскидана по всему интернету, то иметь некоторый сжатый конспект в одном месте было бы, считаю, неплохо. По сути статья получилась как небольшая вводная для новичков. Которые озабочены той же самой проблемой — посмотреть глазами, что было или чего не было, когда автотесты выкинули красный флаг.

Давайте посмотрим, что нам предлагают сдела��ь.

Как получить скриншот экрана


Самый первый вариант, который можно придумать для нашей проблемы — снимать скриншоты экрана. Т.е. подгадать момент, когда тест свалится, и получить картинку. Можно вообще на каждое действие снимать скриншот. Или снимать скриншот с некой периодичностью (например раз в полсекунды).

Способ 1. Selenium

Поскольку тесты многие пишутся на Selenium/WebDriver то было бы разумно использовать его методы. Например:

WebDriver driver = new FirefoxDriver(); driver.get("http://www.google.com/"); 
File scrFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(scrFile, new File("c:\\tmp\\screenshot.png"));

Способ 2. Selenide

Второй способ использовать обертки для Selenium, например Selenide. Этоn фреймворк упрощает работу с драйвером и кроме всего прочего делает скриншоты при возникновении ошибки автоматически и сам. По умолчанию скриншоты складываются в папку “test-result/reports”.

Способ 3. java.awt.Robot

Следующий способ — использовать вообще стандартный класс Java (с версии 1.3) для работы напрямую с операционной системой. Небольшой пример, как может выглядеть подобный код:

BufferedImage image = new Robot().createScreenCapture(new Rectangle(Toolkit.getDefaultToolkit().getScreenSize())); 
ImageIO.write(image, "png", new File("/screenshot.png"));

Способ 4. Использование внешних программ

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

Способ 5. Использовать облачные технологии

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

Как получить видео экрана


С видео — несколько сложнее. Нельзя просто так взять и снять видео. Нужно немного поплясать.

Есть два основных способа танцев:

  • Наделать скриншоты и конвертировать их в видео (далее способ 1)
  • Сразу снимать видео (далее способ 2 и 3)

Способ 1. Конвертация картинок в видео руками (на примере ffmpeg)

Для получения видео можно сделать скриншоты с периодичностью в полсекунды и потом свести их в одно видео. Например при помощи библиотеки ffmpeg (https://ffmpeg.org/)

Для файлов с расширенем PNG, расположенных в одном каталоге, команда может выглядеть так:

ffmpeg -framerate 1 -pattern_type glob -i '*.png' \ -c:v libx264 -r 30 -pix_fmt yuv420p out.mp4

Можно добавить автоматизации и, например, сделать скрипт который запускает подобную команду по окончании тестов.

Способ 2. Рекордер видео — Monte Screen Recorder

Другой способ создания видео — миновать этап создания скриншотов и использовать рекордеры сразу.

Первым, на который я наткнулся, был Monte Screen Recorder и ниже следует небольшой пример использования Java обертки для этого рекордера (https://github.com/stephenc/monte-screen-recorder):

 GraphicsConfiguration gc = GraphicsEnvironment
            .getLocalGraphicsEnvironment()
            .getDefaultScreenDevice()
            .getDefaultConfiguration(); 
         
    screenRecorder = new ScreenRecorder(gc,
            gc.getBounds(),
            new Format(MediaTypeKey, MediaType.FILE, MimeTypeKey, MIME_AVI),
            new Format(MediaTypeKey, MediaType.VIDEO, EncodingKey, ENCODING_AVI_TECHSMITH_SCREEN_CAPTURE,
                    CompressorNameKey, ENCODING_AVI_TECHSMITH_SCREEN_CAPTURE,
                    DepthKey, 24, FrameRateKey, Rational.valueOf(15),
                    QualityKey, 1.0f,
                    KeyFrameIntervalKey, 15 * 60),
            new Format(MediaTypeKey, MediaType.VIDEO, EncodingKey, "black", FrameRateKey, Rational.valueOf(30)),
            null,
            new File(targetFolder));
    screenRecorder.start();

Недостаток данного рекордера в том, что для просмотра видео вам понадобится установленный на компьютере кодек TSC (https://www.techsmith.com/products.html).

Способ 3. Рекордер — ffmpeg

Вторым рекордером на который я наткнулся, была наиболее известная и широко используемая библиотека ffmpeg. Я уже приводил пример ее использования для конвертации картинки в видео. Для библиотеки есть несколько оберток. В итоге я остановился на github.com/SergeyPirogov/video-recorder-java.

Привлекла меня эта библиотечка тем, что обновления достаточно новые — значит проект живой и можно надеяться, что баги будут исправятся оперативно. Кроме этого обертка написана специально в поддержку нашей проблемы — снимать видео, когда тесты свалились. Самый простой способ использования — Java аннотации Video(name = «second_test»)

Например:

   @Test
    @Video(name = "second_test")
    public void videoShouldHaveNameSecondTest(){
        Thread.sleep(1000);
        assertTrue(false);
    }

Главное нужно не забыть, что по умолчанию обертка использует кодек Monte, а не ffmpeg. Поэтому не забудьте переопределить формат видео в файле конфигурации (можно посмотреть как это делается на центральной Git странице проекта)

Выводов не будет. Для себя я выбрал VideoRecorder (by Pirogov), но без использования аннотаций, а напрямую используя классы позволяющие стартовать и останавливать съемку видео. В следующей заметке планирую расписать этот способ

Было бы нечестно не сослаться на страницы, с которых честно украден код в исследовательских конечно же целях:


P.S.: Если вдруг совершенно случайно у вас завалялись идеи что еще можно сделать — нижайшая просьба добавлять ссылками или текстом в комментариях. Спасибо.