Skip to content

Commit

Permalink
Record screen source code for failing tests.
Browse files Browse the repository at this point in the history
  • Loading branch information
wakaleo committed Nov 23, 2015
1 parent 552172c commit 930f34c
Show file tree
Hide file tree
Showing 8 changed files with 141 additions and 24 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package net.serenitybdd.core.model;

import net.thucydides.core.model.TestOutcome;
import net.thucydides.core.model.TestStep;
import net.thucydides.core.screenshots.ScreenshotAndHtmlSource;

public class FailureDetails {
private final TestOutcome testOutcome;

public FailureDetails(TestOutcome testOutcome) {
this.testOutcome = testOutcome;
}

public String getConciseErrorMessage() {
if (testOutcome.firstStepWithErrorMessage().isPresent()) {
return testOutcome.firstStepWithErrorMessage().get().getConciseErrorMessage();
}
return testOutcome.testFailureMessage().or("");
}

public String getPageSourceLink() {
for(TestStep testStep : testOutcome.getFlattenedTestSteps()) {
for(ScreenshotAndHtmlSource screenshot : testStep.getScreenshots()) {
if (screenshot.getHtmlSourceName() != null) {
return screenshot.getHtmlSourceName();
}
}
}
return "#";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package net.serenitybdd.core.photography;

import com.google.common.base.Optional;
import org.openqa.selenium.WebDriver;

import java.io.File;
import java.nio.file.Path;

public class DisabledPageSourceRecorder extends PageSourceRecorder {
public DisabledPageSourceRecorder(WebDriver driver) {
super(driver);
}

@Override
public Optional<File> intoDirectory(Path path) {
return Optional.absent();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package net.serenitybdd.core.photography;


import com.google.common.base.Optional;
import org.openqa.selenium.WebDriver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;

public class PageSourceRecorder {
private final WebDriver driver;

private final Logger LOGGER = LoggerFactory.getLogger(this.getClass());

public PageSourceRecorder(WebDriver driver) {
this.driver = driver;
}

public Optional<File> intoDirectory(Path path) {
try {
Path pageSourceFile = Files.createTempFile(path, "pagesource", ".html.txt");
Files.write(pageSourceFile, pageSource());
return Optional.of(pageSourceFile.toFile());
} catch(IOException couldNotCreatePageSourcce) {
LOGGER.warn("Could not save the page source HTML file", couldNotCreatePageSourcce);
}
return Optional.absent();
}

private byte[] pageSource() {
if (driver.getPageSource() == null) { return new byte[]{}; }
return driver.getPageSource().getBytes();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package net.serenitybdd.core.photography;

import com.google.common.base.Optional;
import net.thucydides.core.model.TestResult;
import org.openqa.selenium.WebDriver;

import java.io.File;

public class SoundEngineer {

private boolean recordPageSource = true;

public SoundEngineer ifRequiredForResult(TestResult result) {
recordPageSource = (result == TestResult.FAILURE || result == TestResult.ERROR);
return this;
}

public PageSourceRecorder recordPageSourceUsing(WebDriver driver) {
return (recordPageSource) ? new PageSourceRecorder(driver) : new DisabledPageSourceRecorder(driver);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import net.serenitybdd.core.exceptions.SerenityWebDriverException;
import net.serenitybdd.core.model.FailureDetails;
import net.serenitybdd.core.time.SystemClock;
import net.thucydides.core.ThucydidesSystemProperty;
import net.thucydides.core.annotations.TestAnnotations;
Expand Down Expand Up @@ -1145,7 +1146,7 @@ public FailureCause getNestedTestFailureCause() {
return getTestFailureCause();
}

private Optional<TestStep> firstStepWithErrorMessage() {
public Optional<TestStep> firstStepWithErrorMessage() {
for (TestStep step : getFlattenedTestSteps()) {
if (isNotBlank(step.getErrorMessage())) {
return Optional.of(step);
Expand All @@ -1166,8 +1167,6 @@ public String getErrorMessage() {
return testFailureMessage().or("");
}



public String getConciseErrorMessage() {
if (firstStepWithErrorMessage().isPresent()) {
return firstStepWithErrorMessage().get().getConciseErrorMessage();
Expand Down Expand Up @@ -2015,4 +2014,9 @@ private void removeSteps(List<TestStep> stepsToReplace) {
}
}
}

public FailureDetails getFailureDetails() {
return new FailureDetails(this);
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package net.thucydides.core.screenshots;

import com.google.common.base.Objects;
import com.google.common.base.Optional;
import org.apache.commons.io.FileUtils;

Expand Down Expand Up @@ -54,24 +55,12 @@ public boolean wasTaken() {
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof ScreenshotAndHtmlSource)) return false;

if (o == null || getClass() != o.getClass()) return false;
ScreenshotAndHtmlSource that = (ScreenshotAndHtmlSource) o;

if (screenshot == null) {
return (that.screenshot == null);
} else if (that.screenshot == null) {
return (this.screenshot == null);
} else {
try {
return FileUtils.contentEquals(screenshot, that.screenshot);
} catch (IOException e) {
return false;
}
}
return Objects.equal(screenshot, that.screenshot) &&
Objects.equal(htmlSource, that.htmlSource);
}


@Override
public int hashCode() {
return screenshot != null ? screenshot.hashCode() : 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import net.serenitybdd.core.PendingStepException;
import net.serenitybdd.core.photography.Darkroom;
import net.serenitybdd.core.photography.ScreenshotPhoto;
import net.serenitybdd.core.photography.SoundEngineer;
import net.serenitybdd.core.photography.bluring.AnnotatedBluring;
import net.serenitybdd.core.rest.RestQuery;
import net.serenitybdd.core.time.SystemClock;
Expand Down Expand Up @@ -97,6 +98,7 @@ public class BaseStepListener implements StepListener, StepPublisher {
private List<TestTag> storywideTags;

private net.serenitybdd.core.photography.Photographer photographer = new net.serenitybdd.core.photography.Photographer();
private SoundEngineer soundEngineer = new SoundEngineer();

public void setEventBus(StepEventBus eventBus) {
this.eventBus = eventBus;
Expand Down Expand Up @@ -599,7 +601,7 @@ private boolean currentStepExists() {

private void takeEndOfStepScreenshotFor(final TestResult result) {
if (currentTestIsABrowserTest() && shouldTakeEndOfStepScreenshotFor(result)) {
take(OPTIONAL_SCREENSHOT);
take(MANDATORY_SCREENSHOT, result);
}
}

Expand All @@ -612,9 +614,13 @@ public void clearForcedResult() {
}

private void take(final ScreenshotType screenshotType) {
take(screenshotType, UNDEFINED);
}

private void take(final ScreenshotType screenshotType, TestResult result) {
if (shouldTakeScreenshots()) {
try {
Optional<ScreenshotAndHtmlSource> screenshotAndHtmlSource = grabScreenshot();
Optional<ScreenshotAndHtmlSource> screenshotAndHtmlSource = grabScreenshot(result);
if (screenshotAndHtmlSource.isPresent()) {
recordScreenshotIfRequired(screenshotType, screenshotAndHtmlSource.get());
}
Expand Down Expand Up @@ -696,20 +702,25 @@ private void takeInitialScreenshot() {
}
}

private Optional<ScreenshotAndHtmlSource> grabScreenshot() {
private Optional<ScreenshotAndHtmlSource> grabScreenshot(TestResult result) {

ScreenshotPhoto newPhoto = ScreenshotPhoto.None;
Optional<File> pageSource = Optional.absent();

if (pathOf(outputDirectory) != null) { // Output directory may be null for some tests
newPhoto = photographer.takesAScreenshot()
.with(getDriver())
.andWithBlurring(AnnotatedBluring.blurLevel())
.andSaveToDirectory(pathOf(outputDirectory));

pageSource = soundEngineer.ifRequiredForResult(result)
.recordPageSourceUsing(getDriver())
.intoDirectory(pathOf(outputDirectory));

}
return (newPhoto == ScreenshotPhoto.None) ?
Optional.<ScreenshotAndHtmlSource>absent()
: Optional.of(new ScreenshotAndHtmlSource(newPhoto.getPathToScreenshot().toFile()));
: Optional.of(new ScreenshotAndHtmlSource(newPhoto.getPathToScreenshot().toFile(), pageSource.orNull()));
}

private Path pathOf(File directory) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -194,8 +194,13 @@
<div id="beforetable"></div>
<div id="contenttilttle">
<#if testOutcome.conciseErrorMessage??>
<span class='error-caption ellipsis'>${testOutcome.result}: ${testOutcome.conciseErrorMessage}</span>
<#if testOutcome.failureDetails.conciseErrorMessage??>
<div class="screenshotFailure panel panel-danger">
<div class="panel-heading"><span class='error-caption ellipsis'>${testOutcome.result}: ${testOutcome.failureDetails.conciseErrorMessage}</span></div>
<div class="panel-body">
<a href="${testOutcome.failureDetails.pageSourceLink}" target="_blank" class="btn btn-info">HTML Source</a>
</div>
</div>
</#if>
<div class="slider-wrapper theme-default">
<div id="slider">
Expand Down

0 comments on commit 930f34c

Please sign in to comment.