Бер 192016
 

Видеозапись выполнения тестов Selenium

Есть ли смысл создавать видеозапись процесса тестирования? Вопрос спорный, но думаю, что каждый из вас хоть раз сталкивался с нестабильно работающими тестами, когда один и тот же тест через раз завершается неудачей без видимых причин. В такой ситуации иногда практически невозможно разобраться в чем конкретно заключалась ошибка.
Записывать выполнение тестов полностью или только особо критические моменты — это решение зависит от Ваших предпочтений и свободного дискового пространства :). Главное, что такая возможность есть и она реализуется относительно несложно.

Для видеозаписи нам понадобится Monte Media Library Screen Recorder. К сожалению, этой библиотеки нет в Maven репозитории, поэтому необходимый нам MonteScreenRecorder.jar нужно скачать на официальном сайте. На момент написания статьи последняя версия рекордера была 0.7.7. Теперь загруженный jar файл можно добавить в Build Path проекта или, если Вы используете Maven, выполнить следующие шаги:

1. Установить библиотеку в локальный репозиторий, из командной строки:

mvn install:install-file -Dfile=MonteScreenRecorder.jar -DgroupId=org.monte 
              -DartifactId=monte-screen-recorder -Dversion=0.7.7 -Dpackaging=jar

-Dfile=абсолютный или относительный путь к файлу

2. Добавить зависимость в pom.xml

org.monte
			monte-screen-recorder
			0.7.7

Сперва создадим собственный класс, который будет вызывать Monte ScreenRecorder и выполнять все необходимые настройки видеозаписи:

import static org.monte.media.FormatKeys.*;
import static org.monte.media.VideoFormatKeys.*;

import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;

import org.monte.media.Format;
import org.monte.media.FormatKeys.MediaType;
import org.monte.media.math.Rational;
import org.monte.screenrecorder.ScreenRecorder;

public class VideoRecorder {

    private ScreenRecorder screenRecorder;

    public void startRecording() {

        try {
            GraphicsConfiguration gc = GraphicsEnvironment
		        .getLocalGraphicsEnvironment().getDefaultScreenDevice()
		        .getDefaultConfiguration();

            this.screenRecorder = new ScreenRecorder(gc, 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);

            this.screenRecorder.start();

        } catch (Exception e) {
            System.out.println(e);
        }
    }

    public void stopRecording() {
        try {
            this.screenRecorder.stop();
        } catch (Exception e) {
            System.out.println(e);
        }
    }

}

Обратите внимание, все действия в методах заключены в блок try … catch для того, чтобы случайно возникшие ошибки видеозаписи не повлияли на дальнейшее выполнение тестов. По умолчанию, ScreenRecorder делает запись всего экрана и сохраняет файл в соответствующую видео директорию ОС ( Windows — Libraries\Videos, Mac — Movies и т.д.) со стандартным именем, например, «ScreenRecording 2013-11-08 at 18.09.00.avi».

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

import static org.monte.media.FormatKeys.*;
import static org.monte.media.VideoFormatKeys.*;

import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.awt.Rectangle;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.monte.media.Format;
import org.monte.media.FormatKeys.MediaType;
import org.monte.media.math.Rational;
import org.monte.screenrecorder.ScreenRecorder;
import org.openqa.selenium.Dimension;
import org.openqa.selenium.Point;
import org.openqa.selenium.WebDriver;

public class VideoRecorder {

    private final String RECORD_DIRECTORY = "D:\\Projects\\temp\\";

    private ScreenRecorder screenRecorder;

    public void startRecording(WebDriver driver) {

        try {
            GraphicsConfiguration gc = GraphicsEnvironment
		        .getLocalGraphicsEnvironment().getDefaultScreenDevice()
		        .getDefaultConfiguration();

            File dir = new File(RECORD_DIRECTORY);

            // записываем только область окна драйвера
            // для уменьшения размера видео файла
            Point point = driver.manage().window().getPosition();
            Dimension dimension = driver.manage().window().getSize();

            Rectangle rectangle = new Rectangle(point.x, point.y,
		        dimension.width, dimension.height);

            this.screenRecorder = new ScreenRecorder(gc, rectangle, 
		        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,
		        dir);

            this.screenRecorder.start();

        } catch (Exception e) {
            System.out.println(e);
        }
    }

    public void stopRecording(String recordName) {

        try {
            this.screenRecorder.stop();

            // переименовываем созданный .avi файл,
            if (recordName != null) {
                SimpleDateFormat dateFormat = new SimpleDateFormat(
			        "yyyy-MM-dd HH.mm.ss");
                File newFileName = new File(String.format("%s%s %s.avi",
			        RECORD_DIRECTORY, recordName,
			        dateFormat.format(new Date())));

                this.screenRecorder.getCreatedMovieFiles().get(0)
			        .renameTo(newFileName);
            }
        } catch (Exception e) {
            System.out.println(e);
        }
    }

}

Пример использования класса VideoRecorder в тесте:

public class RecordedTest {

    private WebDriver driver;

    @Before
    public void setUpDriver() {
        driver = new FirefoxDriver();
    }

    @Test
    public void testRecordFirefox() throws Exception {

        driver.get("http://www.google.com.ua");

        // начинаем запись
        VideoRecorder recorder = new VideoRecorder();
        recorder.startRecording(driver);

        try {
            // критическая секция
            WebElement element = driver.findElement(By.name("q"));
            element.sendKeys("Cheese!");
            element.submit();
        } finally {
            // останавливаем запись
            recorder.stopRecording("Google send Cheese");
        }

    }

    @After
    public void closeDriver() {
        driver.quit();
    }
}

И снова использование блока try … catch, в этом случае его finally секции, для того, чтобы корректно завершить процесс видеозаписи даже в случае возникновения ошибок при выполнении теста.

Так как запись активности осуществляется непосредственно на экране, то такой способ не может быть использован при параллельном запуске тестов, а также с RemoteWebDriver или Grid.