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
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
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
manager fixture takes the
driver fixture value and yields an object of
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
driver instance, we are now using the earlier written
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.
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
It yields this 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.