Skip to content

Commit

Permalink
Added a page to the reports containing system and configuration prope…
Browse files Browse the repository at this point in the history
…rties and browser capabilities for a given test run.

The browser used for each test is also recorded and displayed as an icon on the test report pages.
You can also add your own custom fields into the build information page. You do this by adding properties with the "sysinfo" prefix to your serenity.properties file. These variables take Groovy expressions, which will be evaluated when the report is run, e.g:
    sysinfo.theAnswer = 6*7
    sysinfo.homeDir = System.getenv("HOME")
  • Loading branch information
wakaleo committed Feb 12, 2015
1 parent 828c57a commit fe1ab3e
Show file tree
Hide file tree
Showing 36 changed files with 628 additions and 19 deletions.
4 changes: 4 additions & 0 deletions browser-firefox.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#
#Thu Feb 12 13:47:25 EST 2015
version=
browserName=firefox
Empty file added browser-htmlUnit.properties
Empty file.
2 changes: 2 additions & 0 deletions core/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ dependencies {

compile 'io.appium:java-client:2.1.0'

compile 'org.codehaus.groovy:groovy:2.4.0'

compile "net.sf.opencsv:opencsv:2.0"
compile ("commons-beanutils:commons-beanutils-core:1.8.3") {
exclude group: 'commons-logging', module: 'commons-logging'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package net.serenitybdd.core.buildinfo;

import com.beust.jcommander.internal.Maps;
import groovy.lang.Binding;
import groovy.lang.GroovyShell;
import net.thucydides.core.ThucydidesSystemProperty;
import net.thucydides.core.guice.Injectors;
import net.thucydides.core.guice.ThucydidesModule;
import net.thucydides.core.util.EnvironmentVariables;

import java.util.List;
import java.util.Map;
import java.util.Properties;

import static ch.lambdaj.Lambda.filter;
import static org.hamcrest.CoreMatchers.startsWith;

/**
* Created by john on 12/02/15.
*/
public class BuildInfoProvider {
private final EnvironmentVariables environmentVariables;
private final DriverCapabilityRecord driverCapabilityRecord;

public BuildInfoProvider(EnvironmentVariables environmentVariables) {
this.environmentVariables = environmentVariables;
this.driverCapabilityRecord = Injectors.getInjector().getInstance(DriverCapabilityRecord.class);
}

public BuildProperties getBuildProperties() {
Map<String, String> generalProperties = Maps.newHashMap();
generalProperties.put("Default Driver",ThucydidesSystemProperty.DRIVER.from(environmentVariables,"firefox"));
generalProperties.put("Operating System",System.getProperty("os.name") + " version " + System.getProperty("os.version"));
addRemoteDriverPropertiesTo(generalProperties);
addCustomPropertiesTo(generalProperties);

List<String> drivers = driverCapabilityRecord.getDrivers();
Map<String, Properties> driverPropertiesMap = driverCapabilityRecord.getDriverCapabilities();

return new BuildProperties(generalProperties, drivers, driverPropertiesMap);
}

private void addRemoteDriverPropertiesTo(Map<String, String> buildProperties) {
if (ThucydidesSystemProperty.WEBDRIVER_REMOTE_DRIVER.isDefinedIn(environmentVariables)) {
buildProperties.put("Remote driver", ThucydidesSystemProperty.WEBDRIVER_REMOTE_DRIVER.from(environmentVariables));
buildProperties.put("Remote browser version", ThucydidesSystemProperty.WEBDRIVER_REMOTE_BROWSER_VERSION.from(environmentVariables));
buildProperties.put("Remote OS", ThucydidesSystemProperty.WEBDRIVER_REMOTE_OS.from(environmentVariables));
}
}

private void addCustomPropertiesTo(Map<String, String> buildProperties) {

List<String> sysInfoKeys = filter(startsWith("sysinfo."), environmentVariables.getKeys());
for(String key : sysInfoKeys) {
String simplifiedKey = key.replace("sysinfo.", "");
String expression = environmentVariables.getProperty(key);

String value = evaluateGroovyExpression(expression);

buildProperties.put(simplifiedKey, value);
}

}

private String evaluateGroovyExpression(String expression) {
Binding binding = new Binding();
binding.setVariable("env", environmentVariables);
GroovyShell shell = new GroovyShell(binding);
return shell.evaluate(expression).toString();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package net.serenitybdd.core.buildinfo;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;

import java.util.List;
import java.util.Map;
import java.util.Properties;

/**
* Created by john on 12/02/15.
*/
public class BuildProperties {

private final Map<String, String> generalProperties;
private final List<String> drivers;
private final Map<String, Properties> driverProperties;

public BuildProperties(Map<String, String> generalProperties, List<String> drivers, Map<String, Properties> driverProperties) {
this.generalProperties = generalProperties;
this.drivers = drivers;
this.driverProperties = driverProperties;
}

public Map<String, String> getGeneralProperties() {
return ImmutableMap.copyOf(generalProperties);
}

public List<String> getDrivers() {
return ImmutableList.copyOf(drivers);
}

public Map<String, Properties> getDriverProperties() {
return ImmutableMap.copyOf(driverProperties);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package net.serenitybdd.core.buildinfo;

import org.openqa.selenium.Capabilities;

import java.util.List;
import java.util.Map;
import java.util.Properties;

/**
* Created by john on 12/02/15.
*/
public interface DriverCapabilityRecord {
void registerCapabilities(String driver, Capabilities capabilities);
List<String> getDrivers();
Map<String,Properties> getDriverCapabilities();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package net.serenitybdd.core.buildinfo;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.inject.Inject;
import net.thucydides.core.webdriver.Configuration;
import org.openqa.selenium.Capabilities;

import java.io.*;
import java.nio.file.DirectoryIteratorException;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import static java.nio.file.Files.newInputStream;

/**
* Created by john on 12/02/15.
*/
public class PropertyBasedDriverCapabilityRecord implements DriverCapabilityRecord {

private Configuration configuration;

@Inject
public PropertyBasedDriverCapabilityRecord(Configuration configuration) {
this.configuration = configuration;
}

public void registerCapabilities(String driver, Capabilities capabilities) {

Properties properties = new Properties();
properties.setProperty("platform", capabilities.getPlatform().name());
for (String capability : capabilities.asMap().keySet()) {
if (capabilities.getCapability(capability) instanceof String) {
properties.setProperty(capability, capabilities.getCapability(capability).toString());
}
}
try {
File browserProperties = new File(configuration.getOutputDirectory(), "browser-" + driver.toLowerCase() + ".properties");
try (Writer writer = new FileWriter(browserProperties)) {
properties.store(writer, "");
}
} catch (IOException e) {
e.printStackTrace();
}
}

@Override
public List<String> getDrivers() {
List<String> drivers = Lists.newArrayList();
try (DirectoryStream<Path> stream = driverCapabilityRecords()) {
for (Path file : stream) {
String driverName = driverNameFrom(file);
drivers.add(driverName);
}
} catch (IOException | DirectoryIteratorException x) {
System.err.println(x);
}
return drivers;
}

private String driverNameFrom(Path file) {
return file.getFileName().toString().replace("browser-","").replace(".properties","");
}

private DirectoryStream<Path> driverCapabilityRecords() throws IOException {
Path outputDirectory = configuration.getOutputDirectory().toPath();
return Files.newDirectoryStream(outputDirectory,"browser-*.properties");
}

@Override
public Map<String, Properties> getDriverCapabilities() {
Map<String, Properties> driverCapabilities = Maps.newHashMap();
try (DirectoryStream<Path> stream = driverCapabilityRecords()) {
for (Path file : stream) {
String driverName = driverNameFrom(file);
Properties driverProperties = new Properties();
driverProperties.load(newInputStream(file));
driverCapabilities.put(driverName, driverProperties);
}
} catch (IOException | DirectoryIteratorException x) {
System.err.println(x);
}
return driverCapabilities;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import com.google.inject.AbstractModule;
import com.google.inject.Provides;
import com.google.inject.Singleton;
import net.serenitybdd.core.buildinfo.DriverCapabilityRecord;
import net.serenitybdd.core.buildinfo.PropertyBasedDriverCapabilityRecord;
import net.thucydides.core.annotations.locators.SmartElementProxyCreator;
import net.thucydides.core.batches.BatchManager;
import net.thucydides.core.batches.BatchManagerProvider;
Expand Down Expand Up @@ -66,6 +68,7 @@ protected void configure() {
bind(TestCount.class).to(AtomicTestCount.class).in(Singleton.class);

bind(MarkupRenderer.class).annotatedWith(Asciidoc.class).to(AsciidocMarkupRenderer.class).in(Singleton.class);
bind(DriverCapabilityRecord.class).to(PropertyBasedDriverCapabilityRecord.class);
}

@Provides
Expand Down
20 changes: 20 additions & 0 deletions core/src/main/java/net/thucydides/core/model/TestOutcome.java
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,11 @@ public class TestOutcome {
*/
private String sessionId;

/**
* The driver used to run this test if it is a web test.
*/
private String driver;

/**
* Keeps track of step groups.
* If not empty, the top of the stack contains the step corresponding to the current step group - new steps should
Expand Down Expand Up @@ -313,6 +318,7 @@ public TestOutcome copy() {
this.annotatedResult,
this.dataTable,
this.qualifier,
this.driver,
this.manual);
}

Expand All @@ -333,6 +339,7 @@ protected TestOutcome(final Long startTime,
final TestResult annotatedResult,
final DataTable dataTable,
final Optional<String> qualifier,
final String driver,
final boolean manualTest) {
this.startTime = startTime;
this.duration = duration;
Expand All @@ -355,6 +362,7 @@ protected TestOutcome(final Long startTime,
this.dataTable = dataTable;
this.issueTracking = Injectors.getInjector().getInstance(IssueTracking.class);
this.linkGenerator = Injectors.getInjector().getInstance(LinkGenerator.class);
this.driver = driver;
this.manual = manualTest;
}

Expand Down Expand Up @@ -399,6 +407,7 @@ public TestOutcome withQualifier(String qualifier) {
this.annotatedResult,
this.dataTable,
Optional.fromNullable(qualifier),
this.driver,
this.manual);
} else {
return this;
Expand All @@ -423,6 +432,7 @@ public TestOutcome withIssues(List<String> issues) {
this.annotatedResult,
this.dataTable,
this.qualifier,
this.driver,
this.manual);
}

Expand All @@ -444,6 +454,7 @@ public TestOutcome withTags(Set<TestTag> tags) {
this.annotatedResult,
this.dataTable,
this.qualifier,
this.driver,
this.manual);
}

Expand All @@ -466,6 +477,7 @@ public TestOutcome withMethodName(String methodName) {
this.annotatedResult,
this.dataTable,
this.qualifier,
this.driver,
this.manual);
} else {
return this;
Expand Down Expand Up @@ -545,6 +557,14 @@ public void clearForcedResult() {
annotatedResult = null;
}

public void setDriver(String driver) {
this.driver = driver;
}

public String getDriver() {
return driver;
}

public class TitleBuilder {
private final boolean qualified;
private final TestOutcome testOutcome;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package net.thucydides.core.reports.html;

import com.beust.jcommander.internal.Lists;
import com.beust.jcommander.internal.Maps;
import net.serenitybdd.core.SerenitySystemProperties;
import net.serenitybdd.core.buildinfo.BuildInfoProvider;
import net.thucydides.core.ThucydidesSystemProperty;
import net.thucydides.core.guice.Injectors;
import net.thucydides.core.issues.IssueTracking;
Expand All @@ -21,6 +23,7 @@
import net.thucydides.core.requirements.reports.RequirmentsOutcomeFactory;
import net.thucydides.core.util.EnvironmentVariables;
import net.thucydides.core.util.Inflector;
import net.thucydides.core.util.LocalPreferences;
import net.thucydides.core.util.VersionProvider;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
Expand All @@ -44,6 +47,7 @@ public class HtmlAggregateStoryReporter extends HtmlReporter implements UserStor

private static final String HISTORY_TEMPLATE_PATH = "freemarker/history.ftl";
private static final String TEST_OUTCOME_TEMPLATE_PATH = "freemarker/home.ftl";
private static final String BUILD_INFO_TEMPLATE_PATH = "freemarker/build-info.ftl";
private static final String RELEASES_TEMPLATE_PATH = "freemarker/releases.ftl";
private static final String RELEASE_TEMPLATE_PATH = "freemarker/release.ftl";
private static final String TAGTYPE_TEMPLATE_PATH = "freemarker/results-by-tagtype.ftl";
Expand Down Expand Up @@ -115,6 +119,12 @@ private void addFormattersToContext(final Map<String, Object> context) {
context.put("reportOptions", new ReportOptions(getEnvironmentVariables()));
}

private void addBuildInformationToContext(final Map<String, Object> context) {
BuildInfoProvider buildInfoProvider = new BuildInfoProvider(getEnvironmentVariables());
context.put("build", buildInfoProvider.getBuildProperties());
}


public TestOutcomes generateReportsForTestResultsFrom(final File sourceDirectory) throws IOException {
TestOutcomes allTestOutcomes = loadTestOutcomesFrom(sourceDirectory);
copyScreenshotsFrom(sourceDirectory);
Expand Down Expand Up @@ -247,6 +257,7 @@ private void generateAggregateReportFor(TestOutcomes testOutcomes) throws IOExce
context.put("csvReport", "results.csv");

generateReportPage(context, TEST_OUTCOME_TEMPLATE_PATH, "index.html");
generateReportPage(context, BUILD_INFO_TEMPLATE_PATH, "build-info.html");
generateCSVReportFor(testOutcomes, "results.csv");
logReportPathMessage();
}
Expand Down Expand Up @@ -471,6 +482,7 @@ private Map<String, Object> buildContext(TestOutcomes testOutcomesForTagType,
context.put("serenityVersionNumber", versionProvider.getVersion());
context.put("buildNumber", versionProvider.getBuildNumberText());

addBuildInformationToContext(context);
return context;
}

Expand Down
Loading

0 comments on commit fe1ab3e

Please sign in to comment.