Skip to content

Commit

Permalink
Add RecordingFileFactory with default implementation (#507)
Browse files Browse the repository at this point in the history
Add RecordingFileFactory with default implementation

By default this returns a file in the given vlc recording directory named '<RESULT>-<TestClassName>-<testMethodName>-<YYYYMMdd-HHmmss>.flv', where RESULT is either 'PASSED' or 'FAILED'.

A custom factory can be provided to BrowserWebDriverContainer#withRecordingFileFactory.

The factory is only applicable if the BrowserWebDriverContainer#recordingMode enables the retention of recordings.

Fixes #500.
  • Loading branch information
ldeck authored and rnorth committed Dec 9, 2017
1 parent 9f1486e commit 6620d23
Show file tree
Hide file tree
Showing 7 changed files with 119 additions and 11 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ All notable changes to this project will be documented in this file.
- Use Visible Assertions 2.1.0 for pre-flight test output (eliminating Jansi/JNR-POSIX dependencies for lower likelihood of conflict. JNA is now used internally by Visible Assertions instead).
- Mark all links functionality as deprecated. This is pending removal in a later release. Please see [\#465](https://github.com/testcontainers/testcontainers-java/issues/465). {@link Network} features should be used instead.
- Added support for copying files to/from running containers ([\#378](https://github.com/testcontainers/testcontainers-java/issues/378))
- Added support for customising the recording file name ([\#500](https://github.com/testcontainers/testcontainers-java/issues/500))

## [1.4.3] - 2017-10-14
### Fixed
Expand Down
9 changes: 9 additions & 0 deletions docs/usage/webdriver_containers.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,15 @@ new BrowserWebDriverContainer()
```
Note that the seconds parameter to `withRecordingMode` should be a directory where recordings can be saved.

If you would like to customise the file name of the recording, or provide a different directory at runtime based on the description of the test and/or its success or failure, you may provide a custom recording file factory as follows:
```java
new BrowserWebDriverContainer()
//...
.withRecordingFileFactory(new CustomRecordingFileFactory())
```

Note the factory must implement `org.testcontainers.containers.RecordingFileFactory`.

## More examples

A few different examples are shown in [ChromeWebDriverContainerTest.java](https://github.com/testcontainers/testcontainers-java/blob/master/modules/selenium/src/test/java/org/testcontainers/junit/ChromeWebDriverContainerTest.java).
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,9 @@
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.concurrent.TimeUnit;

import static java.time.temporal.ChronoUnit.SECONDS;
Expand All @@ -47,19 +45,20 @@ public class BrowserWebDriverContainer<SELF extends BrowserWebDriverContainer<SE
@Nullable
private RemoteWebDriver driver;
private VncRecordingMode recordingMode = VncRecordingMode.RECORD_FAILING;
private RecordingFileFactory recordingFileFactory;
private File vncRecordingDirectory = new File("/tmp");

private final Collection<VncRecordingSidekickContainer> currentVncRecordings = new ArrayList<>();

private static final Logger LOGGER = LoggerFactory.getLogger(BrowserWebDriverContainer.class);
private static final SimpleDateFormat filenameDateFormat = new SimpleDateFormat("YYYYMMdd-HHmmss");

/**
*/
public BrowserWebDriverContainer() {
this.waitStrategy = new LogMessageWaitStrategy()
.withRegEx(".*(RemoteWebDriver instances should connect to|Selenium Server is up and running).*\n")
.withStartupTimeout(Duration.of(15, SECONDS));
this.withRecordingFileFactory(new DefaultRecordingFileFactory());
}

/**
Expand Down Expand Up @@ -183,22 +182,20 @@ public RemoteWebDriver getWebDriver() {

@Override
protected void failed(Throwable e, Description description) {

switch (recordingMode) {
case RECORD_FAILING:
case RECORD_ALL:
stopAndRetainRecording(description);
stopAndRetainRecordingForDescriptionAndSuccessState(description, false);
break;
}
currentVncRecordings.clear();
}

@Override
protected void succeeded(Description description) {

switch (recordingMode) {
case RECORD_ALL:
stopAndRetainRecording(description);
stopAndRetainRecordingForDescriptionAndSuccessState(description, true);
break;
}
currentVncRecordings.clear();
Expand All @@ -212,9 +209,8 @@ protected void finished(Description description) {
this.stop();
}

private void stopAndRetainRecording(Description description) {
File recordingFile = new File(vncRecordingDirectory, "recording-" + filenameDateFormat.format(new Date()) + ".flv");

private void stopAndRetainRecordingForDescriptionAndSuccessState(Description description, boolean succeeded) {
File recordingFile = recordingFileFactory.recordingFileForTest(vncRecordingDirectory, description, succeeded);
LOGGER.info("Screen recordings for test {} will be stored at: {}", description.getDisplayName(), recordingFile);

for (VncRecordingSidekickContainer container : currentVncRecordings) {
Expand Down Expand Up @@ -244,6 +240,10 @@ public SELF withRecordingMode(VncRecordingMode recordingMode, File vncRecordingD
return self();
}

public SELF withRecordingFileFactory(RecordingFileFactory recordingFileFactory) {
this.recordingFileFactory = recordingFileFactory;
return self();
}

public enum VncRecordingMode {
SKIP, RECORD_ALL, RECORD_FAILING
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package org.testcontainers.containers;

import org.junit.runner.Description;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;

public class DefaultRecordingFileFactory implements RecordingFileFactory {

private static final SimpleDateFormat filenameDateFormat = new SimpleDateFormat("YYYYMMdd-HHmmss");
private static final String PASSED = "PASSED";
private static final String FAILED = "FAILED";
private static final String FILENAME_FORMAT = "%s-%s-%s-%s.flv";

@Override
public File recordingFileForTest(File vncRecordingDirectory, Description description, boolean succeeded) {
final String prefix = succeeded ? PASSED : FAILED;
final String fileName = String.format(FILENAME_FORMAT,
prefix,
description.getTestClass().getSimpleName(),
description.getMethodName(),
filenameDateFormat.format(new Date())
);
return new File(vncRecordingDirectory, fileName);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package org.testcontainers.containers;

import org.junit.runner.Description;

import java.io.File;

public interface RecordingFileFactory {
File recordingFileForTest(File vncRecordingDirectory, Description description, boolean succeeded);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package org.testcontainers.containers;

import lombok.Value;
import org.junit.Test;
import org.junit.runner.Description;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

import java.io.File;
import java.nio.file.Files;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

import static java.lang.Boolean.FALSE;
import static java.lang.Boolean.TRUE;
import static java.lang.String.format;
import static java.time.LocalDateTime.now;
import static org.hamcrest.core.IsCollectionContaining.hasItem;
import static org.junit.Assert.assertThat;
import static org.junit.runner.Description.createTestDescription;

@RunWith(Parameterized.class)
@Value
public class DefaultRecordingFileFactoryTest {

private static final DateTimeFormatter DATETIME_FORMATTER = DateTimeFormatter.ofPattern("YYYYMMdd-HHmmss");

private final DefaultRecordingFileFactory factory = new DefaultRecordingFileFactory();
private final String methodName;
private final String prefix;
private final boolean success;

@Parameterized.Parameters
public static Collection<Object[]> data() {
Collection<Object[]> args = new ArrayList<>();
args.add(new Object[]{"testMethod1", "FAILED", FALSE});
args.add(new Object[]{"testMethod2", "PASSED", TRUE});
return args;
}

@Test
public void recordingFileThatShouldDescribeTheTestResultAtThePresentTime() throws Exception {
File vncRecordingDirectory = Files.createTempDirectory("recording").toFile();
Description description = createTestDescription(getClass().getCanonicalName(), methodName, Test.class);

File recordingFile = factory.recordingFileForTest(vncRecordingDirectory, description, success);

String expectedFilePrefix = format("%s-%s-%s", prefix, getClass().getSimpleName(), methodName);

List<File> expectedPossibleFileNames = Arrays.asList(
new File(vncRecordingDirectory, format("%s-%s.flv", expectedFilePrefix, now().format(DATETIME_FORMATTER))),
new File(vncRecordingDirectory, format("%s-%s.flv", expectedFilePrefix, now().minusSeconds(1L).format(DATETIME_FORMATTER)))
);

assertThat(expectedPossibleFileNames, hasItem(recordingFile));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import org.junit.Test;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.testcontainers.containers.BrowserWebDriverContainer;
import org.testcontainers.containers.DefaultRecordingFileFactory;

import java.io.File;

Expand All @@ -17,7 +18,8 @@ public class ChromeRecordingWebDriverContainerTest extends BaseWebDriverContaine
@Rule
public BrowserWebDriverContainer chromeThatRecordsAllTests = new BrowserWebDriverContainer()
.withDesiredCapabilities(DesiredCapabilities.chrome())
.withRecordingMode(RECORD_ALL, new File("./target/"));
.withRecordingMode(RECORD_ALL, new File("./target/"))
.withRecordingFileFactory(new DefaultRecordingFileFactory());

@Rule
public BrowserWebDriverContainer chromeThatRecordsFailingTests = new BrowserWebDriverContainer()
Expand Down

0 comments on commit 6620d23

Please sign in to comment.