Page tree
Skip to end of metadata
Go to start of metadata

Last updated: Feb 03, 2021 10:41

This article walks you through a sample integration of Perfecto 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.

Happy Testing!

Step-by-step guide

Take your existing Galen Framework. You can also download this one: https://github.com/galenframework/galen-sample-java-tests

1 | Update the pom.xml file

After importing the project as a Maven Project locating the POM file, update this file with all the dependencies you need.

On this page:

  1. For more convenience, take the version to the top of the file in the Properties section, as follows.

    "properties" section in POM file
    	<properties>
    		<reportium-sdk.version>2.2.9</reportium-sdk.version>
    	</properties>
  2. Add the following repository.

    "repositories" 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>
  3. Add the following dependencies.

    "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.

    POM.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>
    
    

2 | Update the GalenTestBase class

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.

  1. Locate the following file: …\galen-sample-java-tests-master\src\test\java\com\galenframework\java\sample\components
  2. Do the following imports. They are recommended. If you do not use them, you can delete them later.

    Imports
    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;
  3. Declare the following.

    Declarations
    public static ReportiumClient reportiumClient;
    public RemoteWebDriver driver = null;
    public boolean needReportStop = true;
  4. Create your driver, as follows.

    Driver
    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);
  5. Enable reporting. The following example shows the more advanced implementation version, which is recommended.

    Reporting 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 https://developers.perfectomobile.com/display/PD/Test+analysis+with+Smart+Reporting
    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);
  6. Implement the reporting start as follows.

    Start Reporting
    reportiumClient.testStart("Quick Galen Smoke Test", new TestContext("smoke", "test", "galen"));
  7. Add the following methods to stop reporting depending on the test result.

    1. If the test fails with an error, add the following:

      Reporting error
      public void stopReportingFail(Exception e) {
          System.out.print("\n fail after test \n");
          reportiumClient.testStop(TestResultFactory.createFailure(e));
          e.printStackTrace();
          needReportStop = false;
      }
    2. If the test succeeds, add the following:

      Reporting 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");
      }
  8. Add the following at the very end.

    ReportuimClient
    public static  ReportiumClient getReportiumClient() {
    		return reportiumClient;
    	}

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 https://developers.perfectomobile.com/display/PD/Test+analysis+with+Smart+Reporting
        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;
	}
}


3 | Update the GalenSmokeTest class

Now let's focus on updating the GalenSmokeTest class.

  1. Import the following:

    Import
    importio.IOException;
  2. Structure the code so the test gets enclosed in a try-catch and its exceptions get caught (do not forget to add “throws IOException”).

    Test 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);
        }
    }
}


4 | Add the library

Last, let's focus on the library you need to add/create.

  1. Inside the src/test/java folder, create a Package with the name "com.galenframework.support".
  2. Inside that package, create a class with the name "LayoutValidationException".
  3. Fill the newly created class with the following code:

    LayoutValidationException.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;
        }
    }