Galen is a layout testing framework developed by Ivan Shubin. It is an open-source project that you can support (https://github.com/galenframework/galen ).
- It is an automated layout and responsive testing framework.
- Tests locations of objects relatively to each other on the page.
- Runs in Selenium Grid. (SauceLabs & BrowserStack)
You can test responsive websites on different mobile devices. - Supports Parallel Testing
Thus, tests run faster and we save time. - Responsive Design Tests are easy with Galen.
Opens -> Resizes -> Tests with given specifications. - Galen has an own DSL which specifies the constraints about the layout design.
Programming Language Support?
- Basic Syntax
- JavaScript Tests
- Java & Selenium Webdriver
Galen Reporting
- Error Reporting
Generates Html reports where you can see all your test objects. - ScreenShots
Highlights the misaligned elements. - Image Comparison
Compares images and shows differences
Galen Example with JAVA & Webdriver
Note: You can find source code of the sample project at below page:
https://github.com/swtestacademy/galenswtestacademy
Step-1: Add Galen Maven Dependency to the pom.xml
<dependencies>
<dependency>
<groupId>com.galenframework</groupId>
<artifactId>galen-java-support</artifactId>
<version>2.0.3</version>
</dependency>
</dependencies>Step-2: Create a Selenium Maven Test Project
Create an empty test class as shown below:
Resize the browser for 1200×800 resolution and go to swtestacademy.com:
import com.galenframework.api.Galen;
import com.galenframework.reports.GalenTestInfo;
import com.galenframework.reports.HtmlReportBuilder;
import com.galenframework.reports.model.LayoutReport;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.openqa.selenium.Dimension;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import java.io.IOException;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
/**
* Created by can on 29/01/17.
*/
public class GalenExampleTest
{
private WebDriver driver;
@Before
public void setUp()
{
//Create a Chrome Driver
driver = new ChromeDriver();
//Set the browser size for desktop
driver.manage().window().setSize(new Dimension(1200, 800));
//Go to swtestacademy.com
driver.get("https:/");
}
@After
public void tearDown()
{
driver.quit();
}
}
In order to check the layout, we need to use LayoutReport class and instantiate a layoutReport object and assign it to Galen.checkout(param1, param2, param3). Here Galen.checkout function has three parameters:
param1 = webdriver instance (it is our driver object)
param2 = .gspec file
param3 = it is a tag for a specific layout
LayoutReport layoutReport = Galen.checkLayout(driver, "specs/homepage.gspec", Arrays.asList("desktop”));Above code will generate an HTML report based on homepage.gspec file. You can find this report under tartget/ directory and test code should be like that:
@Test
public void homePageLayoutTest() throws IOException
{
//Create a layoutReport object
//checkLayout function checks the layout and returns a LayoutReport object
LayoutReport layoutReport = Galen.checkLayout(driver, "specs/homepage.gspec", Arrays.asList("desktop"));
//Create a tests list
List<GalenTestInfo> tests = new LinkedList<GalenTestInfo>();
//Create a GalenTestInfo object
GalenTestInfo test = GalenTestInfo.fromString("homepage layout");
//Get layoutReport and assign to test object
test.getReport().layout(layoutReport, "check homepage layout");
//Add test object to the tests list
tests.add(test);
//Create a htmlReportBuilder object
HtmlReportBuilder htmlReportBuilder = new HtmlReportBuilder();
//Create a report under /target folder based on tests list
htmlReportBuilder.build(tests, "target");
//If layoutReport has errors Assert Fail
if (layoutReport.errors() > 0)
{
Assert.fail("Layout test failed");
}
}Now, you have to create a Galen Specification (.gspec) file under resources folder to describe your website’s layout and rules. If you want to do image comparison, you should also add baseline image under this folder. Under the “target” folder we will generate test reports.
Step-3: Write a Galen Spec File
This gspec (Galen Spec) fileis for swtestacademy.com’s home page and it consists of many controls and checks such as:
- Alignment control
- Image comparison
- Below check
- Above check
#Declaring objects with css and xpath locators
@objects
header css div.fusion-secondary-header
sw-logo css .fusion-logo-link
#Navigation links are multi-line object type. Thus, we add * at the end of its decleration.
navigation-links-* xpath //ul[@id='menu-main']/li[not((contains(@id,'mobile-menu-item')))]
nav-menu css div.fusion-secondary-main-menu
follow-us-box xpath //div[contains(@class,'fusion-alert')][1]
#Home Page Tag
= Home Page =
#This is for Desktop
@on desktop
#Header properties
header:
inside screen 0px top
inside screen 0px left
inside screen 0px right
#Logo properties
sw-logo:
#31 px below the header
below header 31px
#Image comparison with %2 precision ratio
image file sw-logo.png, error %5
#Each navigation links must be alligned horizontally to each other
#itemName -> Current item and nextItem -> Next item
@forEach [navigation-links-*] as itemName, next as nextItem
${itemName}:
aligned horizontally all ${nextItem}
#Navigation menu must be 20px above to the follow us allert box
nav-menu:
above follow-us-box 20px
@On Mening:
Quite often you need to declare different specs for different conditions (e.g. various devices like mobile, tablet, desktop etc.). You can specify tags in your spec file so that it is easier to manage your layout testing. You can wrap all your checks inside @on statement like this:
= Main section =
@on mobile
menu:
height 300 px
@on desktop
menu:
height 40 pxIn case your specs apply to all of the tags you can express that by using * symbol:
= Main section =
@on *
menu:
height 70px
@on mobile
login-button:
width 100pxYou can also combine multiple tags using comma-separated tag notation
= Main section =
@on mobile, desktop
menu:
height 300 pxImage Comparison:
As for image comparison – it is applied differently. Instead of comparing the complete page screenshot you can choose which specific element you would like to compare. And for each image comparison you can tune the algorithm with different settings (e.g. color tolerance, error rate etc.) and custom image filters (e.g. blur, saturation, quantinize, denoise). If you want to know more you can watch the video where it is explained how to prepare individual image samples and configure the image comparison for elements with noise background.
Ref: https://www.youtube.com/watch?v=bheFQfEGR6U
Step-4: HTML Reporting
When you run the code,
1- If there is a image comparison error, it will highlight it as follows:
2- Also, when we click the “Showimage comparison” link, it shows the mismatches:
3- If there is a layout error, it will highlight it as shown below:
4- Also, we can see the elements heat-map as follows:
5- Successful HTML report will look like this:
Thanks.
-Can

I am working as SDET at sahibinden.com and currently dealing with Software Testing and Test Automation. I also post my articles to my blog: http://cyildirim.com









Good info
Thanks, @Nalini. :)
Güzel makale olmuş. Elinize sağlık :)
Can Yıldırım’a teşekkür ediyoruz. :)
Hi Nice article, I have one query
I am running script parallel through testng.xml
But HTML report is not generated for both browser which i have mentioned in xml
I haven’t tried layout testing in parallel Stephen. Maybe Can Yıldırım has knowledge of this. It is better to put some breakpoints and debug your project. Maybe you will get some insights.
HeatMap is not generating
It is Galen’s problem. Please open a ticket on Galen project.
Hi, Thanks for creating such a nice article, I have just cloned the code into my PC and tried to execute the tests and finally ended up with error, following is the error details, could you help me in resolving the issue
ReferenceError: “org” is not defined.
(; line 1)
at org.mozilla.javascript.NativeGlobal.constructError(NativeGlobal.java:597)
at org.mozilla.javascript.NativeGlobal.constructError(NativeGlobal.java:557)
at org.mozilla.javascript.ScriptRuntime.name(ScriptRuntime.java:1076)
at org.mozilla.javascript.gen.c2.call(:1)
at org.mozilla.javascript.gen.c2.exec()
at org.mozilla.javascript.Context.evaluateReader(Context.java:820)
at org.mozilla.javascript.Context.evaluateString(Context.java:784)
at com.galenframework.javascript.GalenJsExecutor.importClasses(GalenJsExecutor.java:85)
at com.galenframework.javascript.GalenJsExecutor.importAllMajorClasses(GalenJsExecutor.java:62)
at com.galenframework.javascript.GalenJsExecutor.(GalenJsExecutor.java:58)
at com.galenframework.speclang2.pagespec.PageSpecHandler.createGalenJsExecutor(PageSpecHandler.java:97)
at com.galenframework.speclang2.pagespec.PageSpecHandler.(PageSpecHandler.java:65)
at com.galenframework.speclang2.pagespec.PageSpecReader.read(PageSpecReader.java:59)
at com.galenframework.speclang2.pagespec.PageSpecReader.read(PageSpecReader.java:45)
at com.galenframework.api.Galen.checkLayout(Galen.java:68)
at com.galenframework.api.Galen.checkLayout(Galen.java:59)
at com.galenframework.api.Galen.checkLayout(Galen.java:155)
at com.galenframework.api.Galen.checkLayout(Galen.java:129)
at com.sample.test.screens.GalenFrameworkTest.checkLogoVisibleAndImageVerification(GalenFrameworkTest.java:64)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:86)
at org.testng.internal.Invoker.invokeMethod(Invoker.java:643)
at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:820)
at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1128)
at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:129)
at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:112)
at org.testng.TestRunner.privateRun(TestRunner.java:782)
at org.testng.TestRunner.run(TestRunner.java:632)
at org.testng.SuiteRunner.runTest(SuiteRunner.java:366)
at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:361)
at org.testng.SuiteRunner.privateRun(SuiteRunner.java:319)
at org.testng.SuiteRunner.run(SuiteRunner.java:268)
at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
at org.testng.TestNG.runSuitesSequentially(TestNG.java:1244)
at org.testng.TestNG.runSuitesLocally(TestNG.java:1169)
at org.testng.TestNG.run(TestNG.java:1064)
at com.intellij.rt.testng.IDEARemoteTestNG.run(IDEARemoteTestNG.java:66)
at com.intellij.rt.testng.RemoteTestNGStarter.main(RemoteTestNGStarter.java:109)
I need to re-create the error on my machine but now I am using MAC. I am not sure I can reproduce this error on my machine.
But I found this page: https://stackoverflow.com/questions/8982551/getting-java-io-ioexception-when-running-junit-test-case-in-eclipse-continued
It may be because of the old library. Please try to update the library versions in pom.xml and re-try.