Record videos of your UI tests by just putting a couple of annotations.

pom.xml
<dependency>
  <groupId>es.lnsd.videotape</groupId>
  <artifactId>videotape-testng<integration></artifactId>
  <version>3.0-SNAPSHOT</version>
  <scope>test</scope>
</dependency>
<dependency>
  <groupId>es.lnsd.videotape</groupId>
  <artifactId>videotape-backend-monte</artifactId>
  <version>3.0-SNAPSHOT</version>
  <scope>test</scope>
</dependency>
build.gradle
testImplementation group: 'es.lnsd.videotape', name: 'videotape-testng', version: '3.0-SNAPSHOT'
testRuntimeOnly group: 'es.lnsd.videotape', name: 'videotape-backend-monte', version: '3.0-SNAPSHOT'
ExampleTest.java
@Listeners(VideoListener.class)
public class TestNgVideoTest {

    @Test
    @Video
    public void shouldFailAndCreateRecordWithTestName() {
        Thread.sleep(1000);
        assert false;
    }

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

Currently, integrates with the following JVM test frameworks:

  • JUnit

  • JUnit 5

  • TestNG

And supports the following video recording backends:

  • Monte Media Library

  • FFMPEG

  • VLC

Test frameworks

Videotape library integrates with some of the most popular JVM test frameworks:

  • JUnit

  • JUnit 5

  • TestNG

JUnit

Videotape basically integrates with JUnit test framework as a rule:

Dependencies

pom.xml
<dependency>
  <groupId>es.lnsd.videotape</groupId>
  <artifactId>videotape-junit</artifactId>
  <version>3.0-SNAPSHOT</version>
</dependency>
build.gradle
testImplementation group: 'es.lnsd.videotape', name: 'videotape-junit', version: '3.0-SNAPSHOT'

Example code

JUnitVideoTest.java
import es.lnsd.videotape.core.annotations.Video;
import es.lnsd.videotape.junit4.VideoRule;
import org.junit.Rule;
import org.junit.Test;

import static junit.framework.Assert.assertTrue;

public class JUnitVideoTest {

    @Rule
    public VideoRule videoRule = new VideoRule();

    @Test
    @Video
    public void shouldFailAndCreateRecordWithTestName() {
        Thread.sleep(5000);
        assert false;
    }

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

JUnit 5

Dependencies

pom.xml
<dependency>
  <groupId>es.lnsd.videotape</groupId>
  <artifactId>videotape-junit5</artifactId>
  <version>3.0-SNAPSHOT</version>
</dependency>
build.gradle
testImplementation group: 'es.lnsd.videotape', name: 'videotape-junit5', version: '3.0-SNAPSHOT'

Example code

JUnit5VideoTest.java
import es.lnsd.videotape.junit5.Video;

public class JUnit5VideoTest {

    @Test
    @Video
    public void shouldFailAndCreateRecordWithTestName() {
        Thread.sleep(5000);
        assert false;
    }

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

TestNG

Dependencies

pom.xml
<dependency>
  <groupId>es.lnsd.videotape</groupId>
  <artifactId>videotape-testng</artifactId>
  <version>3.0-SNAPSHOT</version>
</dependency>
build.gradle
testImplementation group: 'es.lnsd.videotape', name: 'videotape-testng', version: '3.0-SNAPSHOT'

Example code

TestNgVideoTest.java
import es.lnsd.videotape.core.annotations.Video;
import es.lnsd.videotape.testng.VideoListener;
import org.testng.annotations.Listeners;
import org.testng.annotations.Test;

import static org.testng.Assert.assertTrue;

@Listeners(UniversalVideoListener.class)
public class TestNgVideoTest {

    @Test
    @Video
    public void shouldFailAndCreateRecordWithTestName() {
        Thread.sleep(1000);
        assert false;
    }

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

Recording backends

This library uses the java.utils.ServiceLoader plugins system to load dynamically from the classpath the video recording backend.

For example to use this library with JUnit5 Test Framework and Monte Scree Recorder video backend:

Monte screen recorder

pom.xml
<dependency>
  <groupId>es.lnsd.videotape</groupId>
  <artifactId>videotape-backend-monte</artifactId>
  <version>3.0-SNAPSHOT</version>
  <scope>test</scope>
</dependency>
build.gradle
testRuntimeOnly group: 'es.lnsd.videotape', name: 'videotape-backend-monte', version: '3.0-SNAPSHOT'

Recorder based on the Monte Media Library. A java library for processing media files based on Java Media Framework (JMF).

FFMPEG wrapper

pom.xml
<dependency>
  <groupId>es.lnsd.videotape</groupId>
  <artifactId>videotape-backend-ffmpeg</artifactId>
  <version>3.0-SNAPSHOT</version>
  <scope>test</scope>
</dependency>
build.gradle
testRuntimeOnly group: 'es.lnsd.videotape', name: 'videotape-backend-ffmpeg', version: '3.0-SNAPSHOT'

Recorder backend based on a wrapper around FFMPEG command line interface. This requires the ffmpeg command line executable to be available in the system.

Jaffree based command-line interface wrapper.

Dependencies

Debian
sudo apt-get update
sudo apt-get install ffmpeg
MacOS
brew install ffmpeg
Windows
  • Chocolatey:

