Visual Testing

Resizing the browser or an element

In some cases there may be a need to make sure that the browser always has predefined dimensions. This is useful, for example, when capturing/asserting images. There are two classes that allow to do it:

Example use:

try (WindowResizer windowResizer = new WindowResizer(1000, 768)) {
    try (ElementResizer elementResizer = new ElementResizer(div.that(hasClass("widget-pane")), 600, 400)) {
        System.out.println(String.format("element total dimensions: %d, %d", elementResizer.getTotalWidth(), elementResizer.getTotalHeight()));
        System.out.println(String.format("element visible dimensions: %d, %d", elementResizer.getVisibleWidth(), elementResizer.getVisibleHeight()));

        // do something with the image inside the resized element
    }
}
// at this point everything is reverted to the original state

Capturing and validating images

Dollarx offers the ability to capture an image(ie. screenshoot) of a Path element, and asserting it looks as expected. All the functionality is under SingltonBrowserImage and Images .

It has separate hanling for HTML 5 canvas elements, which allows to download just the image data for that element, thus is more optimized. It also supports capturing an the source of and HTML img element from its URI.

Displaying an image of an element

It is possible to capture and display the image for a given element in a separate window. Note that this does not work well as an evaluation within the debugger. The classes that deal with images are:

Example:

Path map = div.withClass("gm-style");
SingltonBrowserImage mapImage = new SingltonBrowserImage(map);
mapImage.show();

SingltonBrowserImage mapImage = new SingltonBrowserImage(canvas);
// note that show() would also work, but showCanvas should be significantly faster for small elements
mapImage.showCanvas();

Capturing a reference image to a PNG file

Typically, we want to capture a reference image, and then, in our test, assert that our image is similar to the one we previously captured. So, to capture an image:

File outFile = new File("reference.png");
SingltonBrowserImage mapImage = new SingltonBrowserImage( div.withClass("gm-style"));
mapImage.captureToFile(outFile);

In case we want to capture an image from the source of an HTML ‘img’ element, the code would look like:

import static com.github.loyada.jdollarx.BasicPath.image;
import static com.github.loyada.jdollarx.BasicPath.occurrenceNumber;

File outFile = new File("reference.png");
SingltonBrowserImage mapImage = new SingltonBrowserImage( occurrenceNumber(10).of(image));
mapImage.captureImgSourceToFile(outFile);

Validating an image against a reference image

This assertion comes in two flavors:

The fuzzy comparison currently uses a simplistic algorithm (transform color space, check weighted difference and normalize it).

Dollarx also supports providing a “filter image” as a reference to the assertion. This image highlights the areas of interest in the image that we want to focus on in the assertion. That allows to ignore areas that either cannot be asserted, or areas that have no useful information. This improves the assertions significantly, and is highly recommended.

  • fuzzy assertion - see SingltonBrowserImage.assertImageIsSimilarToExpectedWithFilter and ImageComparator.verifyImagesAreSimilarFilteringInterestingAreas
  • strict assertion - see ImageComparator.verifyImagesAreEqualFilteringInterestingAreas.

As a starting point I recommend creating the “filter image” by processing the reference image with a Canny edge detector, followed by dilation. Here is an example:

Reference image:

_images/chart-ref.png

Filter image:

_images/filter-for-chart.jpg

The assertions will ignore any of the locations that are not highlighted in the “filter image”, so that there is less “noise” in the comparison.

In case the assertion fail you can capture the error image that highlights the locations of errors:

  • ImageComparator.getErrorsImage -
  • ImageComparator.getErrorImageForSimilarity

For example, for the example above, let’s say the actual image was :

_images/chart-actual.png

Then the error image is:

_images/chart-error.png

Supported image captures

The classes above support 3 types of image captures/validations:

  • Standard image capture - captures the entire screen, then crops it to the relevant section.
  • Canvas element - more efficient, since it captures only the wanted element.
  • The source of an HTML img element - by downloading it from the URI specficied in the “src” attribute. Typically (assuming the static resources are local in your tests) this will be more efficient than capturing the entire browser.

Temporarily make an element invisible

Sometimes we may want to assert an image capture of an element/page against an expected reference, while ignoring certain parts (ie. elements). This could be, for example, because different configurations or browsers render fonts differently, which may invalidate our assertion. To achieve this, use SingltonBrowserImage.Obscure . This class temporarily obscure the given elements, allowing you to do what you need, and then revert back to the original style.

For example(taken from ObscureExample.java in the tests) :

Path firstJavaSnippet = firstOccurrenceOf(div.withClass("highlight-java"));
assertThat(firstJavaSnippet, isDisplayed());

try (Obscure obscure = new Obscure(firstJavaSnippet)) {
  assertThat(firstJavaSnippet, isNotDisplayed());
  assertThat(obscure.getObscuredElements().size(), is(1));

  // we can now validate that the page ia pixel-perfect
}

// all back to normal
assertThat(firstJavaSnippet, isDisplayed());