Integrate Galen Framework with Perfecto Smart Reporting
Learn how to set up a sample integration of Perfecto Smart Reporting with your existing Galen Framework for visual analysis. This implementation ensures that your tests and results will appear in Perfecto Smart Reporting at https://<your-cloud>.app.perfectomobile.com/reporting
.
Step-by-step guide
Take your existing Galen Framework or download this one: https://github.com/galenframework/galen-sample-java-tests
Click a step to view details.
After importing the project as a Maven Project locating the POM file, update this file with all the dependencies you need.
-
For more convenience, take the version to the top of the file in the Properties section, as follows.
Copy"properties" section in POM file<properties>
<reportium-sdk.version>2.2.9</reportium-sdk.version>
</properties> -
Add the following repository.
Copyrepositories" section in POM file<repositories>
<repository>
<id>repo1.perfectomobile.com</id>
<name>Perfecto mobile</name>
<url>https://repo1.perfectomobile.com/public/repositories/maven</url>
</repository>
</repositories> -
Add the following dependencies.
Copy"dependencies" section in POM file
<dependencies>
...
<dependency>
<groupId>com.perfectomobile</groupId>
<artifactId>pm-webdriver</artifactId>
<version>18.6.0.0</version>
</dependency>
<dependency>
<groupId>com.perfectomobile</groupId>
<artifactId>http-client</artifactId>
<version>18.6.0.0</version>
</dependency>
<dependency>
<groupId>com.perfecto.reporting-sdk</groupId>
<artifactId>reportium-java</artifactId>
<version>${reportium-sdk.version}</version>
</dependency>
<dependency>
<groupId>com.perfecto.reporting-sdk</groupId>
<artifactId>reportium-testng</artifactId>
<version>${reportium-sdk.version}</version>
</dependency>
...
</dependencies>Following is an example of the whole class.
CopyPOM.xml
<?xml version="1.0"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.galenframework</groupId>
<artifactId>galen-java-sample-tests</artifactId>
<version>0.1-SNAPSHOT</version>
<name>Galen Framework Sample Java Test Project</name>
<packaging>jar</packaging>
<description>A test project for testing Galen using Java-based tests</description>
<properties>
<reportium-sdk.version>2.2.9</reportium-sdk.version>
</properties>
<repositories>
<repository>
<id>repo1.perfectomobile.com</id>
<name>Perfecto mobile</name>
<url>https://repo1.perfectomobile.com/public/repositories/maven</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-all</artifactId>
<version>1.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>6.7</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.galenframework</groupId>
<artifactId>galen-java-support</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>com.perfectomobile</groupId>
<artifactId>pm-webdriver</artifactId>
<version>18.6.0.0</version>
</dependency>
<dependency>
<groupId>com.perfectomobile</groupId>
<artifactId>http-client</artifactId>
<version>18.6.0.0</version>
</dependency>
<dependency>
<groupId>com.perfecto.reporting-sdk</groupId>
<artifactId>reportium-java</artifactId>
<version>${reportium-sdk.version}</version>
</dependency>
<dependency>
<groupId>com.perfecto.reporting-sdk</groupId>
<artifactId>reportium-testng</artifactId>
<version>${reportium-sdk.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.17</version>
<configuration>
<properties>
<property><name>usedefaultlisteners</name><value>false</value></property>
<property>
<name>listener</name>
<value>com.galenframework.testng.GalenTestNgReportsListener</value>
</property>
</properties>
</configuration>
</plugin>
</plugins>
</build>
<licenses>
<license>
<name>The Apache Software License, Version 2.0</name>
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
<distribution>manual</distribution>
</license>
</licenses>
</project>
After we have updated the POM file, we can focus on the code. Let's start by adding the needed lines in the GalenTestBase class.
- Locate the following file: …\galen-sample-java-tests-master\src\test\java\com\galenframework\java\sample\components
-
Do the following imports. They are recommended. If you do not use them, you can delete them later.
CopyImports
import com.perfecto.reportium.client.ReportiumClient;
import com.perfecto.reportium.client.ReportiumClientFactory;
import com.perfecto.reportium.model.CustomField;
import com.perfecto.reportium.model.Job;
import com.perfecto.reportium.model.PerfectoExecutionContext;
import com.perfecto.reportium.model.Project;
import com.perfecto.reportium.test.TestContext;
import com.perfecto.reportium.test.result.TestResultFactory;
import org.openqa.selenium.Dimension;
import java.util.concurrent.TimeUnit;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date; -
Declare the following.
CopyDeclarations
public static ReportiumClient reportiumClient;
public RemoteWebDriver driver = null;
public boolean needReportStop = true; -
Create your driver, as follows.
CopyDriver
DesiredCapabilities capabilities = new DesiredCapabilities("", "", Platform.ANY);
String host = "your-cloud.perfectomobile.com";
//Capabilities
capabilities.setCapability("securityToken", "<YourTokenHere>");
capabilities.setCapability("platformName", "Windows");
capabilities.setCapability("platformVersion", "10");
capabilities.setCapability("browserName", "Chrome");
capabilities.setCapability("browserVersion", "latest");
capabilities.setCapability("resolution", "1024x768");
//Driver creation
try {
driver = new RemoteWebDriver(new URL("https://" + host + "/nexperience/perfectomobile/wd/hub/fast"), capabilities);
} catch (MalformedURLException e) {
e.printStackTrace();
}
driver.manage().timeouts().implicitlyWait(15, TimeUnit.SECONDS); -
Enable reporting. The following example shows the more advanced implementation version, which is recommended.
CopyReporting creation
//Smart reporting:
SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd");
Date today = Calendar.getInstance().getTime();
String reportDate = df.format(today);
int date_CIjob= Integer.parseInt(reportDate);
// Reporting client. For more details, see ../Perfecto/test-analysis/test_analysis_with_smart_reporting.htm
PerfectoExecutionContext perfectoExecutionContext = new PerfectoExecutionContext.PerfectoExecutionContextBuilder()
.withProject(new Project("Test Project", "1.0"))
.withJob(new Job("Nato Galen Smoke Test", date_CIjob))
.withContextTags("test")
.withCustomFields(new CustomField("myCustomField", "test2"))
.withWebDriver(driver)
.build();
reportiumClient = new ReportiumClientFactory().createPerfectoReportiumClient(perfectoExecutionContext); -
Implement the reporting start as follows.
CopyStart Reporting
reportiumClient.testStart("Quick Galen Smoke Test", new TestContext("smoke", "test", "galen"));
-
Add the following methods to stop reporting depending on the test result.
-
If the test fails with an error, add the following:
CopyReporting error
public void stopReportingFail(Exception e) {
System.out.print("\n fail after test \n");
reportiumClient.testStop(TestResultFactory.createFailure(e));
e.printStackTrace();
needReportStop = false;
} -
If the test succeeds, add the following:
CopyReporting success
public void stopReportingSuccess() {
System.out.println(needReportStop);
if (needReportStop==true) {
try {
System.out.print("\n success \n");
reportiumClient.testStop(TestResultFactory.createSuccess());
}catch (Exception ex){
ex.printStackTrace();
}
}
System.out.print("\n stop after test \n");
}
-
-
Add the following at the very end.
Following is an example of the whole class.
GalenTestBase.java
package com.galenframework.java.sample.components;
import com.galenframework.testng.GalenTestNgTestBase;
import com.perfecto.reportium.client.ReportiumClient;
import com.perfecto.reportium.client.ReportiumClientFactory;
import com.perfecto.reportium.model.CustomField;
import com.perfecto.reportium.model.Job;
import com.perfecto.reportium.model.PerfectoExecutionContext;
import com.perfecto.reportium.model.Project;
import com.perfecto.reportium.test.TestContext;
import com.perfecto.reportium.test.result.TestResultFactory;
import org.openqa.selenium.Dimension;
import org.openqa.selenium.Platform;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.testng.annotations.DataProvider;
import java.util.List;
import java.util.concurrent.TimeUnit;
import static java.util.Arrays.asList;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
public abstract class GalenTestBase extends GalenTestNgTestBase {
public static ReportiumClient reportiumClient;
public RemoteWebDriver driver = null;
public boolean needReportStop = true;
private final String ENV_URL = "http://testapp.galenframework.com";
//private final String ENV_URL = "https://www.perfecto.io";
@Override
public WebDriver createDriver(Object[] args) {
System.out.println("Run started");
DesiredCapabilities capabilities = new DesiredCapabilities("", "", Platform.ANY);
String host = "your-cloud.perfectomobile.com";
//Capabilities
capabilities.setCapability("securityToken", "<YourTokenHere>");
capabilities.setCapability("platformName", "Windows");
capabilities.setCapability("platformVersion", "10");
capabilities.setCapability("browserName", "Chrome");
capabilities.setCapability("browserVersion", "latest");
capabilities.setCapability("resolution", "1024x768");
//Driver creation
try {
driver = new RemoteWebDriver(new URL("https://" + host + "/nexperience/perfectomobile/wd/hub/fast"), capabilities);
} catch (MalformedURLException e) {
e.printStackTrace();
}
driver.manage().timeouts().implicitlyWait(15, TimeUnit.SECONDS);
//Smart reporting:
SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd");
Date today = Calendar.getInstance().getTime();
String reportDate = df.format(today);
int date_CIjob= Integer.parseInt(reportDate);
// Reporting client. For more details, see ../Perfecto/test-analysis/test_analysis_with_smart_reporting.htm
PerfectoExecutionContext perfectoExecutionContext = new PerfectoExecutionContext.PerfectoExecutionContextBuilder()
.withProject(new Project("Test Project", "1.0"))
.withJob(new Job("Nato Galen Smoke Test", date_CIjob))
.withContextTags("test")
.withCustomFields(new CustomField("myCustomField", "test2"))
.withWebDriver(driver)
.build();
reportiumClient = new ReportiumClientFactory().createPerfectoReportiumClient(perfectoExecutionContext);
reportiumClient.testStart("Quick Galen Smoke Test", new TestContext("smoke", "test", "galen"));
/*WebDriver driver = new FirefoxDriver();
if (args.length > 0) {
if (args[0] != null && args[0] instanceof TestDevice) {
TestDevice device = (TestDevice)args[0];
if (device.getScreenSize() != null) {
driver.manage().window().setSize(device.getScreenSize());
}
}
}*/
return driver;
}
public void stopReportingFail(Exception e) {
System.out.print("\n fail after test \n");
reportiumClient.testStop(TestResultFactory.createFailure(e));
e.printStackTrace();
needReportStop = false;
}
public void stopReportingSuccess() {
System.out.println(needReportStop);
if (needReportStop==true) {
try {
System.out.print("\n success \n");
reportiumClient.testStop(TestResultFactory.createSuccess());
}catch (Exception ex){
ex.printStackTrace();
}
}
System.out.print("\n stop after test \n");
}
public void load(String uri) {
getDriver().get(ENV_URL + uri);
}
@DataProvider(name = "devices")
public Object [][] devices () {
return new Object[][] {
//{new TestDevice("mobile", new Dimension(450, 800), asList("mobile"))},
//{new TestDevice("tablet", new Dimension(750, 800), asList("tablet"))},
{new TestDevice("desktop", new Dimension(1024, 768), asList("desktop"))}
};
}
public static class TestDevice {
private final String name;
private final Dimension screenSize;
private final List<String> tags;
public TestDevice(String name, Dimension screenSize, List<String> tags) {
this.name = name;
this.screenSize = screenSize;
this.tags = tags;
}
public String getName() {
return name;
}
public Dimension getScreenSize() {
return screenSize;
}
public List<String> getTags() {
return tags;
}
@Override
public String toString() {
return String.format("%s %dx%d", name, screenSize.width, screenSize.height);
}
}
public static ReportiumClient getReportiumClient() {
return reportiumClient;
}
}
Now let's focus on updating the GalenSmokeTest class.
-
Import the following:
-
Structure the code so the test gets enclosed in a try-catch and its exceptions get caught (do not forget to add “throws IOException”).
CopyTest method
public void welcomePage_shouldLookGood_onDevice(TestDevice device) throws IOException {
try {
load("/");
checkLayout("/specs/welcomePage.spec", device.getTags());
stopReportingSuccess();
}
catch (Exception e){
stopReportingFail(e);
}
}
Following is an example of the whole class.
GalenSmokeTest.java
package com.galenframework.java.sample.tests;
import com.galenframework.java.sample.components.GalenTestBase;
import org.openqa.selenium.By;
import org.testng.annotations.Test;
import java.io.IOException;
public class GalenSmokeTest extends GalenTestBase {
@Test(dataProvider = "devices")
public void welcomePage_shouldLookGood_onDevice(TestDevice device) throws IOException {
try {
load("/");
checkLayout("/specs/welcomePage.spec", device.getTags());
stopReportingSuccess();
}
catch (Exception e){
stopReportingFail(e);
}
}
//@Test(dataProvider = "devices")
public void loginPage_shouldLookGood_onDevice(TestDevice device) throws IOException {
try {
load("/");
getDriver().findElement(By.xpath("//button[.='Login']")).click();
checkLayout("/specs/loginPage.spec", device.getTags());
stopReportingSuccess();
}
catch (Exception e){
stopReportingFail(e);
}
}
}
Last, let's focus on the library you need to add/create.
- Inside the src/test/java folder, create a Package with the name "com.galenframework.support".
- Inside that package, create a class with the name "LayoutValidationException".
-
Fill the newly created class with the following code:
CopyLayoutValidationException.java
package com.galenframework.support;
import com.galenframework.java.sample.components.GalenTestBase;
import com.galenframework.reports.model.LayoutReport;
import com.galenframework.reports.nodes.LayoutReportNode;
import com.galenframework.speclang2.pagespec.SectionFilter;
import com.galenframework.validation.ValidationResult;
import java.util.List;
public class LayoutValidationException extends RuntimeException {
private static final String ERROR_INDENTATION = " ";
private final LayoutReport layoutReport;
public LayoutValidationException(String specPath, LayoutReport layoutReport, SectionFilter sectionFilter) {
super(createMessage(specPath, layoutReport, sectionFilter));
this.layoutReport = layoutReport;
}
public LayoutReport getLayoutReport() {
return layoutReport;
}
public static String createMessage(String specPath, LayoutReport layoutReport, SectionFilter sectionFilter) {
try {
StringBuilder messageBuilder = new StringBuilder()
.append(specPath);
if (sectionFilter != null) {
if (sectionFilter.getIncludedTags() != null && !sectionFilter.getIncludedTags().isEmpty()) {
messageBuilder.append(", tags: ").append(sectionFilter.getIncludedTags()).append("\n");
}
if (sectionFilter.getExcludedTags() != null && !sectionFilter.getExcludedTags().isEmpty()) {
messageBuilder.append(", excludedTags: ").append(sectionFilter.getExcludedTags()).append("\n");
}
}
messageBuilder.append(collectAllErrors(layoutReport.getValidationErrorResults()));
return messageBuilder.toString();
} catch (Exception ex) {
return specPath;
}
}
private static StringBuilder collectAllErrors(List<ValidationResult> validationErrorResults) {
return collectAllErrors(validationErrorResults, ERROR_INDENTATION);
}
private static StringBuilder collectAllErrors(List<ValidationResult> validationErrorResults, String indentation) {
StringBuilder builder = new StringBuilder();
if (validationErrorResults != null) {
String childIndentation = indentation + ERROR_INDENTATION;
for (ValidationResult validationResult : validationErrorResults) {
for (String errorMessage : validationResult.getError().getMessages()) {
builder.append(indentation)
.append("- ")
.append(errorMessage);
GalenTestBase.getReportiumClient().reportiumAssert(errorMessage, false);
System.out.println(errorMessage);
if (validationResult.getSpec() != null && validationResult.getSpec().getPlace() != null) {
builder.append(" (").append(validationResult.getSpec().getPlace().toPrettyString()).append(")");
}
builder.append("\n");
}
builder.append(collectAllErrors(validationResult.getChildValidationResults(), childIndentation));
}
}
return builder;
}
}
Related articles
See also the Perfecto Knowledgebase.