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