Java library for screenshot based testing with Selenium and Allure reporting
Benefits:
- Easy screenshot comparison for page elements from the box.
- Possibility to ignore different diffs by element, area or diff hash code.
- Allure report integration from the box.
- Easy customization of any part.
- Possibility to take whole page screenshots on mobile devices.
Maven:
<dependency>
<groupId>io.github.rovner</groupId>
<artifactId>screenshot-assert-core</artifactId>
<version>1.0.0</version>
<scope>test</scope>
</dependency>
<!--extension for junit 5-->
<dependency>
<groupId>io.github.rovner</groupId>
<artifactId>screenshot-assert-junit5</artifactId>
<version>1.0.0</version>
<scope>test</scope>
</dependency>
Gradle:
testImplementation 'io.github.rovner:screenshot-assert-core:1.0.0'
//extension for junit 5
testImplementation 'io.github.rovner:screenshot-assert-junit5:1.0.0'
- Junit5 with hard assertions
//junit5 with hard assertions
@RegisterExtension
ScreenshotAssertExtension screenshotAssert = new ScreenshotAssertExtension(()->webDriver);
@Test
void test(){
//test actions
screenshotAssert.assertThat(screenshotOfViewport())
.isEqualToReferenceId("some_reference_id");
}
- Junit5 with soft assertions
@RegisterExtension
private final SoftScreenshotAssertExtension softScreenshotAssert = new SoftScreenshotAssertExtension(()->wd);
@Test
void test(){
//test actions
screenshotAssert.assertThat(screenshotOfElementFoundBy(cssSelector(".element-1")))
.isEqualToReferenceId("element_reference_1");
screenshotAssert.assertThat(screenshotOfElementFoundBy(cssSelector(".element-2")))
.isEqualToReferenceId("element_reference_2");
}
- No framework with hard assertions
ScreenshotAssertBuilder screenshotAssert = ScreenshotAssertBuilder.builder()
.setWebDriver(wd)
.setReferenceStorage(new DefaultReferenceStorage(Paths.get("some/path/to/references")));
@Test
void test(){
//test actions
screenshotAssert.assertThat(screenshotOfViewport())
.isEqualToReferenceId("some_reference_id");
}
- No framework with soft assertions
ScreenshotAssertBuilder screenshotAssert = ScreenshotAssertBuilder.builder()
.setWebDriver(wd)
.setReferenceStorage(new DefaultReferenceStorage(Paths.get("some/path/to/references")))
.setSoft(true);
@Test
void test(){
//test actions
screenshotAssert.assertThat(screenshotOfElementFoundBy(cssSelector(".element-1")))
.setReferenceStorage("element_reference_1");
screenshotAssert.assertThat(screenshotOfElementFoundBy(cssSelector(".element-2")))
.isEqualToReferenceId("element_reference_2");
}
See more in examples
- Of viewport (part of the document visible in window).
screenshotAssert.assertThat(Screenshots.screenshotOfViewport())
.isEqualToReferenceId("id");
- Of whole page (document). Be cautious with method because it scrolls page and could change it state.
screenshotAssert.assertThat(Screenshots.screenshotOfWholePage())
.isEqualToReferenceId("id");
- Of some area by coordinates in the view port. Coordinates are relative to the viewport.
screenshotAssert.assertThat(Screenshots.screenshotOfViewportArea(20,140,640,120))
.isEqualToReferenceId("id");
- Of some area by coordinates in the whole page. Coordinates are relative to the document. Be cautious with method because it scrolls page and could change it state.
screenshotAssert.assertThat(Screenshots.screenshotOfOageArea(20,140,640,120))
.isEqualToReferenceId("id");
- Of web element (for browsers).
WebElement element = webDriver.findElement(cssSelector(".element"));
screenshotAssert.assertThat(Screenshots.screenshotOfElement(element))
.isEqualToReferenceId("id");
- Of web element locatable by selector (for browsers).
screenshotAssert.assertThat(Screenshots.screenshotOfElementFoundBy(cssSelector(".element")))
.isEqualToReferenceId("id");
- Of native element (for native apps).
WebElement element = webDriver.findElement(id("id"));
screenshotAssert.assertThat(Screenshots.screenshotOfNativeElement(element))
.isEqualToReferenceId("id");
- Of native element locatable by selector (for native apps).
screenshotAssert.assertThat(Screenshots.screenshotOfNativeElementFoundBy(id("id")))
.isEqualToReferenceId("id");
See all types
- Of viewport area.
screenshotAssert.assertThat(screenshotOfViewport())
.ignoring(area(10, 10, 40, 50))
.ignoring(area(new Rectangle(60, 30, 10, 20))) //pay attention to order of arguments
.isEqualToReferenceId("id");
- Of element/elements.
WebElement element=webDriver.findElement(cssSelector(".element"));
screenshotAssert.assertThat(screenshotOfViewport())
.ignoring(element(element))
.isEqualToReferenceId("id");
- Of elements found by selector.
screenshotAssert.assertThat(screenshotOfViewport())
.ignoring(elementBy(cssSelector(".element")))
.isEqualToReferenceId("id");
- Of diff hash codes.
screenshotAssert.assertThat(screenshotOfViewport())
.ignoring(hashes(123,321)) //diff hash could be found in allure report
.isEqualToReferenceId("id");
Add file named screenshot-assert.properties
to resources dir or use -D
properties
- Property:
io.github.rovner.screenshot.assert.is.update.reference.image
.
Default:false
.
Whatever save actual image as reference when there is difference. Useful to update images after changes. - Property:
io.github.rovner.screenshot.assert.is.save.reference.image.when.missing
.
Default:true
.
Whatever save actual image as reference when no reference exists. Recommended to set tofalse
on CI. - Property:
io.github.rovner.screenshot.assert.is.soft
.
Default:false
.
Makes all assertions soft. - Property:
io.github.rovner.screenshot.assert.references.base.dir
Default:src/test/resources/references
[Only for junit5] Base directory where screenshots will be stored.
Screenshots provided by appium from mobile devices besides the viewport contain additional parts(phone bar, browser bar) as well. The height and location of these parts are different on different browsers/devices so such configurations should be done in the target test/framework with knowledge of what devices are used. Here are some examples of how it could be achieved:
//iphone 13
@RegisterExtension
private final ScreenshotAssertExtension screenshotAssert = new ScreenshotAssertExtension(() -> wd)
.scrollSleepTimeout(ofMillis(100))
.viewportCropper(aggregating(fixedHeaderCutting(140), floatingFooterCutting()));
//ipad 9th generation
@RegisterExtension
private final ScreenshotAssertExtension screenshotAssert = new ScreenshotAssertExtension(() -> wd)
.scrollSleepTimeout(ofMillis(100))
.scrollMarginPixels(16)
.viewportCropper(floatingHeaderCutting());
//android Pixel 5
@RegisterExtension
private final ScreenshotAssertExtension screenshotAssert = new ScreenshotAssertExtension(() -> wd)
.scrollSleepTimeout(ofSeconds(1))
.scrollMarginPixels(8)
.viewportCropper(aggregating(capabilities(), floatingHeaderCutting()));
//android Pixel C
@RegisterExtension
private final ScreenshotAssertExtension screenshotAssert = new ScreenshotAssertExtension(() -> wd)
.scrollSleepTimeout(ofSeconds(1))
.scrollMarginPixels(60)
.viewportCropper(aggregating(fixedFooterCutting(120), floatingHeaderCutting()));
//selecting cropper in runtime
@RegisterExtension
private final ScreenshotAssertExtension screenshotAssert = new ScreenshotAssertExtension(() -> wd)
.scrollSleepTimeout(ofSeconds(500))
.viewportCropper(matching()
.match(isDesktop(), desktop())
.match(isIos().and(isIpad()).and(isSafari()), floatingHeaderCutting())
.match(isIos().and(isIphone()).and(isSafari()), aggregating(fixedHeaderCutting(140), floatingFooterCutting()))
.match(isAndroid(), aggregating(capabilities(), floatingHeaderCutting()))
);
See more in examples
-
To change how diff is represented in allure implement AllureListener
-
To change how screenshot is cropped implement ImageCropper
-
To change how viewport is cropped implement ViewportCropper
-
To change how screenshot is compared to reference implement ImageDiffer
-
To add custom ignoring implement Ignoring
-
To change how references are stored implement ReferenceStorage
-
To add custom screenshot implement Screenshot
-
To change how soft assertions are handled implement SoftExceptionCollector
-
To change how images are scaled implement ImageScaler
-
To change how device pixel ratio is detected implement DprDetector