    choco install ffmpeg
  • Scoop:

    scoop install ffmpeg
Manual install

Binaries can be found at FFMPEG’s project downloads page.

Configuration options

Name Default value Description

video.ffmpeg.binary

-

Command line interface binary path. If not set, the wrapper will use the ffmpeg binary available in the PATH.

video.ffmpeg.format

OS dependent value (e.g. for MacOS is avfoundation)

Input format for input device (see ffmpeg’s -f option).

video.ffmpeg.display

OS dependent value (e.g. for MacOS is 1:)

Input device index (See: ffmpeg’s -i option).

video.ffmpeg.pixelFormat

yuv420p

Specific pixel format (See: ffmpeg’s -pixel_format option).MacOS specific option.

VLC

pom.xml
<dependency>
  <groupId>es.lnsd.videotape</groupId>
  <artifactId>videotape-backend-vlc</artifactId>
  <version>3.0-SNAPSHOT</version>
  <scope>test</scope>
</dependency>
build.gradle
testRuntimeOnly group: 'es.lnsd.videotape', name: 'videotape-backend-vlc', version: '3.0-SNAPSHOT'

VLC recorder backend is based on vlcj, a Java framework that hides a lot of the complexities of working with LibVLC.

Requirements

VLC backend requires VLC 4.0.0+ (LibVLC) to be available in the system.

Dependencies

Debian
sudo apt-get update
sudo apt-get install vlc
MacOS
brew cask install vlc
Windows
  • Chocolatey:

    choco install vlc
  • Scoop:

    scoop install vlc
Manual install

Follow instructions at VLC’s official website.

Configuration

Some aspects of videotape operation can be modified by configuration parameters.And these configuration options can be passed through by any of the following mechanisms:

  • Declaring some JVM properties (e.g. using java/maven -Doption.name=value )

  • Through a configuration file written in properties or XML format.

Options

The following options apply to any of the different test framework integrations:

Name Default value Description

video.output

${user.dir}/video

Recorded videos output directory.

video.enable

true

Enable/disable video recording.

video.mode

ANNOTATED

Test cases to be recorded.

  • ANNOTATED: Record only the execution of test case methods annotated with @Video.

  • ALL: Record all test cases execution.

video.keep

FAILED_ONLY

Recorded videos keeping strategy.

  • FAILED_ONLY: Keep only failed test cases videos.

  • ALL: Keep all videos.

video.format

mp4

Recorded video format.

video.recorder

MONTE

Recorder backend. See the Recording backends section for more information.

video.frame.rate

24

Video recording frame rate.

For recorder backend specific options see the Recording Backends section.

Specifying a configuration file

In order to specify a custom configuration file the video.configurationFile should be provided to java runtime at start up, just before starting the tests' execution.

pom.xml
<systemPropertyVariables>
  <video.configurationFile>file:${project.basedir}/example.properties</video.configurationFile>
</systemPropertyVariables>
gradle.build
test {
  systemProperty 'video.configurationFile', "file:${projectDir}/example.properties"
}

Library’s configuration management is based on owner library. This allows videotape library to load configuration from different sources:

Options lookup sequence

Configuration loader looks up for option values following this order:

  1. First, the ConfigurationLoader looks up JVM’s system properties for the configuration entry.

  2. If no JVM’s system property is set, it will inspect the video.configurationFile system property and it will load the configuration entry.

  3. If entry is not set in video.configurationFile, the ConfigurationLoader will look for video.properties file in the classpath.

  4. If no video.properties file could be located, the ConfigurationLoader will use default values.

Project fork and renaming

This library is a fork of the work of Serhii Pirohov and the differet contributors of the video-recorder-java project.

Copyright © 2020-2022 Lorenzo Delgado

Use of this software is granted under the terms of the MIT License.

The MIT License (MIT)

Copyright (c) 2020-2021 Lorenzo Delgado
Copyright (c) 2016 Serhii Pirohov

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.