Advanced Configuration
General Configuration
Configuring the Server URL
By default, the SDK communicates with the Applitools public Eyes cloud server, located at https://eyesapi.applitools.com
.
If you have a dedicated cloud or an on-premise server, you can configure a different Eyes server URL using the following code:
eyes.configuration.set_server_url("https://company.applitools.com")
Configuring a Proxy
If your company's network requires requests to go through a corporate proxy, you can configure it using the following code:
from applitools.common import ProxySettings
eyes.configuration.set_proxy("http://proxy.url")
eyes.configuration.set_proxy(ProxySettings("host",8080,"username","password"))
Integrating with Functional Tests
You can integrate an Eyes test with a functional test that you have created in a different system.
Every call to eyes.open
and eyes.close
defines a test in Applitools Eyes, and all the calls to eyes.check
between them are called "steps". In order to get a test structure in Applitools that corresponds to the test structure in your functional test, you should open/close tests in every test
call.
For example, when running with pytest as a test runner fixtures can be defined to do this automatically. This example will produce two tests, named "test login page" and "test app".
import pytest
from playwright.sync_api import sync_playwright
from applitools.playwright import Eyes, Target, RectangleSize
@pytest.fixture(scope="session")
def playwright_chromium():
with sync_playwright() as playwright:
yield playwright.chromium.launch()
@pytest.fixture
def page(playwright_chromium):
yield playwright_chromium.new_page()
@pytest.fixture
def eyes(page, request):
eyes = Eyes()
test_name = request.node.name.replace('_', " ")
eyes.open(page, "my app", test_name, RectangleSize(1280, 720))
yield eyes
eyes.close()
def test_login_page(page, eyes):
page.goto("https://demo.applitools.com")
eyes.check("login page", Target.window().fully())
page.locator("#username").type("user")
page.locator("#password").type("pa$$w0rd")
eyes.check("credentials entered", Target.window().fully())
def test_app(page, eyes):
page.goto("https://demo.applitools.com/app.html")
eyes.check(Target.window().fully())
Here is modified example that executes same tests in three parallel UFG browsers:
import pytest
from playwright.sync_api import sync_playwright
from applitools.playwright import Eyes, Target, RectangleSize, VisualGridRunner, \
RunnerOptions, BrowserType, ChromeEmulationInfo, \
DeviceName, ScreenOrientation
@pytest.fixture(scope="session")
def playwright_chromium():
with sync_playwright() as playwright:
yield playwright.chromium.launch()
@pytest.fixture(scope="session")
def runner():
runner = VisualGridRunner(RunnerOptions().test_concurrency(10))
yield runner
runner.get_all_test_results()
@pytest.fixture
def page(playwright_chromium):
yield playwright_chromium.new_page()
@pytest.fixture
def eyes(runner, page, request):
eyes = Eyes(runner)
configuration = eyes.configuration
configuration.add_browser(1280, 720, BrowserType.CHROME)
configuration.add_browser(1280, 720, BrowserType.FIREFOX)
configuration.add_browser(
ChromeEmulationInfo(DeviceName.iPhone_11_Pro, ScreenOrientation.PORTRAIT)
)
test_name = request.node.name.replace('_', " ")
eyes.open(page, "my app", test_name, RectangleSize(1280, 720))
yield eyes
eyes.close_async()
def test_login_page(page, eyes):
page.goto("https://demo.applitools.com")
eyes.check("login page", Target.window().fully())
page.locator("#username").type("user")
page.locator("#password").type("pa$$w0rd")
eyes.check("credentials entered", Target.window().fully())
def test_app(page, eyes):
page.goto("https://demo.applitools.com/app.html")
eyes.check(Target.window().fully())
Organizing Tests in Batches
To manage how visual tests are grouped into batches, you can use the following methods:
Method 1: Environment Variable
Run all the processes that execute Playwright with the same value for APPLITOOLS_BATCH_ID
. For example, run tests with pytest with the same randomly generated UUID:
#! Unix based machines:
APPLITOOLS_BATCH_ID=`uuidgen` pytest
You can control the batch name displayed in the Test Manager, for example:
export APPLITOOLS_BATCH_ID=`uuidgen`
export APPLITOOLS_BATCH_NAME="Login tests"
pytest
Method 2: Set Batch
Provide all Eyes instances with the same value for batch ID in configuration. For example:
from applitools.playwright import BatchInfo
batch_info = BatchInfo("My tests batch").with_batch_id("random-batch-id")
configuration.set_batch(batch_info);
Test Configuration
Test Properties
You can provide additional information about each test in custom fields, which can then show up in Test Manager in their own column.
This is done by calling set_properties
on the configuration, and providing it with an array of properties with the structure {name, value}
. For example:
configuration = eyes.configuration
configuration.add_property("my custom property", "some value");
Test Results
The results of the test can be consumed as the return value from eyes.close
. Here's an example for creating a formatted output string out of the TestResults
object:
def format_test_results(results):
formatted_steps = ", ".join(format_step(step) for step in results.steps_info)
return """Test name: {name}
Test status: {status}
URL to results: {url}
Total number of steps: {steps}
Number of matching steps: {matches}
Number of visual diffs: {mismatches}
Number of missing steps: {missing}
Display size: {host_display_size}
Steps: """.format(**vars(results)) + formatted_steps
def format_step(step_info):
if step_info.is_different:
status = "Diff"
elif not step_info.has_baseline_image:
status = "New"
elif not step_info.has_current_image:
status = "Missing"
else:
status = "Passed"
return "{} - {}".format(step_info.name, status)
Stitch Mode
In Applitools Eyes, when taking a full-page screenshot, the SDK captures multiple screenshots of the viewport at different positions on the page and then combines them into a single image. This process is known as "stitching."
The stitch mode determines how images are pasted together:
-
Scroll stitch mode - This mode simulates scrolling behavior by capturing the viewport screenshot and then scrolling the page to capture additional screenshots at calculated positions. The screenshots are stitched together to create a complete image of the entire page. However, one limitation of this mode is that if the page responds to scroll events and changes its visual appearance, it might result in inconsistencies between the stitched screenshots.
-
CSS stitch mode - In this mode, the page is moved by manipulating the CSS property
transform
on the HTML element. The SDK changes thetranslate(x, y)
values to capture different portions of the page. This method is not affected by scroll events, making it more reliable in scenarios where the page dynamically adjusts its layout during scrolling.
The default stitch mode is Scroll
. To change it:
from applitools.playwright import StitchMode
eyes.configuration.set_stitch_mode(StitchMode.CSS)
eyes.configuration.set_stitch_mode(StitchMode.SCROLL)
Stitch Overlap
The stitch overlap refers to the length of the intersecting area between two screenshots that are stitched together to create a full-page screenshot. It represents the amount of overlapping pixels between adjacent images. The stitch overlap is particularly useful when dealing with fixed elements, such as a footer, that appear in each sub-screenshot. By setting a stitch overlap larger than the size of the footer, you can ensure that the footer is excluded from each individual screenshot and only appears once at the bottom of the full-page screenshot.
The default stitch overlap is 50 pixels. You can change the stitch overlap by using the set_stitch_overlap
method as shown in the following example:
eyes.configuration.set_stitch_overlap(60)
Match Level
The match level determines how Eyes compares the checkpoint image with the baseline image.
The following match levels are available:
-
Strict - (Default) Detects changes in text, font, color, graphics, and position of elements. It aims to detect differences that are visible to the human eye while ignoring differences in pixel values that are platform dependent due to the rendering software and hardware.
-
Layout - Identifies changes in various page elements, such as text, images, buttons, and columns, and verifies that the relative positions of these elements are consistent. This match level can detect elements that have appeared, disappeared, or moved. With this match level, Eyes ignores differences in the actual content text and graphics, color, and other style changes. This level is useful for pages with dynamic content, language localization, and cross-environment testing where a single baseline is used for multiple execution environments.
-
Ignore colors - Similar to the strict match level but ignores changes in colors. It is effective when your content is static but the color varies, for example if there are buttons or screen elements that can appear in a variety of colors.
-
Exact - Pixel-to-pixel comparison of the checkpoint and baseline images. It is sensitive to differences such as rendering anomalies that are not visible to the human eye. It is not recommended for ordinary verification purposes.
-
Dynamic - Recognizes defined text patterns such as a date, email address, or URL. For details, see Dynamic text match level
For more information, see How to use Eyes match levels.
The default match level is Strict
.
To change the match level for the rest of the execution:
from applitools.playwright import MatchLevel, Target
eyes.configuration.set_match_level(MatchLevel.LAYOUT)
eyes.check(Target.window().layout())
eyes.check(Target.window().strict())
eyes.check(Target.window().exact())
eyes.Check(Target.window().dynamic())
Ignore Displacements
Use ignore displacements to hide differences that arise from content whose position on the page has changed. For example, if text is longer in the checkpoint or the size of an image has changed, if IgnoreDisplacements
is set to true
, unchanged content that has shifted position because of the changed text or image will not be marked as a difference.
The default is false
.
For more information, see Hide displacement diffs tool. To change the match level for the rest of the execution:
# For the rest of the execution
eyes.configuration.set_ignore_displacements(True)
To change the match level for a single checkpoint:
eyes.check(Target.window().ignore_displacements())