Transcripted Summary

In this tutorial you will learn how to write your first visual test using Applitools Selenium Python SDK.

Before that, let's take a look at the application under test.



We will be using the Automation Bookstore site created by Angie Jones in her Visual Testing with Java course on Test Automation University.

The site is a simple bookstore with a list of some great books on testing and automation and some of its capabilities are as follows.

You can search the desired book based on the author name.

So, let's say I want to search for the book written by “James”.



Then I can see that he has written How Google Tests Software and it's available in this bookstore.

I can also search based on the name of the book itself.

If I want to know how much the Agile Testing book costs, I can enter that and see the book in the store.

I can also give a partial name of the book and see what all books are available in the bookstore.

Let's say you want to assert that on searching for the book “Agile Testing” on the site we are only able to see the one book on the screen.



We could achieve this by writing a function to get all the elements under this parent and then see if our text is present in the list.

I have already gone ahead and written a Page Object class which does this.


class SearchPage:

    def __init__(self, driver):
        self.driver = driver

    def filter_books(self, search_text):
        element = self.driver.find_element_by_id('searchBar')
        element.send_keys(search_text)

    def verify_visible_books_by_title(self, expected_title):
        elements = self.driver.find_elements_by_css_selector( '#productList li a h2')
        for element in elements:
            if expected_title in element.text:
                return True
        return False

Here the verify_visible_books_by_title, expects an argument with the title name and then it iterates in all the available books and sees if our expected book (expected_title) is present in them.

Otherwise it returns False.

Here is a test method that does the same thing.


from assertpy import assert_that
from time import sleep

from automation.page_objects.search_page import SearchPage

def test_filter_book(eyes, driver):
    page = SearchPage(driver)
    page.filter_books('Agile')
    sleep(5)
    result = page.verify_visible_books_by_title('Agile Testing')
    assert_that(result).is_equal_to(True)

I have initialized the page Object (SearchPage) and I'm calling the filter_books function further by calling the simple assertion to verify_visible_books_by_title and then asserting the result.

Let's run this.

However, there are some problems with this assertion.



It is not very robust because it still would not verify that the other books are not displayed.

If you take a look at your DOM right now, all the other books are also present under this parent control.



Also, it does not verify other important details of the book, like the color of the cover, or the price.

All these elements or details are missed while we are trying to verify this.

For such cases Applitools visual assertion can give a lot of value with a very simple assertion that we can do.

Let's see this in action.

We have modified the framework to use pytest framework. I have added a bunch of fixtures to set up WebDriver, get the Eyes instance with the API key and some other utility functions already.



Before every test function execution we will initialize the WebDriver, launch the app and after the test is executed, we would be creating the driver instance.

And likewise, for the eyes instance.

Let's see how we can add a simple function to validate the whole window using Applitools.

Let's add a new function to validate the whole window in the conftest.py file.

We’ll add a function validate_window and pass it the driver name, the eyes instance and the tag name. I'll explain what this tag means in just a minute.

To start validation of a particular window, we need to open eyes, perform the validation and then close the eyes instance. Let's add functions for this.

To open_eyes we need to pass it the driver instance and the eyes instance, which we have received from our test.

To open the Eyes on the eyes instance we need to call the open function and pass it the driver name that we have just received, the name of the app (APP_NAME) and the name of the test (test_name) that is going to get executed. Let's pass this as a default parameter.

I have already written the get_test_name function, which uses the inspect module to get the name of the test function.

Let's close the eyes instance. Nice.

Once the eyes are open on the particular eyes instance we can call our check_window function and pass it the tag that we received from the test function.


# Example Code – conftest.py

import pytest
from applitools.selenium import Eyes
from selenium import webdriver
from automation.config.base import APPLITOOLS_API_KEY

APP_NAME = 'automation_bookstore'
APP_UNDER_TEST = 'file:///Users/gaurav/Self/Dev/automated-visual-testing/website/index.html'

@pytest.fixture(scope='function')

def driver():
    driver = webdriver.Chrome()
    driver.get(APP_UNDER_TEST)
    yield driver
    driver.quit()

@pytest.fixture(scope='function')

def eyes():
    eyes = initialize_eyes()
    yield eyes

def initialize_eyes():
    eyes = Eyes()
    eyes.api_key = APPLITOOLS_API_KEY
    return eyes

def validate_window(driver, eyes, tag):
    open_eyes(driver, eyes)
    eyes.check_window(tag=tag)
    close_eyes(eyes)

def open_eyes(driver, eyes):
    eyes.open(driver, APP_NAME, test_name=get_test_name())

def get_test_name():
    import inspect
    return inspect.stack()[3].function

def close_eyes(eyes):
    eyes.close()

Now let's add this validate_window function in our search_test.

Pass it the driver instance, eyes instance and a tag ("filter_text"). Here tag is a way to specify a unique name for this assertion, which we can visualize in the Applitools dashboard.


# Example Code – search_test

from assertpy import assert_that
from automation.tests.conftest import open_eyes, validate_window, close_eyes
from automation.page_objects.search_page import SearchPage

def test_filter_book(eyes, driver):
    page = SearchPage(driver)
    page.filter_books('Agile')
    validate_window(driver, eyes, tag='filter_text')

Let's remove these earlier assertions.

And run the test.



We see that the test passed.

Let's see this in Applitools.

Here we have the Applitools Eyes Manager and we can see the results in Applitools website.



Here you can see certain sections like the test that was just executed and see the snapshot that was captured.

Since the snapshot looks okay to me, I can give it a thumbs up and save this as a baseline.



Sweet.

However, what if we changed the book name to be passed to the site?

Let's do that (changing the filter_books value to “James” instead of “Agile”) and run the test again.

This time we see a different book on the screen as expected, the test failed.



If you take a look at the exception trace, we see Applitools DiffsFoundError and a URL for the Applitools website with the test results.

This time in the Applitools site, we can see the test is marked as “Unresolved”.

And if we open it, we can see that it has captured the difference between the original baseline and the new one.



Since this is not a change that we are expecting and looks like a visual bug, we can mark it as failed and the test is marked as failed.



Resources