Видеозапись выполнения тестов 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.