Transcripted Summary

So far in this course we have been running test cases individually. However, at work we often have to run a suite of related cases together.

Applitools SDK gives us the flexibility to do this by setting a property on the eyes instance, called BatchInfo.

Let's see an example of this.

Let's assume this is our application under test.



Here we have a sample table with some dummy user data.

Assume that we want to test a sorting based on each column header (such as first name and last name, et cetera) works fine visually. All these cases should logically be part of the same test module or class.


Let's dive into how we can set these so that they are part of a single batch.

I have refactored the code to make it much easier to work with.


# Example Code – eyes_manager.py

from applitools.common import BatchInfo
from applitools.selenium import Eyes
from automation.config.base import APPLITOOLS_API_KEY

class EyesManager:

    def __init__(self, driver):
        self.app_name = None
        self.driver = driver
        self.eyes = self.initialize_eyes()

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

    def set_app_name(self, app_name):
        self.app_name = app_name

    def set_batch(self, batch_name):
        if batch_name:
            batch_info = BatchInfo(batch_name)
            self.eyes.batch = batch_info

    def validate_window(self, tag=None, full_page=False):
        if full_page:
            self.eyes.force_full_page_screenshot = True
            self.eyes.check_window(tag=tag)

    def validate_element(self, element, tag=None):
        self.eyes.check_region(element, tag=tag)

    def validate_frame(self, frame_reference, region, tag=None):
        self.eyes.check_region_in_frame(frame_reference, region, tag=tag)

    def open_eyes(self, test_name):
        self.eyes.open(self.driver, self.app_name, test_name=test_name)

    def close_eyes(self):
        self.eyes.close()

Let's go over what has changed.

We have moved all Eyes-related code into a class called EyesManager.

This class accepts the driver instance and has certain methods to set up the eyes instance and other related checkpoints that we have been seeing earlier.

The important change to note here is the set_batch function, which takes the name of the batch (batch_name) and creates an instance of the BatchInfo class that is batch_name and sets it into the eyes object that we are working with.

Setting this property on the eyes instance is how we instruct Applitools that we want a set of test cases to be batched into a single suite.


Our conftest.py file has also changed.

# Example Code - conftest.py


import pytest
from selenium import webdriver
from automation.core.eyes_manager import EyesManager

@pytest.fixture(scope='module')

def manager(driver):
    eyes_manager = EyesManager(driver)
    yield eyes_manager

@pytest.fixture(scope='module')

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

We have introduced a new module scoped fixture called manager.

The manager fixture takes the driver fixture value and yields an object of EyesManager.


Now let's take a look at the tests.


# Example Code – sortable_data_table_test.py


import pytest
from automation.page_objects.the_internet.tables.sortable_tables import SortableTablePage

@pytest.fixture(scope='module')

def setup_suite(manager, driver):
    app_name = 'the-internet'
    app_under_test = 'https://the-internet.herokuapp.com/tables'
    manager.set_batch('sortable table test suite')
    manager.set_app_name(app_name)
    driver.get(app_under_test)
    driver.maximize_window()

@pytest.fixture(scope='function', autouse=True)

def setup_eyes(request, setup_suite, manager):
    test_name = request.function.__name__
    manager.open_eyes(test_name)
    yield setup_eyes
    manager.close_eyes()

def test_sort_by_first_name(manager):
    page = SortableTablePage(manager.driver)
    page.sort_by_first_name()
    manager.validate_window(tag='by_first_name')

def test_sort_by_last_name(manager):
    page = SortableTablePage(manager.driver)
    page.sort_by_last_name()
    manager.validate_window(tag='by_last_name')

We have two tests in this module, which click on the first name and the last name header and then take a screenshot to compare against the baseline.

Also notice that instead of eyes and driver instance, we are now using the earlier written manager fixture.

Additionally, we have moved all the behavior for this specific webpage into its own dedicated page object class (SortableTablePage), that functions to perform the action. This makes the code nicely organized and cleaner.


To make all this work, we have added a couple of additional fixtures in the test file.

The first is setup_suite, which will be run once for the entire module.

It sets batch name (using set_batch) as “sortable table test suite”.

Using the earlier added function in EyesManager, we also set the app_name and the initialization code to launch the application under test (app_under_test) in a maximized form.


Since we want to be able to pass the test name to open the Eyes function, we have another helper-fixture (called setup_eyes) which gets the name of the test function being executed from Pytest's request fixture.

The request object has a lot of context about the test that is being executed.

  • We get the name of the test function using this

  • This fixture also opens the Eyes (open.eyes) with our given test_name

  • It yields this object (yield setup_object)

  • Then closes the Eyes (close.eyes) once every test is executed

This is a function level fixture and hence is executed for every test function.


Let's run this test file.

So, you can see Pytest has run both the cases.

Let's take a look into Applitools site for results.



As we can see, instead of creating different test suites for each of the individual cases, we have a single test suite with the name that was provided and the two cases nicely organized.



Resources