Image Verification Made Effortless with Python and Selenium UI Automation

Shohanur Rahman
3 min readAug 11, 2023

Are you tired of the hassle of manually comparing images to ensure they match? Look no further! In this user-centric guide, I’ll guide you through my journey of automating image verification using Python and Selenium UI automation.

This guide will walk you through my experience using Python and Selenium UI automation to:

  • Automatically compare images.
  • Calculate differences and determine matches.
  • Set an acceptable difference threshold.

Preparing the Stage

Before I jump into the code, let’s lay the foundation for our image verification journey:

  1. Expected vs. Actual: I’ll compare an “expected” image to an “actual” image. The expected image serves as our reference, while the actual image is produced during testing.
  2. View Types: I’ll explore different view types, such as “desktop” and “mobile,” to ensure consistent images across devices.
  3. Threshold: I’ll define a threshold for an acceptable percentage difference between images. Images within this threshold are deemed a match.

Step 1: Getting Ready

Let’s start by setting up the tools and environment for our image verification adventure:

I assume that you already have a dedicated Selenium setup and UI test suite.

  1. Install the Python Imaging Library (PIL) and Selenium UI automation package using pip:
pip install Pillow

Step 2: Automating Verification

My journey unfolds with the following automated process:

  1. Loop through each view type (e.g., desktop, mobile). I’ve taken a proactive approach by predefining the directories for both expected and actual screenshots. Additionally, I’ve carefully categorized the verification process into different view types, allowing us to easily extend the process to accommodate various view perspectives, such as “desktop” and “mobile.”
  2. By organizing the code in this loopable and repeatable manner, we ensure that the verification process can effortlessly adapt to the specific needs of each view type. This approach not only enhances code reusability but also simplifies the management of multiple view scenarios.
expected_screenshot_folder = 'expected_screenshots'
actual_screenshot_folder = 'test_screenshots'
view_types = ['desktop', 'mobile']
# ESTIMATED THRESHOLD
threshold = 2.51

for view_type in view_types:
expected_screenshot_filename = f'{view_type}_view_screenshot.png'
actual_screenshot_filename = f'{view_type}_view_screenshot.png'

3. Open expected and actual images.

      # OPEN THE EXPECTED IMAGE
expected_image_path = os.path.join(expected_screenshot_folder, expected_screenshot_filename)
expected_image = Image.open(expected_image_path)
# OPEN THE ACTUAL IMAGE
actual_image_path = os.path.join(actual_screenshot_folder, actual_screenshot_filename)
actual_image = Image.open(actual_image_path)

4. Calculate image differences. The first step, done with PIL, is like putting one picture on top of the other. The computer compares them pixel by pixel, checking where they’re not the same. Now, with PIL’s help, we want to understand how different these highlighted areas are in terms of overall size.

This gives us a number that tells us how different the two pictures are in terms of a percentage.

      # CALCULATE THE DIFFERENCE BETWEEN THE IMAGES
diff = ImageChops.difference(expected_image, actual_image)
print(diff.getdata())
# CALCULATE THE PERCENTAGE DIFFERENCE
percentage_diff = (sum(sum(pixel) for pixel in diff.getdata()) / (
255.0 * expected_image.width * expected_image.height)) * 100

5. Compute the percentage difference.

 # COMPARE THE PERCENTAGE DIFFERENCE WITH THE THRESHOLD
if percentage_diff <= threshold:
message = f"{view_type.capitalize()} view: Images match! Difference in Percentage: {percentage_diff:.2f}%"
print("Pass:", message)
assert True, message
else:
message = f"{view_type.capitalize()} view: Images do not match. Difference in Percentage : {percentage_diff:.2f}%"
print("Fail:", message)
assert False, message

6. Compare with the predefined threshold. This threshold is nothing but a percentage ratio that you are max accepted. Let’s say I take a screenshot. Is there some text or images that change with every re-run of the code? So I fixed an initial threshold of 2.5 (it works for my expected result). It could be changed depending on the requirements.

 if percentage_diff <= threshold:
message = f"{view_type.capitalize()} view: Images match! Difference in Percentage: {percentage_diff:.2f}%"
print("Pass:", message)
assert True, message
else:
message = f"{view_type.capitalize()} view: Images do not match. Difference in Percentage : {percentage_diff:.2f}%"
print("Fail:", message)
assert False, message

Step 3: Tidying Up

After the verification quest, it’s important to leave no trace:

  1. Close the actual image.
  2. Remove actual images (regardless of the outcome).
        finally:
# CLOSE THE ACTUAL IMAGE IF IT WAS OPENED
actual_image.close()
finally:
# REMOVE THE ACTUAL IMAGES REGARDLESS OF THE OUTCOME
for view_type in view_types:
actual_screenshot_filename = f'{view_type}_view_screenshot.png'
actual_image_path = os.path.join(actual_screenshot_folder, actual_screenshot_filename)
if os.path.exists(actual_image_path):
os.remove(actual_image_path)

Conclusion

In wrapping up, I want to emphasize that I’m on a continual journey of learning and improvement. The world of automation and coding is vast, and each day brings new insights and discoveries. While I’ve shared a snippet of my current understanding, I’m excited to further refine my skills and explore even more creative solutions.

Feel free to reach out on Linkedin if you have questions or need assistance. Happy coding!

--

--