Migrating code to use the Ultrafast Grid
This article describes how to adapt an Eyes visual test that was created before the availability of the Ultrafast Grid to enable use of the Ultrafast Grid. The adapted code is based on the Runner API. Once your test uses this API, you can easily switch between running with or without the Ultrafast Grid as required. The required changes are limited to the setup and wrap up code, but do not impact the test code where images are captured and checked.
The article assumes that you have a general knowledge of working with the Eyes SDK and what the Ultrafast Grid is. It focuses on introducing new concepts and the changes you need to make to existing code so that it can use the Ultrafast Grid.It includes a concise example, designed to get you up and running converting existing code to use the Ultrafast Grid as quickly as possible. For an overview of what the Ultrafast Grid can do and how it does it see the article Introduction to the Ultrafast Grid. The article Ultrafast Grid configuration is more expansive than the current article, describing in more detail the various options that are available.
Overview
- Runner interface: This object manages access by multiple Eyes instances to the Ultrafast Grid and the Eyes Server. There are two types of runners, one for working with the Ultrafast Grid and one for working without it.
- Configuration class: An object that supports configuration of the Ultrafast Grid and is also useful for applying a common configuration on multiple Eyes instances.
Converting a legacy test suite to use these new concepts includes the following steps:
- Before any test is run:
- Create a runner object using the
visualgridrunner
constructor to run with the Ultrafast Grid or with theclassicrunner
constructor to run without the Ultrafast Grid. - If using the Ultrafast Grid, define one or more browser configuration(s) using the
configuration
class methodsconfiguration$addbrowser
,configuration$adddeviceemulation
orconfiguration$addbrowsers
. - Set other global configurations that you want to apply to all tests.
- For each test:
- Create the Eyes instance, passing the runner object.
- If you previously set the server URL by passing it to the Eyes constructor, remove this parameter and set it when setting the global configurations.
- Replace calls to the Eyes
eyes$close
method with the methodeyes$closeasync
. - After all the tests have been executed, use the method
visualgridrunner$getAllTestResults
to wait for all the tests to complete and to return all of the test results.
The sections below explain the above steps in more detail and illustrate them with a simple example.
Example test and how to migrate to it
Each of these are discussed in the sections that follow., the full example which appears at the end of the article are based on TestNG (Java), NUnit(C#) and Mocha (JavaScript).
The Runner and Configuration Objects
- runner This object coordinates multiple tests, each running with it's own Eyes instance. The object also collects the test results and makes them available when all the tests are complete. You need one runner instance for the entire test suite.
- suiteconfig This object represents all the Ultrafast Grid and Eyes configuration values. Before any tests starts, you set it up with default values and it is then applied to each test before the test starts.
Set up the test suite
- Create an instance of the class
VisualGridRunner
. - Define which browser configurations the Ultrafast Grid should render.
- Set up any global configuration values that apply to all the tests.
Creating the VisualGridRunner
object
-
visualgridrunner
: To use the Ultrafast Grid. -
classicrunner
: When not using the Ultrafast Grid.
The type of runner you pass to the Eyes constructor when creating it determines if its checkpoints are rendered using the Ultrafast Grid or not.
The
RunnerOptions
object passed to the VisualGridRunner
constructor is used to configure the runner. The example shows the method RunnerOptions.testConcurrency
being passed. This option is used to limit the maximum number of Eyes tests that the runner will run simultaneously.
Increasing the concurrency value allows your test suite to run faster, but the maximum number of tests that can run simultaneously depends on your Eyes plan, if concurrency has been allocated at a team level, and what other tests are being run on your account at the same time.
The integer value passed to the constructor limits the maximum number of Eyes tests that interact concurrently. Increasing the concurrency value can make your test suite run faster, but the maximum possible concurrency depends on your Eyes plan.
The Configuration object
The configuration
object stores the required values of all the configuration values. The following snippet shows this object being created and configured with Ultrafast Grid browser configurations and Eyes configuration values that are typically common for all tests.
When each test is set up, as demonstrated in the
method below, the Configuration object is used to initialize the Eyes object.
Note the use of the fluent API style to simplify setting up multiple configuration values.
The example demonstrates the use of the method
addbrowser
to configure for which desktop browsers, emulated and simulated devices the Ultrafast Grid should generate images for each of the checkpoints. You can read more about these methods and their variations in the article Ultrafast Grid configuration..
You can also use the
Configuration
object to set up
Eyes
configuration values that need to be applied to the entire test suite.The
Configuration
object supports most of the
setXXX methods exposed by the
Eyes
object. For an overview of common test suite level configuration values see
Test suite configuration.
Set up before each test
The snippet below shows how to set up the Eyes instance and web driver objects that are required for each test. For conciseness, this example is not multithreaded and uses class fields for the Eyes and web driver objects. These are set with new instances for each test. If your test is multithreaded, then each thread must have its own instance of the Eyes and web driver objects.
-
Create the Eyes instance by calling the constructor, passing it the runner object that was created in the
beforetestsuite
method. Passing a runner of type visualgridrunner indicates to Eyes that this test should run using the Ultrafast Grid. If a different type of runner is passed, then the test will run without the Ultrafast Grid.In previous versions of the SDK, if you used a private cloud or an on-premise server, you could pass the URL of the cloud or server when instantiating the Eyes object. This is no longer supported, and you should set it using the
configuration$setserverurl
method on the suiteconfig object in thebeforetestsuite
method as shown in the example above. - Use the Eyes
eyes$setconfiguration
method, passing it the suiteconfig object to apply the test suite default configuration values to the Eyes instance. Note that this method sets all the configuration values, either to the values defined explicitly or to the SDK default values. We will see in the next section how you can change only specific configuration values. - If in your code you use one or more eyes.setXXX commands for the initial configuration of the Eyes instance, then it is recommended that you replace these calls with the equivalent calls to the global configuration object as shown in the method
beforetestsuite
, since the eyes.setXXX might be deprecated at some point.
The test
The following snippet shows some typical test code, which first does some test specific configuration and then executes the test:
- A test may have some test-specific configuration. For example, we configured the application name in the global configuration since it is common to all the tests. Now in the test we need to configure the test name.
- Call
eyes$getconfiguration
to get the current configuration values. - Make changes to the current configuration.
- Set the updated configuration using the method
eyes$setconfiguration
. - Open the Eyes session by calling the method
eyes$open
.In legacy code, this method took as a parameter the application name, test name and viewport size. If these are now set in the Configuration object, then you don't need to pass them as parameters, although you can do so if you want to override the default set in the configuration.
Wrap up after each test
The snippet below shows the typical content for a method that wraps up after every eyes test.
- Call the eyes method
eyes$closeasync
instead of theeyes$close
method. Calling theeyes$closeasync
method signifies the end of the checkpoints, but unlike callingeyes$close
, the method does not wait for results, so execution can proceed immediately to the next test. -
If your test infrastructure indicates that the test terminated abnormally, then you should call
eyes$abortifnotclosed
instead ofeyes$closeAsync
.
Wrap up the test suite and obtain the test results
After all the tests have been closed, you wait for all the test processing to complete and obtain all of the tests results using the method visualgridrunner$getalltestresults
as shown in the snippet below.
-
The call to
visualgridrunner$getalltestresults
returns an iterator that you can use to get the test results of each browser configuration of each test. For example, if the test is configured with five browser configurations and the test method is called 10 times, you will get 50 test results. - The object returned by the iterator,
testResultContainer
, supports the following methods or properties: -
testResultContainer$getexception$morp
: Returns a non null status value if a failure prevented the test from completion. testResultContainer$gettestresults$morp
. Returns atestresults
object which contains the results of each test or a null if an exception occurred and test results are not available.
The getAllTestResults()
method takes an optional Boolean parameter that determines what happens if Eyes finds mismatches in the test. If the parameter is true
, or no parameter is passed, then an exception is raised is any test had a mismatch, was missing or if there were new checkpoints. Typically, if you want your test framework to capture and handle the exceptions in the same way as any other assertion failure in your tests then pass "true
. If you want to generate a custom report or otherwise process the test result programmatically upon test completion then pass false
.
Full Example
The code below shows an example of a visual test using the visualgridrunner
, and configuration
object to use Eyes with the Ultrafast Grid.