Comparing images in Selenium

Many a time, our tests need image-based comparison. For example, verifying whether correct icons are displayed, verifying whether correct images are displayed in web pages, or comparing the baseline screen layout with the actual layout.

Selenium WebDriver does have features to capture screenshots or images from the application under test; however, it does not have the feature to compare the images.

In this recipe, we will create an extension class to compare images and use it in our Selenium tests.

Getting ready

Set up a new Java project for the CompareUtil class. This class will be used by Selenium tests as an extension to compare images.

How to do it...

Let's implement the CompareUtil class with a method to compare two image files, as shown in the following code:

package com.secookbook.examples.chapter09;

import java.awt.Image;
import java.awt.Toolkit;
import java.awt.image.PixelGrabber;

public class CompareUtil {

  public enum Result {
    Matched, SizeMismatch, PixelMismatch
  };

  public static Result CompareImage(String baseFile, String actualFile) {
    Result compareResult = Result.PixelMismatch;
    Image baseImage = Toolkit.getDefaultToolkit().getImage(baseFile);
    Image actualImage = Toolkit.getDefaultToolkit().getImage(actualFile);
    try {
      PixelGrabber baseImageGrab = new PixelGrabber(baseImage, 0, 0, -1,
          -1, false);
      PixelGrabber actualImageGrab = new PixelGrabber(actualImage, 0, 0,
          -1, -1, false);

      int[] baseImageData = null;
      int[] actualImageData = null;

      if (baseImageGrab.grabPixels()) {
        int width = baseImageGrab.getWidth();
        int height = baseImageGrab.getHeight();
        baseImageData = new int[width * height];
        baseImageData = (int[]) baseImageGrab.getPixels();
      }

      if (actualImageGrab.grabPixels()) {
        int width = actualImageGrab.getWidth();
        int height = actualImageGrab.getHeight();
        actualImageData = new int[width * height];
        actualImageData = (int[]) actualImageGrab.getPixels();
      }

      if ((baseImageGrab.getHeight() != actualImageGrab.getHeight())
          || (baseImageGrab.getWidth() != actualImageGrab.getWidth()))
        compareResult = Result.SizeMismatch;
      else if (java.util.Arrays.equals(baseImageData, actualImageData))
        compareResult = Result.Matched;

    } catch (Exception e) {
      e.printStackTrace();
    }
    return compareResult;
  }
}

How it works...

The CompareUtil class uses the java.awt.Image namespace to work with images. The CompareImage() method takes the path of the base file and the actual file as an argument. It then retrieves these images to the Image class:

Image baseImage = Toolkit.getDefaultToolkit().getImage(baseFile);
Image actualImage = Toolkit.getDefaultToolkit().getImage(actualFile);

Finally, it uses the PixelGrabber class to get the pixels from these images to an array, as shown in the following code:

PixelGrabber baseImageGrab = new PixelGrabber(baseImage, 0, 0, -1, -1, false);
PixelGrabber actualImageGrab = new PixelGrabber(actualImage, 0, 0, -1, -1, false);

int[] baseImageData = null;
int[] actualImageData = null;

if(baseImageGrab.grabPixels()) {
    int width = baseImageGrab.getWidth();
    int height = baseImageGrab.getHeight();
    baseImageData = new int[width * height];
    baseImageData = (int[])baseImageGrab.getPixels();
}

if(actualImageGrab.grabPixels()) {
    int width = actualImageGrab.getWidth();
    int height = actualImageGrab.getHeight();
    actualImageData = new int[width * height];
    actualImageData = (int[])actualImageGrab.getPixels();
}

The images are first tested for size mismatch, and then for pixel mismatch, using the following code:

if ((baseImageGrab.getHeight() != actualImageGrab.getHeight()) || (baseImageGrab.getWidth() != actualImageGrab.getWidth()))
    compareResult = Result.SizeMismatch;
else if(java.util.Arrays.equals(baseImageData, actualImageData))
    compareResult = Result.Matched;

The following code is a sample test, comparing the layout of the application being tested with a base layout captured from an earlier release:

package com.secookbook.examples.chapter09;

import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.*;
import org.apache.commons.io.FileUtils;
import org.junit.*;
import static org.junit.Assert.*;
import java.io.File;

public class BmiCalculatorTest {

  private WebDriver driver;

  @Before
  public void setUp() throws Exception {
    // Create a new instance of the Firefox driver
    driver = new FirefoxDriver();
  }

  @Test
  public void testBmiCalculatorLayout() throws Exception {

    String scrFile = "c:\screenshot.png";
    String baseScrFile = "c:\baseScreenshot.png";

    // Open the BMI Calculator Page and get a Screen Shot of Page into a
    // File
    driver.get("http://dl.dropbox.com/u/55228056/bmicalculator.html");
    File screenshotFile = ((TakesScreenshot) driver)
        .getScreenshotAs(OutputType.FILE);
    FileUtils.copyFile(screenshotFile, new File(scrFile));

    // Verify baseline image with actual image
    assertEquals(CompareUtil.Result.Matched,
        CompareUtil.CompareImage(baseScrFile, scrFile));

  }

  @After
  public void tearDown() throws Exception {
    // Close the browser
    driver.quit();
  }
}

There's more...

The following code is the C# implementation of CompareUtil. You can use this class for Selenium tests created with .NET bindings:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;

namespace CompareUtil
{
  public class CompareUtil
  {
    public enum Result { Matched, SizeMismatch, PixelMismatch };

    public static Result CompareImage(string baseFile, string actualFile)
    {
      Result result = Result.Matched;

      Bitmap baseBmp = (Bitmap)Image.FromFile(baseFile);
      Bitmap actBmp = (Bitmap)Image.FromFile(actualFile);

      if (baseBmp.Size != actBmp.Size)
        result = Result.SizeMismatch;
      else
      {
        int height = Math.Min(baseBmp.Height, actBmp.Height);
        int width = Math.Min(baseBmp.Width, actBmp.Width);

        bool are_identical = true;
        for (int x = 0; x <= width - 1; x++)
        {
          for (int y = 0; y <= height - 1; y++)
          {
            if (baseBmp.GetPixel(x, y).Equals(actBmp.GetPixel(x, y)))
            {
            }
            else
            {
              are_identical = false;
            }
          }
        }
        if (are_identical == true)
          result = Result.Matched;
        else
          result = Result.PixelMismatch;
      }

      return result;
    }
  }
}

See also

  • The Capturing screenshots with Selenium WebDriver recipe in Chapter 4, Working with the Selenium API
  • The Capturing screenshots of elements in the Selenium WebDriver recipe
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.118.142.250