Skip to content

Commit

Permalink
Write screenshots to file and return the file path instead of returni…
Browse files Browse the repository at this point in the history
…ng screenshots bytes. getgauge/gauge#1476
  • Loading branch information
negiDharmendra committed Dec 16, 2019
1 parent 1e047b6 commit 0440c8c
Show file tree
Hide file tree
Showing 7 changed files with 58 additions and 65 deletions.
10 changes: 5 additions & 5 deletions src/main/java/com/thoughtworks/gauge/Gauge.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ protected List<String> initialValue() {
}
};
private static ClassInstanceManager instanceManager;
private static ThreadLocal<List<byte[]>> screenshots = new InheritableThreadLocal<List<byte[]>>() {
private static ThreadLocal<List<String>> screenshots = new InheritableThreadLocal<List<String>>() {
@Override
protected List<byte[]> initialValue() {
protected List<String> initialValue() {
return new ArrayList<>();
}
};
Expand Down Expand Up @@ -61,11 +61,11 @@ static List<String> getMessages() {
}

public static void captureScreenshot() {
byte[] screenshotBytes = new ScreenshotFactory(instanceManager).getScreenshotBytes();
getScreenshots().add(screenshotBytes);
String screenshotFileName = new ScreenshotFactory(instanceManager).getScreenshotBytes();
getScreenshots().add(screenshotFileName);
}

static List<byte[]> getScreenshots() {
static List<String> getScreenshots() {
return screenshots.get();
}
}
13 changes: 5 additions & 8 deletions src/main/java/com/thoughtworks/gauge/ScreenshotCollector.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@

package com.thoughtworks.gauge;

import com.google.protobuf.ByteString;
import gauge.messages.Spec;

import java.util.ArrayList;
Expand All @@ -25,20 +24,18 @@

public class ScreenshotCollector {
public Spec.ProtoExecutionResult addPendingScreenshotTo(Spec.ProtoExecutionResult result) {
List<byte[]> screenshots = getAllPendingScreenshots();
ArrayList<String> screenshots = getAllPendingScreenshots();
return addPendingScreenshot(result, screenshots);
}

Spec.ProtoExecutionResult addPendingScreenshot(Spec.ProtoExecutionResult result, List<byte[]> screenshots) {
Spec.ProtoExecutionResult addPendingScreenshot(Spec.ProtoExecutionResult result, List<String> screenshotsFileName) {
Spec.ProtoExecutionResult.Builder builder = Spec.ProtoExecutionResult.newBuilder(result);
for (byte[] screenshot : screenshots) {
builder.addScreenshots(ByteString.copyFrom(screenshot));
}
builder.addAllScreenshotFiles(screenshotsFileName);
return builder.build();
}

private List<byte[]> getAllPendingScreenshots() {
List<byte[]> pendingScreenshots = new ArrayList<>(getScreenshots());
private ArrayList<String> getAllPendingScreenshots() {
ArrayList<String> pendingScreenshots = new ArrayList<>(getScreenshots());
clear();
return pendingScreenshots;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,13 @@ protected Spec.ProtoExecutionResult mergeExecResults(Spec.ProtoExecutionResult p
if (previousStageResult.getFailed()) {
builder.setErrorMessage(previousStageResult.getErrorMessage());
builder.setErrorType(previousStageResult.getErrorType());
builder.setScreenShot(previousStageResult.getScreenShot());
builder.setFailureScreenshot(previousStageResult.getFailureScreenshot());
builder.setFailureScreenshotFile(previousStageResult.getFailureScreenshotFile());
builder.setStackTrace(previousStageResult.getStackTrace());
builder.setRecoverableError(previousStageResult.getRecoverableError());
} else if (execResult.getFailed()) {
builder.setErrorType(execResult.getErrorType());
builder.setErrorMessage(execResult.getErrorMessage());
builder.setScreenShot(execResult.getScreenShot());
builder.setFailureScreenshot(execResult.getFailureScreenshot());
builder.setFailureScreenshotFile(execResult.getFailureScreenshotFile());
builder.setStackTrace(execResult.getStackTrace());
builder.setRecoverableError(execResult.getRecoverableError());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@

package com.thoughtworks.gauge.execution;

import com.google.protobuf.ByteString;
import com.thoughtworks.gauge.ClassInstanceManager;
import com.thoughtworks.gauge.ContinueOnFailure;
import com.thoughtworks.gauge.screenshot.ScreenshotFactory;
Expand Down Expand Up @@ -51,9 +50,8 @@ public Spec.ProtoExecutionResult execute(Method method, Object... args) {

private Spec.ProtoExecutionResult createFailureExecResult(long execTime, Throwable e, boolean recoverable, Class[] continuableExceptions) {
Spec.ProtoExecutionResult.Builder builder = Spec.ProtoExecutionResult.newBuilder().setFailed(true);
ByteString screenshotBytes = ByteString.copyFrom(new ScreenshotFactory(instanceManager).getScreenshotBytes());
builder.setScreenShot(screenshotBytes);
builder.setFailureScreenshot(screenshotBytes);
String screenshotFileName = new ScreenshotFactory(instanceManager).getScreenshotBytes();
builder.setFailureScreenshotFile(screenshotFileName);
if (e.getCause() != null) {
builder.setRecoverableError(false);
for (Class c : continuableExceptions) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,11 @@
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.UUID;

/**
* Used to take screenshots on failure.
Expand All @@ -44,22 +48,23 @@ static void setCustomScreenshotGrabber(Class<? extends ICustomScreenshotGrabber>
customScreenshotGrabber = customScreenGrabber;
}

public byte[] getScreenshotBytes() {
public String getScreenshotBytes() {
if (shouldTakeScreenshot()) {
return takeScreenshot();
}
return new byte[0];
return "";
}

private byte[] takeScreenshot() {
private String takeScreenshot() {
if (customScreenshotGrabber != null) {
try {
ICustomScreenshotGrabber customScreenGrabberInstance = (ICustomScreenshotGrabber) manager.get(customScreenshotGrabber);
byte[] bytes = customScreenGrabberInstance.takeScreenshot();
if (bytes == null) {
bytes = new byte[0];
}
return bytes;
File file = generateUniqueScreenshotFile();
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
BufferedImage bufferedImage = ImageIO.read(byteArrayInputStream);
ImageIO.write(bufferedImage, IMAGE_EXTENSION, file);
return file.getName();
} catch (Exception e) {
Logger.error(String.format("Failed to take Custom screenshot: %s : %s", customScreenshotGrabber.getCanonicalName(), e.getMessage()));
Logger.warning("Capturing regular screenshot..");
Expand All @@ -68,8 +73,13 @@ private byte[] takeScreenshot() {
return captureScreen();
}

private byte[] captureScreen() {
ByteArrayOutputStream imageBytes = new ByteArrayOutputStream();
private File generateUniqueScreenshotFile() {
Path path = Paths.get(System.getenv("screenshots_dir"), String.format("screenshot-%s.png", UUID.randomUUID().toString()));
return new File(path.toAbsolutePath().toString());
}

private String captureScreen() {
File file = generateUniqueScreenshotFile();
if (shouldTakeScreenshot()) {
try {
// Union together all screen devices for 1 large screenshot
Expand All @@ -78,13 +88,12 @@ private byte[] captureScreen() {
screenRect = screenRect.union(gd.getDefaultConfiguration().getBounds());
}
BufferedImage image = new Robot().createScreenCapture(screenRect);
ImageIO.write(image, IMAGE_EXTENSION, imageBytes);
ImageIO.write(image, IMAGE_EXTENSION, file);
} catch (Throwable e) {
Logger.error("Failed to take regular screenshot: " + e.getMessage());
return new byte[0];
}
}
return imageBytes.toByteArray();
return file.getName();
}

private boolean shouldTakeScreenshot() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@

package com.thoughtworks.gauge;

import com.google.protobuf.ByteString;
import gauge.messages.Spec;
import junit.framework.TestCase;

Expand All @@ -25,15 +24,15 @@
public class ScreenshotCollectorTest extends TestCase {
public void testAddingScreenshotsToProtoResult() {
Spec.ProtoExecutionResult executionResult = emptyExecResult();
byte a = Byte.valueOf("1");
byte b = Byte.valueOf("2");
byte[] bytes = {a,b};
List<byte[]> screenshots = new ArrayList<>();
screenshots.add(bytes);
String a = "1";
String b = "2";
List<String> screenshots = new ArrayList<>();
screenshots.add(a);
screenshots.add(b);
Spec.ProtoExecutionResult protoExecutionResult = new ScreenshotCollector().addPendingScreenshot(executionResult, screenshots);
List<ByteString> actualScreenshotList = protoExecutionResult.getScreenshotsList();
for (byte[] screenshot : screenshots) {
assertTrue(actualScreenshotList.contains(ByteString.copyFrom(screenshot)));
List<String> actualScreenshotList = protoExecutionResult.getScreenshotFilesList();
for (String screenshot : screenshots) {
assertTrue(actualScreenshotList.contains(screenshot));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@

package com.thoughtworks.gauge.execution;

import com.google.protobuf.ByteString;
import gauge.messages.Spec;
import junit.framework.TestCase;

Expand All @@ -30,17 +29,14 @@ public void testMergingSimpleResultsBothPassing() throws Exception {
}

public void testMergingResultsPreviousFailing() throws Exception {

Byte b = Byte.valueOf("1");
byte[] bytes = {b};
ByteString screenShot = ByteString.copyFrom(bytes);
String screenShot = "1";

Spec.ProtoExecutionResult previous = Spec.ProtoExecutionResult.newBuilder().setFailed(true).
setExecutionTime(100).
setRecoverableError(false).
setErrorMessage("Previous failed").
setStackTrace("Previous stacktrace").
setFailureScreenshot(screenShot).build();
setFailureScreenshotFile(screenShot).build();
Spec.ProtoExecutionResult current = Spec.ProtoExecutionResult.newBuilder().setFailed(false).setExecutionTime(1100).build();
Spec.ProtoExecutionResult result = new TestExecutionStage().mergeExecResults(previous, current);

Expand All @@ -49,77 +45,73 @@ public void testMergingResultsPreviousFailing() throws Exception {
assertEquals("Previous failed", result.getErrorMessage());
assertEquals("Previous stacktrace", result.getStackTrace());
assertFalse(result.getRecoverableError());
assertEquals(screenShot, result.getFailureScreenshot());
assertEquals(screenShot, result.getFailureScreenshotFile());
}

public void testMergingResultsCurrentFailing() throws Exception {
Byte b = Byte.valueOf("2");
byte[] bytes = {b};
ByteString screenShot = ByteString.copyFrom(bytes);
String screenShot = "2";

Spec.ProtoExecutionResult previous = Spec.ProtoExecutionResult.newBuilder().setFailed(false).setExecutionTime(100).build();
Spec.ProtoExecutionResult current = Spec.ProtoExecutionResult.newBuilder().setFailed(true).
setExecutionTime(100).
setRecoverableError(false).
setErrorMessage("current failed").
setStackTrace("current stacktrace").
setFailureScreenshot(screenShot).build();
setFailureScreenshotFile(screenShot).build();
Spec.ProtoExecutionResult result = new TestExecutionStage().mergeExecResults(previous, current);

assertTrue(result.getFailed());
assertEquals(200, result.getExecutionTime());
assertEquals("current failed", result.getErrorMessage());
assertEquals("current stacktrace", result.getStackTrace());
assertFalse(result.getRecoverableError());
assertEquals(screenShot, result.getFailureScreenshot());
assertEquals(screenShot, result.getFailureScreenshotFile());
}

public void testMergingResultsBothFailing() throws Exception {
Byte b = Byte.valueOf("2");
byte[] bytes = {b};
ByteString screenShotPrevious = ByteString.copyFrom(bytes);
ByteString screenShotCurrent = ByteString.copyFromUtf8("hello");
String screenShotPrevious = "2";
String screenShotCurrent = "hello";

Spec.ProtoExecutionResult previous = Spec.ProtoExecutionResult.newBuilder().setFailed(true).
setExecutionTime(1001).
setRecoverableError(true).
setErrorMessage("previous failed").
setStackTrace("previous stacktrace").
setFailureScreenshot(screenShotPrevious).build();
setFailureScreenshotFile(screenShotPrevious).build();
Spec.ProtoExecutionResult current = Spec.ProtoExecutionResult.newBuilder().setFailed(true).
setExecutionTime(1002).
setRecoverableError(false).
setErrorMessage("current failed").
setStackTrace("current stacktrace").
setFailureScreenshot(screenShotCurrent).build();
setFailureScreenshotFile(screenShotCurrent).build();
Spec.ProtoExecutionResult result = new TestExecutionStage().mergeExecResults(previous, current);

assertTrue(result.getFailed());
assertEquals(2003, result.getExecutionTime());
assertEquals("previous failed", result.getErrorMessage());
assertEquals("previous stacktrace", result.getStackTrace());
assertFalse(result.getRecoverableError());
assertEquals(screenShotPrevious, result.getFailureScreenshot());
assertEquals(screenShotPrevious, result.getFailureScreenshotFile());
}

public void testMergingResultsCurrentFailingAndIsRecoverable() throws Exception {
ByteString screenShotCurrent = ByteString.copyFromUtf8("hello");
String screenShotCurrent = "screenShotCurrent.png";

Spec.ProtoExecutionResult previous = Spec.ProtoExecutionResult.newBuilder().setFailed(false).setExecutionTime(1001).build();
Spec.ProtoExecutionResult current = Spec.ProtoExecutionResult.newBuilder().setFailed(true).
setExecutionTime(1002).
setRecoverableError(true).
setErrorMessage("current failed").
setStackTrace("current stacktrace").
setFailureScreenshot(screenShotCurrent).build();
setFailureScreenshotFile(screenShotCurrent).build();
Spec.ProtoExecutionResult result = new TestExecutionStage().mergeExecResults(previous, current);

assertTrue(result.getFailed());
assertEquals(2003, result.getExecutionTime());
assertEquals("current failed", result.getErrorMessage());
assertEquals("current stacktrace", result.getStackTrace());
assertTrue(result.getRecoverableError());
assertEquals(screenShotCurrent, result.getFailureScreenshot());
assertEquals(screenShotCurrent, result.getFailureScreenshotFile());
}

private class TestExecutionStage extends AbstractExecutionStage {
Expand Down

0 comments on commit 0440c8c

Please sign in to comment.