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.
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.
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.