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

Я уже давно не брал в руки шашки и 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.: Если вдруг совершенно случайно у вас завалялись идеи что еще можно сделать — нижайшая просьба добавлять ссылками или текстом в комментариях. Спасибо.